由C中的malloc引起的内存泄漏

时间:2018-03-15 16:11:35

标签: c malloc undefined-behavior calloc

我很难理解代码中出错的地方。我的程序有一个函数,它一次从文件中读取8个字节的数据

char *read_64_bit_data_from_file(FILE *file, size_t *number_of_chars_read ){
    char *buffer = malloc(sizeof(char) *  8);
    *number_of_chars_read  = fread(buffer, 1, 8, file);
    printf("%s\n", buffer);
    printf("Length of buffer: %ld\n", strlen(buffer));
    printf("Number of chars read: %ld\n", *number_of_chars_read);
    return buffer;
}

该函数调用如下:

...
size_t num = 0;
size_t *number_of_chars_read = #
char *message = calloc(sizeof(char), 8);
do{
    message = read_64_bit_data_from_file(file, number_of_chars_read);
}while(*number_of_chars_read==8);
...

现在,当我编译并运行程序时,我得到以下输出:

Two road�B�z
Length of buffer: 14
Number of chars read: 8
s divergx<�z
Length of buffer: 14
Number of chars read: 8
ed in a x<�z
Length of buffer: 14
Number of chars read: 8
yellow wx<�z
Length of buffer: 14
Number of chars read: 8
ood, Andx<�z
Length of buffer: 14
Number of chars read: 8
 sorry I
Length of buffer: 8
Number of chars read: 8
 could n
Length of buffer: 8
Number of chars read: 8`

问题是写入缓冲区的字符有时超过8 ,但 fread每次都返回值

现在,如果我使用calloc代替malloc来分配buffer,我会根据需要获得输出。以下是这种情况下的输出:

Two road
Length of buffer: 8
Number of chars read: 8
s diverg
Length of buffer: 8
Number of chars read: 8
ed in a 
Length of buffer: 8
Number of chars read: 8
yellow w
Length of buffer: 8
Number of chars read: 8
ood, And
Length of buffer: 8
Number of chars read: 8
 sorry I
Length of buffer: 8
Number of chars read: 8
 could n
Length of buffer: 8
Number of chars read: 8`

我使用带有-Wall-Wextra标志的GCC编译器编译了我的程序。 编译器没有发出警告。

我通过valgrind运行程序。以下是输出:

==6051== Invalid write of size 1
==6051==    at 0x10917B: char_as_binary (in 
/home/saksham/Documents/DES/DES)
==6051==    by 0x1091FA: string_to_binary (in 
/home/saksham/Documents/DES/DES)
==6051==    by 0x108EE6: main (in /home/saksham/Documents/DES/DES)
==6051==  Address 0x521ecf7 is 5 bytes after a block of size 2 alloc'd
==6051==    at 0x4C31B25: calloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6051==    by 0x1090EE: char_as_binary (in 
/home/saksham/Documents/DES/DES)
==6051==    by 0x1091FA: string_to_binary (in 
/home/saksham/Documents/DES/DES)
==6051==    by 0x108EE6: main (in /home/saksham/Documents/DES/DES)
==6051== 
==6051== Invalid read of size 1
==6051==    at 0x10900A: initial_permutation (in 
/home/saksham/Documents/DES/DES)
==6051==    by 0x108FA9: encrypt (in /home/saksham/Documents/DES/DES)
==6051==    by 0x108EFD: main (in /home/saksham/Documents/DES/DES)
==6051==  Address 0x521ec60 is 0 bytes after a block of size 64 
alloc'd
==6051==    at 0x4C31B25: calloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6051==    by 0x1091D3: string_to_binary (in 
/home/saksham/Documents/DES/DES)
==6051==    by 0x108EE6: main (in /home/saksham/Documents/DES/DES)
==6051== 
==6051== 
==6051== HEAP SUMMARY:
==6051==     in use at exit: 2,076 bytes in 172 blocks
==6051==   total heap usage: 186 allocs, 14 frees, 12,972 bytes 
allocated
==6051== 
==6051== LEAK SUMMARY:
==6051==    definitely lost: 2,076 bytes in 172 blocks
==6051==    indirectly lost: 0 bytes in 0 blocks
==6051==      possibly lost: 0 bytes in 0 blocks
==6051==    still reachable: 0 bytes in 0 blocks
==6051==         suppressed: 0 bytes in 0 blocks
==6051== Rerun with --leak-check=full to see details of leaked memory
==6051== 
==6051== For counts of detected and suppressed errors, rerun with: -v
==6051== ERROR SUMMARY: 93 errors from 2 contexts (suppressed: 0 from 
0)

我真的不明白为什么malloc表现如此,以及如何使用calloc修复它。我相信我的程序有UB(未定义的行为)。

请帮助我了解我监督的内容以及我在哪里出错。

1 个答案:

答案 0 :(得分:2)

为了使C字符串样式函数起作用(例如strlen),您需要在buffer中为NUL终止符保留一个字节。

你没有这样做,所以你的程序的行为正式 undefined 。你的编译器没有接受这个,但Valgrind是。它还会警告您遗失的free。考虑分配9个字节,明确地将buffer[8]设置为0,并确保您不要尝试将超过8个字节读入buffer