如果我说:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char *x;
char *y;
int main() {
x = malloc(sizeof("Hello, world!"));
strcpy(x, "Hello world!");
y = "Hello, world";
free(x);
fprintf(stderr, "okay");
free(y);
}
然后,很明显,程序会打印"OK",然后死亡,因为"释放的指针没有分配"——很明显,因为字符串是字符串文字。
我想写一个函数,当给定字符串文字时什么都不做,但当给定非字符串文字时调用free。这可能吗?如果可能,怎么做?
我不认为标准有任何东西可以检查malloc是否返回了指针(你只应该把它们传递给free),所以我会说没有,你找不到。你必须自己记录。
否。在C中,你必须记录你自己分配了什么。
一些malloc
实现(如dlmalloc
)提供了一些用于检查堆的额外功能,但您不应该依赖这些功能。dlmalloc
具有函数dlmalloc_inspect_all
,它将遍历堆并返回给您malloc
已分配的所有内存区域,但内存映射块除外。因此,您可以使用它来测试指针是否指向非内存映射的分配,但总的来说,这仍然是个坏主意。
在Windows上,甚至不要考虑使用[IsBadReadPtr
]来测试指针是否指向可读内存——它真的应该被称为CrashProgramRandomly
。
没有可移植的方法。然而,由于大多数实现将堆对象分配到与文字(字符串)数据不同的内存区域,因此,如果给定的字符串指针位于任一区域内,则可以进行有根据的猜测。
static char x;
bool isStatic(const void *p)
{
const char * cp = (const char *)p;
// Check if the pointer falls within +/-16K of 'x'
if (cp-16*1024 <= &x && &x <= cp+16*1024)
return true;
else
return false;
}
显然,这有点像黑客。更好的方法是在可执行文件加载到内存后直接访问其.bss
、.data
和.text
地址(这些是Unix,Win32类似),并将指针与这些区域进行比较。
如果您在执行时了解程序的内存映射,那么您可能会做一些事情。不过,一个更好的想法是进行适当的内存管理。
您可以为malloc编写一个包装器,跟踪已分配内存的地址。然后在你的空闲函数中,你可以看到该内存是否在列表中。
除此之外,你可能可以玩堆,但它甚至不能远程移植。
但为什么不构建某种GC或使用GC库呢。