如果我说:
#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);
}
然后,显然,程序将打印“okay”,然后死亡,因为“指针被释放未被分配” - 显然,因为字符串是一个字符串文字。
我想编写一个在给定字符串文字时不执行任何操作的函数,但在给定非字符串文字时调用free。这可能吗,如果是的话,怎么样?
答案 0 :(得分:9)
我认为标准没有任何东西可以检查指针是否由malloc返回(而你只能将它们传递给free)所以我会说不,你找不到它。你必须自己跟踪它。
答案 1 :(得分:5)
没有。在C中,你必须跟踪你自己分配的内容。
某些malloc
实现(例如dlmalloc
)为检查堆提供了一些额外的功能,但您不应该依赖它们。 dlmalloc
具有函数dlmalloc_inspect_all
,它将遍历堆并返回malloc
已分配的所有内存区域,内存映射块除外。因此,您可以使用它来测试指针是否指向非内存映射分配,但一般来说这仍然是一个坏主意。
在Windows上,甚至不要考虑使用[IsBadReadPtr
]来测试指针是否指向可读内存 - it should really be called CrashProgramRandomly
。
答案 2 :(得分:2)
没有可移植的方式。但是,由于大多数实现在与文字(字符串)数据不同的内存区域中分配堆对象,因此如果给定的字符串指针落在任一区域内,则可以进行有根据的猜测。
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类似),并进行比较你指向这些地区的指针。
答案 3 :(得分:1)
如果您在执行时了解程序的内存映射,那么您可以做一些事情。但更好的办法是进行适当的内存管理。
答案 4 :(得分:1)
您可以为malloc编写一个包装器,用于跟踪已分配内存的地址。然后在您的免费功能中,您可以查看该内存是否在列表中。
除此之外,您可以使用堆,但它甚至不能远程移植。
但为什么不构建某种GC或使用GC库。