CS50 第 4 周,“恢复问题”,内存泄漏问题

问题描述 投票:0回答:1

your text我居然在大汗淋漓之后,把cs50课程的“recover”题做完了。我得到的最后一个错误是内存泄漏,虽然我修复了它,但我仍然不明白为什么会得到它。所以如果有人能向我解释一下,我会很高兴。

给我错误的那一行是下面的( BYTE 是他们建议在问题规范中创建的类型定义,我是这样创建的:typedef uint8_t BYTE;我在代码的其他地方使用它没有问题)

//Allocating space for images names
char *filename = malloc(1 *(sizeof(BYTE)));

这就是 valgrind 所说的:

  ==2963== Memcheck, a memory error detector
  ==2963== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
  ==2963== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
  ==2963== Command: ./recover card.raw
   ==2963==
  ==2963== Invalid write of size 1
  ==2963==    at 0x4A17034: \_IO_default_xsputn (genops.c:394)
  ==2963==    by 0x4A17034: \_IO_default_xsputn (genops.c:370)
  ==2963==    by 0x4A09822: \_IO_padn (iopadn.c:64)
  ==2963==    by 0x49FF817: pad_func (vfprintf-internal.c:196)
  ==2963==    by 0x49FF817: \__vfprintf_internal (vfprintf-internal.c:1516)
  ==2963==    by 0x4A0AA08: \__vsprintf_internal (iovsprintf.c:95)
  ==2963==    by 0x49E99A7: sprintf (sprintf.c:30)
  ==2963==    by 0x1092FD: main (recover.c:52)
   ==2963==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==2963==    by 0x109241: main (recover.c:29)
  ==2963==
   ==2963== Invalid write of size 1
  ==2963==    at 0x4A17034: \_IO_default_xsputn (genops.c:394)
  ==2963==    by 0x4A17034: \_IO_default_xsputn (genops.c:370)
  ==2963==    by 0x49FED28: outstring_func (vfprintf-internal.c:239)
  ==2963==    by 0x49FED28: \__vfprintf_internal (vfprintf-internal.c:1516)
   ==2963==    by 0x4A0AA08: \__vsprintf_internal (iovsprintf.c:95)
  ==2963==    by 0x49E99A7: sprintf (sprintf.c:30)
  ==2963==    by 0x1092FD: main (recover.c:52)
  ==2963==  Address 0x4bb5262 is 1 bytes after a block of size 1 alloc'd
  ==2963==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==2963==    by 0x109241: main (recover.c:29)
  ==2963==
  ==2963== Invalid write of size 1
  ==2963==    at 0x4A17034: \_IO_default_xsputn (genops.c:394)
  ==2963==    by 0x4A17034: \_IO_default_xsputn (genops.c:370)
  ==2963==    by 0x49FF049: outstring_func (vfprintf-internal.c:239)
  ==2963==    by 0x49FF049: \__vfprintf_internal (vfprintf-internal.c:1593)
  ==2963==    by 0x4A0AA08: \__vsprintf_internal (iovsprintf.c:95)
  ==2963==    by 0x49E99A7: sprintf (sprintf.c:30)
  ==2963==    by 0x1092FD: main (recover.c:52)
   =2963==  Address 0x4bb5263 is 2 bytes after a block of size 1 alloc'd
  ==2963==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==2963==    by 0x109241: main (recover.c:29)
  ==2963==
  ==2963== Invalid write of size 1
  ==2963==    at 0x4A0AA0E: \__vsprintf_internal (iovsprintf.c:97)
  ==2963==    by 0x49E99A7: sprintf (sprintf.c:30)
  ==2963==    by 0x1092FD: main (recover.c:52)
  ==2963==  Address 0x4bb5267 is 6 bytes after a block of size 1 alloc'd
  ==2963==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==2963==    by 0x109241: main (recover.c:29)
  ==2963==
  ==2963== Syscall param openat(filename) points to unaddressable byte(s)
  ==2963==    at 0x4A9D6EB: open (open64.c:41)
  ==2963==    by 0x4A15135: \_IO_file_open (fileops.c:188)
  ==2963==    by 0x4A15491: \_IO_file_fopen@@GLIBC_2.2.5 (fileops.c:280)
  ==2963==    by 0x4A0872D: \__fopen_internal (iofopen.c:75)
  ==2963==    by 0x4A0872D: fopen@@GLIBC_2.2.5 (iofopen.c:86)
  ==2963==    by 0x109316: main (recover.c:56)
  ==2963==  Address 0x4bb5261 is 0 bytes after a block of size 1 alloc'd
  ==2963==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
  ==2963==    by 0x109241: main (recover.c:29)
  ==2963==
  ==2963==
  ==2963== HEAP SUMMARY:
  ==2963==     in use at exit: 0 bytes in 0 blocks
  ==2963==   total heap usage: 104 allocs, 104 frees, 233,481 bytes allocated
  ==2963==
  ==2963== All heap blocks were freed -- no leaks are possible
  ==2963==
  ==2963== For lists of detected and suppressed errors, rerun with: -s
  ==2963== ERROR SUMMARY: 400 errors from 5 contexts (suppressed: 0 from 0)

这些是 check50 结果:

:) recover.c exists.
:) recover.c compiles.
:) handles lack of forensic image
:) recovers 000.jpg correctly
:) recovers middle images correctly
:) recovers 049.jpg correctly
:( program is free of memory errors
valgrind tests failed; see log for more information.

但是如果更改错误行:

 //Allocating space for images names
 char *filename = malloc(8 *(sizeof(char)));

一切正常。在这两种情况下分配的空间都是 1 个字节,并且在这两种情况下都被释放,如果我使用 typedef BYTE 为什么会出现错误?

c memory-leaks valgrind cs50 typedef
1个回答
0
投票
//Allocating space for images names
char *filename = malloc(1 *(sizeof(BYTE)));

BYTE 是别名 uint8_t,它是一个(至少)8 位无符号类型,它本身就是一个 unsigned char 的别名。这仅为 1 char/ 字节分配内存。假设它是一个字符串,它只能容纳空字节。


 //Allocating space for images names
 char *filename = malloc(8 *(sizeof(char)));

两种情况分配的空间都是1个字节。

不,这里分配的空间是8个字节(sizeof (char)根据定义为1),足以容纳000.jpg+\0。但是你不需要在这里malloc()。分配的大小在编译时已知并保持不变,只需使用 array[8] 的简单 char

我在代码的其他地方使用它没有问题。

你很幸运。引用越界内存(包括读取和写入)是未定义的行为。

允许的未定义行为包括忽略情况 完全具有不可预知的结果,在翻译过程中表现 或程序以文件化的方式执行 环境(有或没有诊断消息的发布),以 终止翻译或执行(发出 诊断信息)。

© www.soinside.com 2019 - 2024. All rights reserved.