您没有验证fopen()
呼叫一切成功;这是一个麻烦的根源。
你不检查ftell()
给你一个合理的价值lSize
.
您没有验证strstr()
操作实际上找到了标记字符串。如果不存在,它将返回 NULL,并且接下来的长度操作是假的。但该错误表明您的代码写入越界,而不仅仅是读取数据越界。
您可以将前四个变量声明到循环体中,而不是在循环外部。
您没有显示变量的声明filename
;那可能是一个没有分配空间的 char 指针吗?或者它是一个足够大的数组吗?
这是一个赔率的赌注,即某些内容已写入超出某些分配空间的末尾。这段代码有什么问题并不是很明显,但问题可能出在其他地方,但正是这段代码受到了其他地方违规行为的影响。这在记忆问题中很常见;发现问题的代码并不是导致问题的代码。
是否malloc()
当您分配零字节时,您的机器上返回 null 或非空指针?两者都是合法的回应。
If ftell()
返回-1,然后malloc()
会分配一个 0 字节的缓冲区,但是fread()
将尝试读取最多 4 GB 的数据,这可能会溢出空间。奥托,如果ftell()
失败,很可能是fread()
也会失败。
你打印出文件的大小了吗?崩溃的是第二个部分文件,还是后来的文件?
我已经获取了您提供的代码,将其包装为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
所以每个文件的长度是 4107 字节。
工作代码
#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;
}
我没有插入所有错误检查,如果这是我自己的程序的话。
我的方案中的输出文件长度为16381字节;即少了 3 个字节。问题在于fwrite()
来电。这fread()
代码告诉你它读取了多少字节;您减去标头的字节,然后再减去一个。以便if/else
代码简化为fwrite()
in the else
.