source

'더블 프리 또는 파손' 오류를 추적하는 방법

gigabyte 2022. 7. 17. 16:47
반응형

'더블 프리 또는 파손' 오류를 추적하는 방법

(C++) 프로그램을 실행하면 이 에러와 함께 크래시 됩니다.

* glibc가 검출되었습니다*./load: 이중 프리 또는 파손(!display): 0x00000000c6ed50 ***

오류를 추적하려면 어떻게 해야 합니까?

.std::cout ( ) 。 수 있다gdb게게할 할? ???

사용하는 glibc를 설정할 수 .MALLOC_CHECK_에서 ''로2의 glibc를 malloc더블 프리가 실행되는 시점에서 프로그램이 중단됩니다.

에서 gdb를 하여 할 수 .set environment MALLOC_CHECK_ 2실행하기 에 명령어를 됩니다.프로그램이 중단됩니다.free()콜이 백트레이스로 표시됩니다.

상세한 것에 대하여는, 의 man 페이지를 참조해 주세요.

적어도 두 가지 상황이 있을 수 있습니다.

  1. 동일한 엔티티를 두 번 삭제합니다.
  2. 할당되지 않은 것을 삭제하고 있습니다.

첫 번째 포인터에서는 삭제된 포인터를 모두 NULL로 설정하는 것이 좋습니다.

다음의 3가지 옵션이 있습니다.

  1. 새로 오버로드하여 할당 삭제 및 추적
  2. 네, gdb를 사용하세요.그러면 크래쉬로 역추적을 얻을 수 있습니다.그것은 아마 매우 도움이 될 거예요.
  3. 제안하신 바와 같이 - Valgrind를 사용하세요 - 쉽게 접근할 수 없지만, 앞으로 수천 배의 시간을 절약할 수 있습니다.

gdb를 사용할 수 있지만 먼저 Valgrind를 사용해 보겠습니다.퀵 스타트 가이드를 참조해 주세요.

간단히 말해 Valgrind는 프로그램을 계측하여 동적으로 할당된 메모리 사용 시 이중 여유 공간 및 할당된 메모리 블록의 끝을 지나 쓰기(히프가 손상될 수 있음)와 같은 여러 종류의 오류를 탐지할 수 있도록 합니다.에러가 발생하는 즉시 검출해 보고하기 때문에, 문제의 원인을 직접 참조할 수 있습니다.

세 가지 기본 규칙:

  1. 를 「」로 합니다.NULL 제공 후
  2. NULL자유자
  3. NULL★★★★★★★★★★★★★★★★★★.

이 세 가지 조합은 꽤 잘 어울린다.

하시면 됩니다.valgrind디버깅할 수 있습니다.

#include<stdio.h>
#include<stdlib.h>

int main()
{
 char *x = malloc(100);
 free(x);
 free(x);
 return 0;
}

[sand@PS-CNTOS-64-S11 testbox]$ vim t1.c
[sand@PS-CNTOS-64-S11 testbox]$ cc -g t1.c -o t1
[sand@PS-CNTOS-64-S11 testbox]$ ./t1
*** glibc detected *** ./t1: double free or corruption (top): 0x00000000058f7010 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3a3127245f]
/lib64/libc.so.6(cfree+0x4b)[0x3a312728bb]
./t1[0x400500]
/lib64/libc.so.6(__libc_start_main+0xf4)[0x3a3121d994]
./t1[0x400429]
======= Memory map: ========
00400000-00401000 r-xp 00000000 68:02 30246184                           /home/sand/testbox/t1
00600000-00601000 rw-p 00000000 68:02 30246184                           /home/sand/testbox/t1
058f7000-05918000 rw-p 058f7000 00:00 0                                  [heap]
3a30e00000-3a30e1c000 r-xp 00000000 68:03 5308733                        /lib64/ld-2.5.so
3a3101b000-3a3101c000 r--p 0001b000 68:03 5308733                        /lib64/ld-2.5.so
3a3101c000-3a3101d000 rw-p 0001c000 68:03 5308733                        /lib64/ld-2.5.so
3a31200000-3a3134e000 r-xp 00000000 68:03 5310248                        /lib64/libc-2.5.so
3a3134e000-3a3154e000 ---p 0014e000 68:03 5310248                        /lib64/libc-2.5.so
3a3154e000-3a31552000 r--p 0014e000 68:03 5310248                        /lib64/libc-2.5.so
3a31552000-3a31553000 rw-p 00152000 68:03 5310248                        /lib64/libc-2.5.so
3a31553000-3a31558000 rw-p 3a31553000 00:00 0
3a41c00000-3a41c0d000 r-xp 00000000 68:03 5310264                        /lib64/libgcc_s-4.1.2-20080825.so.1
3a41c0d000-3a41e0d000 ---p 0000d000 68:03 5310264                        /lib64/libgcc_s-4.1.2-20080825.so.1
3a41e0d000-3a41e0e000 rw-p 0000d000 68:03 5310264                        /lib64/libgcc_s-4.1.2-20080825.so.1
2b1912300000-2b1912302000 rw-p 2b1912300000 00:00 0
2b191231c000-2b191231d000 rw-p 2b191231c000 00:00 0
7ffffe214000-7ffffe229000 rw-p 7ffffffe9000 00:00 0                      [stack]
7ffffe2b0000-7ffffe2b4000 r-xp 7ffffe2b0000 00:00 0                      [vdso]
ffffffffff600000-ffffffffffe00000 ---p 00000000 00:00 0                  [vsyscall]
Aborted
[sand@PS-CNTOS-64-S11 testbox]$


