Я знаю , що це старе питання, але майже все можливо в C. Є кілька хака рішення вже тут, але дійсний спосіб визначення , якщо пам'ять була правильно розподілена, щоб використовувати оракул зайняти місце malloc
, calloc
, realloc
, і free
. Це те саме, що тестові фреймворки (наприклад, cmocka) можуть виявляти проблеми з пам’яттю (помилки сегментів, не звільняючи пам’ять тощо). Ви можете вести список адрес пам'яті, виділених у міру їх виділення, і просто перевірити цей список, коли користувач хоче використовувати вашу функцію. Я застосував щось дуже подібне для власного тестування. Приклад коду:
typedef struct memory_ref {
void *ptr;
int bytes;
memory_ref *next;
}
memory_ref *HEAD = NULL;
void *__wrap_malloc(size_t bytes) {
if(HEAD == NULL) {
HEAD = __real_malloc(sizeof(memory_ref));
}
void *tmpPtr = __real_malloc(bytes);
memory_ref *previousRef = HEAD;
memory_ref *currentRef = HEAD->next;
while(current != NULL) {
previousRef = currentRef;
currentRef = currentRef->next;
}
memory_ref *newRef = (memory_ref *)__real_malloc(sizeof(memory_ref));
*newRef = (memory_ref){
.ptr = tmpPtr,
.bytes = bytes,
.next = NULL
};
previousRef->next = newRef;
return tmpPtr;
}
Ви б мати аналогічні функції для calloc
, realloc
і free
, кожен обгортку з префіксом __wrap_
. Реальний malloc
доступний завдяки використанню __real_malloc
(аналогічно для інших функцій, які ви обгортаєте). Щоразу, коли ви хочете перевірити, чи справді виділено пам’ять, просто перейдіть по зв’язаному memory_ref
списку та знайдіть адресу пам’яті. Якщо ви знайдете його, і він досить великий, ви точно знаєте, що адреса пам'яті не призведе до збою програми; в іншому випадку поверніть помилку. У файлі заголовка, який використовує ваша програма, ви додасте такі рядки:
extern void *__real_malloc (size_t);
extern void *__wrap_malloc (size_t);
extern void *__real_realloc (size_t);
extern void *__wrap_realloc (size_t);
Мої потреби були досить простими, тому я реалізував дуже базову реалізацію, але ви можете собі уявити, як це можна було б розширити, щоб мати кращу систему відстеження (наприклад, створити, struct
що відстежує місце розташування пам'яті на додаток до розміру). Тоді ви просто компілюєте код за допомогою
gcc src_files -o dest_file -Wl,-wrap,malloc -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,free
Недоліком є те, що користувач повинен компілювати свій вихідний код із зазначеними вище директивами; однак, це далеко не гірше, що я бачив. Виділення та звільнення пам’яті має певні накладні витрати, але при додаванні захисту завжди є накладні витрати.