我已经完成了 cs50 的问题集 4,名为“recover”。您将在下面看到我对一个名为 sfile 的 char* 使用了 malloc。在文件末尾,我记得释放分配的空间(又名 sfile)并关闭我打开的 2 个文档。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
printf("%s", argv[1]);
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
printf(" can't be opened for reading\n");
return 2;
}
unsigned char arr[512];
int s = 0;
FILE *output_file = NULL;
char *sfile = malloc(sizeof(char) * 8);
while (fread(arr, sizeof(char), 512, file) != 0)
{
if (arr[0] == 0xff && arr[1] == 0xd8 && arr[2] == 0xff && (arr[3] & 0xf0) == 0xe0)
{
sprintf(sfile, "%03i.jpg", s);
output_file = fopen(sfile, "w");
s++;
}
if (output_file != NULL)
{
fwrite(arr, sizeof(char), 512, output_file);
}
}
free(sfile);
fclose(output_file);
fclose(file);
return 0;
}
但是,当运行 check50(一个检查您是否完成练习的所有要点的工具)时,我只收到一条红色消息,表明 valgrind 已检测到内存错误。所以我的下一步是跑步:
$ valgrind ./recover card.raw
这就是返回的内容:
==53590== HEAP SUMMARY:
==53590== in use at exit: 23,128 bytes in 49 blocks
==53590== total heap usage: 1,091 allocs, 1,042 frees, 240,880 bytes allocated
==53590==
==53590== 23,128 bytes in 49 blocks are still reachable in loss record 1 of 1
==53590== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==53590== by 0x4A076CD: __fopen_internal (iofopen.c:65)
==53590== by 0x4A076CD: fopen@@GLIBC_2.2.5 (iofopen.c:86)
==53590== by 0x109304: main (recover.c:37)
==53590==
==53590== LEAK SUMMARY:
==53590== definitely lost: 0 bytes in 0 blocks
==53590== indirectly lost: 0 bytes in 0 blocks
==53590== possibly lost: 0 bytes in 0 blocks
==53590== still reachable: 23,128 bytes in 49 blocks
==53590== suppressed: 0 bytes in 0 blocks
==53590==
==53590== For lists of detected and suppressed errors, rerun with: -s
==53590== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
程序运行完美,这是唯一剩下的问题。
我看过 cs50 receive sillreachable but no valgrind error,但我无法真正理解它,因为他的代码在我看来是意大利面条代码(没有冒犯!!)
我对 C 语言还是个新手,并且拥有 Python 编程背景,这让我很难理解与内存有关的任何内容,因为 python 更加直接。
任何帮助表示赞赏:)
问题是
output_file = fopen(sfile, "w");
可能会发生多次。但你只关闭
output_file
一次。
您需要在打开文件之前添加一个检查,看看
output_file
是否不是NULL
,然后先关闭文件,然后再打开它。