我知道这是一个老问题,但是在C语言中几乎一切皆有可能。这里已经有一些骇人听闻的解决方案,但是确定内存是否已正确分配的一种有效方法是使用oracle代替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
缺点是用户必须使用上述指令编译其源代码。但是,这与我见过的最糟糕的情况相去甚远。分配和释放内存会有一些开销,但是在增加安全性时总会有一些开销。