2

考虑以下:

int * i = malloc(sizeof(int));
free(i);

我现在处于i指向已释放内存的情况,但它也非零;i这是 C 编程中的一个常见错误,有没有办法在我去做类似的事情之前告诉它仍然是一个有效的指针:

*i++; //probable EXC_BAD_ACCESS crash

我知道完全不可能有 100% 可靠(无误报)的方法,除非你从未重用内存;但是大部分时间都有效的东西对于调试来说非常有用。

编辑

我并不是说您不应该将指针设置为 NULL,我只是想知道是否有一种可移植的(POSIXish)方法来戳地址而不会造成灾难性的影响,我只是对调试复杂的多线程问题感兴趣到时间。

4

5 回答 5

2

不。

静态分析和实时工具(例如 valgrind 和 guard malloc)可以帮助您解决这个问题。改变你编写程序的方式也有助于更容易地理解所有权和生命周期。

如果您真的想要更详细地了解此功能,您可以使用自定义分配器——但现有的一些工具可以提供很大帮助。

于 2012-04-18T22:29:29.877 回答
2

要获得适用于调试的东西,您需要使用 valgrind 的 memcheck 工具。访问发生时,您会看到无效读取或无效写入错误。

@Anthales 是对的,您需要在释放后立即将指针设置为 NULL。如果您对指针有多个引用,这会变得更加复杂。在不了解您的具体情况的情况下,我无法确切说明如何执行此操作,但可能的解决方案是为不同的结构提供一些东西,使它们能够请求对该内存的引用而不是特定的指针。

于 2012-04-18T22:19:37.093 回答
1

没有(可移植的)方法可以从指针值本身知道非 NULL 指针值是否有效。同样,没有(便携式)方法可以知道指针是否指向具有自动、静态或动态范围的对象。如果您非常熟悉您的平台的内存模型,您可能会做出一些有根据的猜测(即,0x00000001可能不是有效的内存位置),但仅此而已。

您必须将所有这些信息与指针本身分开跟踪,或者在如何使用指针时强制执行一些纪律。

于 2012-04-18T22:28:53.703 回答
0

你在 C 中真正能做的就是传递足够的信息来知道是否i仍然指向某个东西。

从哲学上讲,如果您不知道*i++;是否i仍然指向可以安全递增的东西,那么即使确实如此,您怎么知道递增它是正确的?

这与 C 中的数组使用情况类似:您养成了传递数据指针和伴随的大小指示符的习惯。或者你将它们都包装成一个结构。

也许如果你能给出一个更大的例子来说明如何i使用,人们可以推荐一种惯用的方式来添加你需要的附加信息。

于 2012-04-18T22:22:00.490 回答
0

有些人喜欢将释放的指针设置为紧随NULL其后free

#define paranoid_free(ptr)    (free(ptr), (ptr) = NULL)

这有利于避免free(NULL)C 中定义的双重释放问题(作为无操作)。但它仍然不会阻止您取消引用指针并在程序的其他地方调用未定义的行为。

于 2012-04-18T22:33:42.690 回答