Programing

C malloc 어설 션 실패가 발생하는 이유는 무엇입니까?

lottogame 2020. 11. 4. 07:37
반응형

C malloc 어설 션 실패가 발생하는 이유는 무엇입니까?


OpenCL 구현에 대해 벤치마킹 할 수 있도록 분할 및 정복 다항식 알고리즘을 구현하고 있지만 malloc작업을 수행 할 수 없습니다 . 프로그램을 실행하면 많은 것을 할당하고 몇 가지를 확인한 다음 size/2알고리즘 에을 보냅니다 . 그런 다음 malloc다시 라인을 치면 다음과 같이 뱉어집니다.

malloc.c : 3096 : sYSMALLOc : Assertion`(old_top == (((mbinptr) (((char *) & ((av)-> bins [((1)-1) * 2])))-__builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size)> = (unsigned long) ((((__ builtin_offsetof (struct malloc_chunk, fd_nextsize)) + ((2 * (sizeof (size_t)))-1)) & ~ ((2 * (sizeof (size_t)))-1))) && ((old_top)-> size & 0x1) && ((unsigned long) old_end & pagemask) == 0) '실패했습니다. 중단됨

문제의 라인은 다음과 같습니다.

int *mult(int size, int *a, int *b) {
    int *out,i, j, *tmp1, *tmp2, *tmp3, *tmpa1, *tmpa2, *tmpb1, *tmpb2,d, *res1, *res2;
    fprintf(stdout, "size: %d\n", size);

    out = (int *)malloc(sizeof(int) * size * 2);
}

나는으로 크기를 확인 fprintf했고 그것은 양의 정수 (대개 그 시점에서 50)이다. 나는 malloc일반 번호로 전화 시도했지만 여전히 오류가 발생합니다. 나는 무슨 일이 일어나고 있는지 어리둥절하고 지금까지 내가 찾은 Google의 어떤 것도 도움이되지 않습니다.

무슨 일이 일어나고 있는지 아이디어가 있습니까? 컴파일러 오류 인 경우 최신 GCC를 컴파일하는 방법을 알아 내려고 노력하고 있지만 정말 의심 스럽습니다.


메모리가 손상되었을 가능성이 99.9 % (버퍼 오버플로 또는 언더 플로, 해제 된 후 포인터에 쓰기, 같은 포인터에서 두 번 free 호출 등)

Valgrind 에서 코드를 실행하여 프로그램이 잘못한 부분을 확인하십시오.


이런 일이 발생 하는지 더 잘 이해하기 위해 @ r-samuel-klatchko의 답변을 조금 확장하고 싶습니다.

를 호출 할 때 malloc실제로 일어나는 일은 단순히 재생할 메모리 덩어리를 제공하는 것보다 조금 더 복잡합니다. 내부적 malloc으로은 (는) 제공 한 메모리 (가장 중요한 것은 크기)에 대한 일부 관리 정보를 유지하므로를 호출 할 때 해제 할 free메모리 양과 같은 정보를 알 수 있습니다. 이 정보는 일반적으로에서 메모리 위치를 반환하기 직전에 보관됩니다 malloc. 더 자세한 정보는 internet ™ 에서 찾을 수 있지만 (매우) 기본적인 아이디어는 다음과 같습니다.

+------+-------------------------------------------------+
+ size |                  malloc'd memory                +
+------+-------------------------------------------------+
       ^-- location in pointer returned by malloc

이를 기반으로 (그리고 크게 단순화)를 호출 할 때 malloc사용 가능한 메모리의 다음 부분에 대한 포인터를 가져와야합니다. 이 작업을 수행하는 매우 간단한 방법 중 하나는 이전에 제공 한 메모리 비트를보고 메모리에서 size바이트를 더 아래 (또는 위로) 이동하는 것 입니다. 이 구현으로, 당신은 할당 한 후이 같은 것을보고 당신의 기억과 끝 p1, p2그리고 p3:

+------+----------------+------+--------------------+------+----------+
+ size |                | size |                    | size |          +
+------+----------------+------+--------------------+------+----------+
       ^- p1                   ^- p2                       ^- p3

그렇다면 오류의 원인은 무엇입니까?

글쎄, 당신의 코드가 당신이 할당 한 메모리의 양을 넘어서 잘못 쓴다고 상상해 보라 (당신이 당신의 문제처럼 필요한 것보다 적게 할당했거나 당신의 코드 어딘가에서 잘못된 경계 조건을 사용하고 있기 때문이다). 코드가 너무 많은 데이터를 p2써서 p3size필드에 있는 내용을 덮어 쓰기 시작 한다고 가정 해보십시오 . 이제 다음에 호출 malloc하면 반환 된 마지막 메모리 위치를보고 크기 필드로 이동 p3 + size한 다음 거기에서 메모리 할당을 시작합니다. size그러나 코드가 덮어 써 졌으므로이 메모리 위치는 더 이상 이전에 할당 된 메모리 뒤에 있지 않습니다.

말할 필요도없이 이것은 혼란을 일으킬 수 있습니다! malloc따라서 의 구현 자는 이러한 문제 (및 기타 문제)가 발생하려고 할 때이를 포착하기 위해 여러 건전성 검사를 시도하는 여러 "어설 션"또는 검사를 넣었습니다. 특정 경우에 이러한 주장이 위반되어 malloc중단 되어 코드가 실제로 수행해서는 안되는 작업을 수행하려고한다는 것을 알려줍니다.

이전에 언급했듯이 이것은 지나치게 단순화 한 것이지만 요점을 설명하는 것으로 충분합니다. glibc 구현은 malloc5k 라인 이상이며 좋은 동적 메모리 할당 메커니즘을 구축하는 방법에 대한 상당한 양의 연구가 있었기 때문에 모든 것을 SO 답변으로 다루는 것은 불가능합니다. 바라건대 이것이 실제로 문제를 일으키는 원인에 대한 약간의 견해를 제공했기를 바랍니다!


Valgrind 사용에 대한 나의 대체 솔루션 :

친구가 프로그램을 디버깅하는 것을 도왔 기 때문에 매우 기쁩니다. 그의 프로그램에는 malloc()GDB의 동일한 오류 메시지와 함께이 정확한 문제 ( 중단 원인) 가있었습니다 .

Address Sanitizer사용하여 그의 프로그램을 컴파일했습니다.

gcc -Wall -g3 -fsanitize=address -o new new.c
              ^^^^^^^^^^^^^^^^^^

그리고 gdb new. 프로그램이 SIGABRT후속에서 원인으로 종료되면 malloc()유용한 정보가 많이 인쇄됩니다.

=================================================================
==407==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x6060000000b4 at pc 0x7ffffe49ed1a bp 0x7ffffffedc20 sp 0x7ffffffed3c8
WRITE of size 104 at 0x6060000000b4 thread T0
    #0 0x7ffffe49ed19  (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x5ed19)
    #1 0x8001dab in CreatHT2 /home/wsl/Desktop/hash/new.c:59
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
    #4 0x8001679 in _start (/mnt/d/Desktop/hash/new+0x1679)

0x6060000000b4 is located 0 bytes to the right of 52-byte region [0x606000000080,0x6060000000b4)
allocated by thread T0 here:
    #0 0x7ffffe51eb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
    #1 0x8001d56 in CreatHT2 /home/wsl/Desktop/hash/new.c:55
    #2 0x80031cf in main /home/wsl/Desktop/hash/new.c:209
    #3 0x7ffffe061b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

출력, 특히 스택 추적을 살펴 보겠습니다.

첫 번째 부분은에 잘못된 쓰기 작업이 있음을 나타 new.c:59냅니다. 그 줄은

memset(len,0,sizeof(int*)*p);
             ^^^^^^^^^^^^

두 번째 부분은 잘못된 쓰기가 발생한 메모리가 new.c:55. 그 줄은

if(!(len=(int*)malloc(sizeof(int)*p))){
                      ^^^^^^^^^^^

That's it. It only took me less than half a minute to locate the bug that confused my friend for a few hours. He managed to locate the failure, but it's a subsequent malloc() call that failed, without being able to spot this error in previous code.

Sum up: Try the -fsanitize=address of GCC or Clang. It can be very helpful when debugging memory issues.


You are probably overrunning beyond the allocated mem somewhere. then the underlying sw doesn't pick up on it until you call malloc

There may be a guard value clobbered that is being caught by malloc.

edit...added this for bounds checking help

http://www.lrde.epita.fr/~akim/ccmp/doc/bounds-checking.html


I got the following message, similar to your one:


    program: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.

Made a mistake some method call before, when using malloc. Erroneously overwrote the multiplication sign '*' with a '+', when updating the factor after sizeof()-operator on adding a field to unsigned char array.

Here is the code responsible for the error in my case:


    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)+5);
    b[INTBITS]=(some calculation);
    b[BUFSPC]=(some calculation);
    b[BUFOVR]=(some calculation);
    b[BUFMEM]=(some calculation);
    b[MATCHBITS]=(some calculation);

In another method later, I used malloc again and it produced the error message shown above. The call was (simple enough):


    UCHAR* b=(UCHAR*)malloc(sizeof(UCHAR)*50);

Think using the '+'-sign on the 1st call, which lead to mis-calculus in combination with immediate initialization of the array after (overwriting memory that was not allocated to the array), brought some confusion to malloc's memory map. Therefore the 2nd call went wrong.


We got this error because we forgot to multiply by sizeof(int). Note the argument to malloc(..) is a number of bytes, not number of machine words or whatever.


I was porting one application from Visual C to gcc over Linux and I had the same problem with

malloc.c:3096: sYSMALLOc: Assertion using gcc on UBUNTU 11.

I moved the same code to a Suse distribution (on other computer ) and I don't have any problem.

I suspect that the problems are not in our programs but in the own libc.


i got the same problem, i used malloc over n over again in a loop for adding new char *string data. i faced the same problem, but after releasing the allocated memory void free() problem were sorted

참고URL : https://stackoverflow.com/questions/2987207/why-do-i-get-a-c-malloc-assertion-failure

반응형