Освобождение указателя на массив в структуре приводит к ошибке обработчика адресов

#c #malloc #free

Вопрос:

Я пытаюсь освободить массив, адрес которого хранится в структуре, а затем освободить саму структуру целиком, чтобы убедиться, что все освобождено правильно. Код выглядит так:

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

struct foo {
  uint32_t size;
  uint32_t key[4];
  void* data;
};

struct helper_data {
  uint16_t branching;
  struct info** arr_ptr;
};

int main() {

  struct helper_data* ds = malloc(sizeof(struct helper_data));

  ds->branching = 16;

  struct info* arr = malloc(sizeof(struct foo) * 10);
  ds->arr_ptr = amp;arr;

  // ... doing work here ...
  // ... doing work here ...
  // ... doing work here ...

  free(ds->arr_ptr);
  free(ds);

  return 0;

}
 

Обратите внимание, что освобождение ds структуры на самом деле происходит в другой функции, где ей дается указатель на нее, но ошибка в любом случае одинакова:

 ==6880==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7ffee0148700 in thread T0
    #0 0x10fb152c6 in wrap_free 0xa6 (libclang_rt.asan_osx_dynamic.dylib:x86_64h 0x492c6)
    #1 0x10fabae63 in main 0x213 (testing:x86_64 0x100003e63)
    #2 0x7fff204e8620 in start 0x0 (libdyld.dylib:x86_64 0x15620)

Address 0x7ffee0148700 is located in stack of thread T0 at offset 32 in frame
    #0 0x10fabac5f in main 0xf (testing:x86_64 0x100003c5f)

  This frame has 1 object(s):
    [32, 40) 'arr' <== Memory access at offset 32 is inside this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C   exceptions *are* supported)
SUMMARY: AddressSanitizer: bad-free (libclang_rt.asan_osx_dynamic.dylib:x86_64h 0x492c6) in wrap_free 0xa6
==6880==ABORTING
Abort trap: 6
 

Есть ли что-то неправильное в том, как я пытаюсь освободить указатель, как я его храню или что-то еще? Я не могу до конца понять, что могло бы вызвать это.

Ответ №1:

Линия

free(ds->arr_ptr);

это неправильно. Вы должны передать адрес, возвращаемый функцией malloc . Однако вместо этого вы передаете адрес локальной переменной arr .

Вам следует написать либо

free(arr);

или

free(*ds->arr_ptr);

для того, чтобы освободить возвращенный адрес malloc .

Комментарии:

1. free(*ds->arr_ptr); работал на меня, большое спасибо.

2. @Sam: free(arr); тоже должно работать, если arr только не было изменено в коде, который вы не показываете.

3. это сработало бы в этом примере, но я использую указатель на ds структуру, доступ к которой осуществляется из других функций, поэтому на самом деле я освобождаю их в другой функции, поэтому возможность извлечения ds и последующего использования free(*ds->arr_ptr); является идеальным решением.