[sand@PS-CNTOS-64-S11 testbox]$ vim t1.c
[sand@PS-CNTOS-64-S11 testbox]$ cc -g t1.c -o t1
[sand@PS-CNTOS-64-S11 testbox]$ valgrind --tool=memcheck ./t1
==20859== Memcheck, a memory error detector
==20859== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==20859== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==20859== Command: ./t1
==20859==
==20859== Invalid free() / delete / delete[]
==20859==    at 0x4A05A31: free (vg_replace_malloc.c:325)
==20859==    by 0x4004FF: main (t1.c:8)
==20859==  Address 0x4c26040 is 0 bytes inside a block of size 100 free'd
==20859==    at 0x4A05A31: free (vg_replace_malloc.c:325)
==20859==    by 0x4004F6: main (t1.c:7)
==20859==
==20859==
==20859== HEAP SUMMARY:
==20859==     in use at exit: 0 bytes in 0 blocks
==20859==   total heap usage: 1 allocs, 2 frees, 100 bytes allocated
==20859==
==20859== All heap blocks were freed -- no leaks are possible
==20859==
==20859== For counts of detected and suppressed errors, rerun with: -v
==20859== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
[sand@PS-CNTOS-64-S11 testbox]$


[sand@PS-CNTOS-64-S11 testbox]$ valgrind --tool=memcheck --leak-check=full ./t1
==20899== Memcheck, a memory error detector
==20899== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==20899== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==20899== Command: ./t1
==20899==
==20899== Invalid free() / delete / delete[]
==20899==    at 0x4A05A31: free (vg_replace_malloc.c:325)
==20899==    by 0x4004FF: main (t1.c:8)
==20899==  Address 0x4c26040 is 0 bytes inside a block of size 100 free'd
==20899==    at 0x4A05A31: free (vg_replace_malloc.c:325)
==20899==    by 0x4004F6: main (t1.c:7)
==20899==
==20899==
==20899== HEAP SUMMARY:
==20899==     in use at exit: 0 bytes in 0 blocks
==20899==   total heap usage: 1 allocs, 2 frees, 100 bytes allocated
==20899==
==20899== All heap blocks were freed -- no leaks are possible
==20899==
==20899== For counts of detected and suppressed errors, rerun with: -v
==20899== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
[sand@PS-CNTOS-64-S11 testbox]$

한 가지 해결 방법:

#include<stdio.h>
#include<stdlib.h>

int main()
{
 char *x = malloc(100);
 free(x);
 x=NULL;
 free(x);
 return 0;
}

[sand@PS-CNTOS-64-S11 testbox]$ vim t1.c
[sand@PS-CNTOS-64-S11 testbox]$ cc -g t1.c -o t1
[sand@PS-CNTOS-64-S11 testbox]$ ./t1
[sand@PS-CNTOS-64-S11 testbox]$

[sand@PS-CNTOS-64-S11 testbox]$ valgrind --tool=memcheck --leak-check=full ./t1
==20958== Memcheck, a memory error detector
==20958== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==20958== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==20958== Command: ./t1
==20958==
==20958==
==20958== HEAP SUMMARY:
==20958==     in use at exit: 0 bytes in 0 blocks
==20958==   total heap usage: 1 allocs, 1 frees, 100 bytes allocated
==20958==
==20958== All heap blocks were freed -- no leaks are possible
==20958==
==20958== For counts of detected and suppressed errors, rerun with: -v
==20958== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)
[sand@PS-CNTOS-64-S11 testbox]$

Valgrind Link 사용에 대한 블로그를 확인하십시오.

