Linux *** 检测到 glibc *** free():下一个大小无效(正常):0x0a03c978 ***
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4980852/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
*** glibc detected *** free(): invalid next size (normal): 0x0a03c978 ***
提问by user614578
I'm writing a socket program to download images. The problem is that when I test my code on small pics like gif it works fine. But when I run it with JPG pics (bigger than GIF) I got the error message:
我正在编写一个套接字程序来下载图像。问题是当我在像 gif 这样的小图片上测试我的代码时,它工作正常。但是当我用 JPG 图片(比 GIF 大)运行它时,我收到了错误消息:
*** glibc detected *** /home/ubuntu/NetBeansProjects/myDownloader/dist/Debug/GNU-Linux-x86/mydownloader: free(): invalid next size (normal): 0x0a03c978 ***
Please see the code and I'll give more information about the error.
请查看代码,我将提供有关错误的更多信息。
FILE* pFile;
long lSize;
unsigned char* buffer;
size_t result;
FILE* combinedFile = fopen("mypic.jpg", "wb+");
for(i = 1; i <= numberOfPartitions; i++)
{
sprintf(filename, "part%d", i);
pFile = fopen(filename, "rb");
//obtain file size
fseek(pFile , 0 , SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
// allocate memory to contain the whole file:
buffer = (unsigned char*) malloc(sizeof(unsigned char) * (lSize + 1));
if(buffer == NULL)
{
fputs("Memory error", stderr);
exit(2);
}
// copy the file into the buffer:
result = fread(buffer, 1, lSize, pFile);
if(result != lSize)
{
fputs("Reading error", stderr);
exit(3);
}
else
{
unsigned char* temp = strstr(buffer, "\r\n\r\n");
temp = temp + 4;
int len = lSize - (temp - buffer);
//printf("i : %d len is : %d plen is %f\n",i,len,pLen);
if(i != numberOfPartitions)
fwrite(temp, 1, len - 1, combinedFile);
else
fwrite(temp, 1, len, combinedFile);
}
fclose(pFile);
printf("crash here\n");
free(buffer);
}
fclose(combinedFile);
I got the error from this part, as i said when the image size is small it works fine. But with bigger size it's broken! P.S: The program divided the pic into several files then re-combine it so the combining part is the one that causes the error.
我从这部分得到了错误,正如我所说,当图像尺寸小时它工作正常。但是更大的尺寸它坏了!PS:程序将图片分成几个文件然后重新组合它所以组合部分是导致错误的部分。
Any help will be very much appreciated since I've been stuck with this error for more than 3 days!
任何帮助将不胜感激,因为我已经被这个错误困住了 3 天多!
采纳答案by Jonathan Leffler
You don't verify that the fopen()
calls all succeed; this is a recipe for trouble.
您无需验证fopen()
调用是否全部成功;这是一个麻烦的秘诀。
You don't check the ftell()
gives you a plausible value in lSize
.
你不检查ftell()
给你一个合理的值lSize
。
You don't verify that the strstr()
operation actually finds the marker string. If it doesn't, it will return NULL and the following length operations are then bogus. But the error suggests that your code has written out of bounds, rather than just read data out of bounds.
您无需验证strstr()
操作是否确实找到了标记字符串。如果不是,它将返回 NULL 并且以下长度操作是假的。但该错误表明您的代码已越界写入,而不仅仅是越界读取数据。
You could declare the first four variables into the body of the loop instead of outside the loop.
您可以将前四个变量声明到循环体中,而不是在循环外。
You don't show the declaration of the variable filename
; could that be a char pointer with no space allocated? Or is it an array that is big enough?
您不显示变量的声明filename
;这可能是一个没有分配空间的字符指针吗?或者它是一个足够大的数组?
It is an odds-on bet that something has written beyond the end of some allocated space. It is not immediately obvious that there's anything wrong with this code, but the trouble could be elsewhere yet it is this code that suffers the effects of transgressions elsewhere. This is quite common with memory problems; the code that finds the problem isn't the code that causes it.
有一些东西已经写到某个分配空间的末尾之外,这是一个很有可能的赌注。这段代码有什么问题并不是很明显,但问题可能出在其他地方,但正是这段代码受到了其他地方违规的影响。这在内存问题中很常见;发现问题的代码不是导致问题的代码。
Does the malloc()
on your machine return null or a non-null pointer when you allocate zero bytes? Both are legitimate responses.
malloc()
当您分配零字节时,您的机器上是否返回空指针或非空指针?两者都是合法的回应。
If ftell()
returns -1, then malloc()
would allocate a buffer for 0 bytes, but the fread()
would attempt to read up to 4 GB of data, which might overflow the space. OTOH, if ftell()
fails, it is likely that fread()
will fail too.
如果ftell()
返回 -1,则将malloc()
为 0 字节分配缓冲区,但fread()
会尝试读取最多 4 GB 的数据,这可能会溢出空间。OTOH,如果ftell()
失败,很可能fread()
也会失败。
Have you printed out the sizes of the files? Is it the second partial file that crashes, or a later file?
你有没有打印出文件的大小?是崩溃的第二个部分文件还是后来的文件?
I've taken the code you supplied, wrapped it up as a main()
function, supplied missing variables and headers, and run it under valgrind. (MacOS X 10.6.6, GCC 4.5.2, Valgrind 3.6.0) It shows no problem. So, your trouble is most probably not in this code per se; something else earlier in your program trampled out of bounds of allocated memory and caused this to fail. I generated the 4 part files using the script:
我已经采用了您提供的代码,将其包装为一个main()
函数,提供了缺少的变量和头文件,并在 valgrind 下运行它。(MacOS X 10.6.6, GCC 4.5.2, Valgrind 3.6.0) 显示没有问题。所以,你的麻烦很可能不在这段代码本身;程序中的其他内容超出了分配的内存范围并导致此操作失败。我使用脚本生成了 4 个部分文件:
{ echo "Header:control-Vcontrol-Mreturncontrol-Vcontrol-M";
dd if=/dev/random bs=1k count=4; } >part1
{ echo "Header:control-Vcontrol-Mreturncontrol-Vcontrol-M";
dd if=/dev/random bs=1k count=4; } >part1
So each file was 4107 bytes long.
所以每个文件的长度为 4107 字节。
Working Code
工作代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char filename[32];
FILE* pFile;
long lSize;
char *buffer;
ssize_t result;
FILE* combinedFile = fopen("mypic.jpg", "wb+");
int numberOfPartitions = 4;
int i;
for(i = 1; i <= numberOfPartitions; i++)
{
sprintf(filename, "part%d", i);
pFile = fopen(filename, "rb");
fseek(pFile , 0 , SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
printf("size(%d) = %ld\n", i, lSize);
buffer = (char*) malloc(sizeof(char) * (lSize + 1));
if (buffer == NULL)
{
fputs("Memory error", stderr);
exit(2);
}
result = fread(buffer, 1, lSize, pFile);
if (result != lSize)
{
fputs("Reading error", stderr);
exit(3);
}
else
{
char* temp = strstr(buffer, "\r\n\r\n");
temp = temp + 4;
int len = lSize - (temp - buffer);
if(i != numberOfPartitions)
fwrite(temp, 1, len - 1, combinedFile);
else
fwrite(temp, 1, len, combinedFile);
}
fclose(pFile);
printf("crash here\n");
free(buffer);
}
fclose(combinedFile);
return 0;
}
I've not inserted all the error checking that I would if it were my own program.
如果它是我自己的程序,我没有插入所有错误检查。
The output file in my scheme is 16381 bytes long; that is 3 bytes short. The problem there is the fwrite()
calls. The fread()
code told you how many bytes it read; you subtracted the bytes for the header, and then subtracted one more. So, that if/else
code reduces to just the fwrite()
in the else
.
我的方案中的输出文件长 16381 字节;即 3 个字节短。问题是fwrite()
电话。该fread()
代码告诉你它有多少字节读取; 您减去标题的字节,然后再减去一个。所以,这if/else
代码减少到只fwrite()
在else
。
回答by llongi
Actually I can't find anything obviously wrong with your memory or file handling in the code above, the crash on free() might just be a symptom of something in your code writing into malloc()'s personal space...
实际上,我在上面的代码中找不到任何明显的内存或文件处理错误,free() 崩溃可能只是您的代码写入 malloc() 个人空间的症状...
You could use memory checkers such as Valgrind or debuggers like gdb to take a closer look.
您可以使用内存检查器(例如 Valgrind)或调试器(例如 gdb)来仔细查看。
The only possibly wrong thing that comes to mind is that buffer is not necessarily NUL-terminated, and as such the strstr() search can happily go over it, buffer[lSize] = '\0'; after the malloc-NULL-check should fix that. Also just to be sure, check that strstr() actually found what it was looking for (it returns NULL if it didn't). You may also want to check that all your fopen() calls actually succeed (return not NULL). If none of this helps, printout's of len, lSize, temp and buffer's values just before the fwrite() calls would be helpful.
想到的唯一可能错误的事情是缓冲区不一定以 NUL 结尾,因此 strstr() 搜索可以愉快地遍历它, buffer[lSize] = '\0'; 在 malloc-NULL-check 之后应该解决这个问题。也只是为了确定,检查 strstr() 是否确实找到了它正在寻找的东西(如果没有,它返回 NULL)。您可能还想检查所有 fopen() 调用是否实际成功(返回非 NULL)。如果这些都没有帮助,那么在 fwrite() 调用之前打印 len、lSize、temp 和缓冲区的值会有所帮助。