为什么以下代码没有提供双重免费错误?

时间:2016-12-14 16:46:28

标签: c undefined-behavior

当我在同一个指针上连续两个free()时,它会产生双重自由错误但是当我尝试释放两次相同的指针时,我释放了其他指针,它没有给出错误。

#include <stdio.h>                                                              
#include <stdlib.h>                                                             
int main (){                                                                               
   long int*ptr;                                                              
    int *ptr1;                                                                  

    ptr = malloc (1);                                                           
    ptr1 = malloc (1);                                                          

    printf ("%ld\n", ptr[-1]);                                                  
    free (ptr);                                                                 
    printf ("%ld\n", ptr[-1]);                                                  
    free (ptr1);                                                                
    free (ptr);                                                                 
    free (ptr1);                                                                
    free (ptr);                                                                 
    free (ptr1);                                                                
    return 0;                                                                   
} 

2 个答案:

答案 0 :(得分:6)

没有承诺双free会导致分段错误。

来自man page

  

free()释放ptr指向的内存空间,它必须具有   通过之前的malloc()calloc()realloc()来电回复。   否则,或者之前已经调用free(ptr),   发生未定义的行为。如果ptrNULL,则不执行任何操作   进行。

Undefined behavior表示无法保证会发生什么。您的程序可能会崩溃,可能会出现奇怪的行为,或者(正如您所见)它可能会正常工作。对代码进行看似无关的更改可能会改变未定义行为的显示方式,因此可能会崩溃或者可能会停止崩溃。

编辑:

如Toby所建议的那样,通过Valgrind等工具运行程序,专门针对这些类型的错误进行了额外的检查,并会准确地告诉您出错的地方。

如果没有这样的工具,如果你调用未定义的行为,所有的赌注都会关闭。

答案 1 :(得分:2)

也许您使用错误的工具来测试您的程序。当我构建你的测试程序时,Valgrind肯定会报告很多错误:

gcc -std=c11 -fPIC -g -Wall -Wextra -Wwrite-strings -Wno-parentheses -Wpedantic -Warray-bounds      41147878.c    -o 41147878
valgrind  ./41147878 
==30744== Memcheck, a memory error detector
==30744== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==30744== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==30744== Command: ./41147878
==30744== 
==30744== Invalid read of size 8
==30744==    at 0x10876C: main (41147878.c:10)
==30744==  Address 0x51d5038 is 8 bytes before a block of size 1 alloc'd
==30744==    at 0x4C2ABAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x108751: main (41147878.c:7)
==30744== 
0
==30744== Invalid read of size 8
==30744==    at 0x108797: main (41147878.c:12)
==30744==  Address 0x51d5038 is 8 bytes before a block of size 1 free'd
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x10878E: main (41147878.c:11)
==30744==  Block was alloc'd at
==30744==    at 0x4C2ABAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x108751: main (41147878.c:7)
==30744== 
0
==30744== Invalid free() / delete / delete[] / realloc()
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x1087C5: main (41147878.c:14)
==30744==  Address 0x51d5040 is 0 bytes inside a block of size 1 free'd
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x10878E: main (41147878.c:11)
==30744==  Block was alloc'd at
==30744==    at 0x4C2ABAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x108751: main (41147878.c:7)
==30744== 
==30744== Invalid free() / delete / delete[] / realloc()
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x1087D1: main (41147878.c:15)
==30744==  Address 0x51d5090 is 0 bytes inside a block of size 1 free'd
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x1087B9: main (41147878.c:13)
==30744==  Block was alloc'd at
==30744==    at 0x4C2ABAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x10875F: main (41147878.c:8)
==30744== 
==30744== Invalid free() / delete / delete[] / realloc()
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x1087DD: main (41147878.c:16)
==30744==  Address 0x51d5040 is 0 bytes inside a block of size 1 free'd
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x10878E: main (41147878.c:11)
==30744==  Block was alloc'd at
==30744==    at 0x4C2ABAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x108751: main (41147878.c:7)
==30744== 
==30744== Invalid free() / delete / delete[] / realloc()
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x1087E9: main (41147878.c:17)
==30744==  Address 0x51d5090 is 0 bytes inside a block of size 1 free'd
==30744==    at 0x4C2BDDB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x1087B9: main (41147878.c:13)
==30744==  Block was alloc'd at
==30744==    at 0x4C2ABAF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30744==    by 0x10875F: main (41147878.c:8)
==30744== 
==30744== 
==30744== HEAP SUMMARY:
==30744==     in use at exit: 0 bytes in 0 blocks
==30744==   total heap usage: 3 allocs, 7 frees, 1,026 bytes allocated
==30744== 
==30744== All heap blocks were freed -- no leaks are possible
==30744== 
==30744== For counts of detected and suppressed errors, rerun with: -v
==30744== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)

如果您使用其他检查器进行测试,则应将问题编辑为更具体。