최신 C++ 컴파일러에서는 세정제를 사용하여 추적할 수 있습니다.

예:

내 프로그램:

$cat d_free.cxx 
#include<iostream>

using namespace std;

int main()

{
   int * i = new int();
   delete i;
   //i = NULL;
   delete i;
}

주소 검사기를 사용하여 컴파일:

# g++-7.1 d_free.cxx -Wall -Werror -fsanitize=address -g

실행:

# ./a.out 
=================================================================
==4836==ERROR: AddressSanitizer: attempting double-free on 0x602000000010 in thread T0:
    #0 0x7f35b2d7b3c8 in operator delete(void*, unsigned long) /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:140
    #1 0x400b2c in main /media/sf_shared/jkr/cpp/d_free/d_free.cxx:11
    #2 0x7f35b2050c04 in __libc_start_main (/lib64/libc.so.6+0x21c04)
    #3 0x400a08  (/media/sf_shared/jkr/cpp/d_free/a.out+0x400a08)

0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014)
freed by thread T0 here:
    #0 0x7f35b2d7b3c8 in operator delete(void*, unsigned long) /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:140
    #1 0x400b1b in main /media/sf_shared/jkr/cpp/d_free/d_free.cxx:9
    #2 0x7f35b2050c04 in __libc_start_main (/lib64/libc.so.6+0x21c04)

previously allocated by thread T0 here:
    #0 0x7f35b2d7a040 in operator new(unsigned long) /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:80
    #1 0x400ac9 in main /media/sf_shared/jkr/cpp/d_free/d_free.cxx:8
    #2 0x7f35b2050c04 in __libc_start_main (/lib64/libc.so.6+0x21c04)

SUMMARY: AddressSanitizer: double-free /media/sf_shared/gcc-7.1.0/libsanitizer/asan/asan_new_delete.cc:140 in operator delete(void*, unsigned long)
==4836==ABORTING

세정제에 대한 자세한 내용은 이 문서 또는 이 문서 또는 최신 c++ 컴파일러(gcc, clang 등)를 참조하십시오.

Boost와 같은 스마트 포인터를 사용하고 있습니까?shared_ptrraw pointer를 사용하고 있는 경우는, 어느 장소에서라도 직접 사용하고 있는지, 전화로 확인해 주세요.get()저는 이것이 꽤 흔한 문제라는 것을 알게 되었습니다.

예를 들어 원시 포인터가 코드에 전달되는 시나리오(콜백핸들러 등)를 상정해 보겠습니다.참조 카운트 등에 대처하기 위해 스마트 포인터에 할당하는 경우가 있습니다.큰 실수입니다. 깊은 복사를 하지 않으면 이 포인터는 코드로부터 소유되지 않습니다.스마트 포인터를 사용한 코드가 종료되면, 그 포인터를 파기해, 지적되고 있는 메모리를 파기하려고 합니다.다른 사람이 필요로 하지 않는다고 생각되기 때문입니다만, 발신 코드가 삭제하려고 하면, 이중 프리 문제가 발생합니다.

물론, 그건 당신의 문제가 아닐 수도 있습니다.가장 간단한 것은 이것이 어떻게 일어날 수 있는지를 보여주는 예입니다.첫 번째 삭제는 문제가 없지만 컴파일러는 이미 해당 메모리가 삭제되었음을 감지하여 문제를 일으킵니다.따라서 삭제 직후 포인터에 0을 할당하는 것이 좋습니다.

int main(int argc, char* argv[])
{
    char* ptr = new char[20];

    delete[] ptr;
    ptr = 0;  // Comment me out and watch me crash and burn.
    delete[] ptr;
}

편집: 변경됨delete로.delete[]ptr은 char 배열입니다.

제 경우엔, 제 프로그램과CUDA 10.0제 프로그램의 의존성은CUDA 10.2 (cudart.10.2.so)그 불일치는 나에게 "이중 자유 혹은 부패"를 초래했다.

사용할 수 있습니다.ldd <your program>종속성에 여러 버전의 CUDA lib가 있는지 확인합니다.

매우 오래된 스레드인 것은 알지만, 이 에러에 대한 구글 검색의 톱이며, 에러의 일반적인 원인을 언급하는 응답은 없습니다.

즉, 이미 닫은 파일을 닫는 것입니다.

주의를 기울이지 않고 두 개의 다른 함수가 같은 파일을 닫으면 두 번째 함수가 이 오류를 생성합니다.

언급URL : https://stackoverflow.com/questions/2902064/how-to-track-down-a-double-free-or-corruption-error

반응형