Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在std C中有没有一种方法可以告诉我是否可以安全地取消引用指针_C_Debugging_Pointers_Exception Handling - Fatal编程技术网

在std C中有没有一种方法可以告诉我是否可以安全地取消引用指针

在std C中有没有一种方法可以告诉我是否可以安全地取消引用指针,c,debugging,pointers,exception-handling,C,Debugging,Pointers,Exception Handling,考虑以下几点: int * i = malloc(sizeof(int)); free(i); 我现在处在一个场景中,I指向释放的内存,但它也是非零的;这是C编程中的一个常见错误,在我开始执行以下操作之前,是否有办法判断i仍然是有效指针: *i++; //probable EXC_BAD_ACCESS crash 我知道这是完全不可能有一个100%可靠(没有误报)的方法,除非你从来没有重用内存;但是,对于调试来说,大部分时间都有效的东西是非常好的 编辑 我不是说你不应该把指针设为NULL,我

考虑以下几点:

int * i = malloc(sizeof(int));
free(i);
我现在处在一个场景中,
I
指向释放的内存,但它也是非零的;这是C编程中的一个常见错误,在我开始执行以下操作之前,是否有办法判断
i
仍然是有效指针:

*i++; //probable EXC_BAD_ACCESS crash
我知道这是完全不可能有一个100%可靠(没有误报)的方法,除非你从来没有重用内存;但是,对于调试来说,大部分时间都有效的东西是非常好的

编辑


我不是说你不应该把指针设为NULL,我只是想知道是否有一种便携的(POSIXish)方法可以在不造成灾难性后果的情况下插入地址,我只是对调试时不时出现的复杂多线程问题感兴趣。

要想获得能够用于调试的东西,您需要使用valgrind的memcheck工具。当访问发生时,您将看到无效的读或写错误


@Anthales是对的,您需要在释放后立即将指针设置为NULL。如果对指针有多个引用,这会变得更复杂。在不知道你具体情况的情况下,我不能确切地说怎么做,但是一个可能的解决方案是给不同的结构一些东西,允许它们请求对该内存的引用,而不是一个特定的指针。

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

从哲学上讲,如果你不知道在
*i++
无论
i
是否仍然指向可以安全递增的对象,您如何知道即使递增也正确

这与C中的数组使用情况类似:您习惯于同时传递指向数据的指针和相应的大小指示符。或者将它们都包装到一个结构中

如果你能举一个更大的例子来说明如何使用
i
,人们可以推荐一种惯用的方法,在差异点添加所需的附加信息。

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

您必须独立于指针本身跟踪所有这些信息,或者在如何使用指针方面强制执行一些规则

没有

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


如果您确实想更详细地了解此功能,可以使用自定义分配器,但现有的一些工具非常有用。

有些人喜欢在
free
之后立即将释放的指针设置为
NULL

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

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

空闲
之后,始终将
i
设置为
NULL
,并在取消引用之前测试它是否为
NULL
。简单回答:否。复杂答案:不。@Anthales只要对指针只有一个引用就可以工作,我注意到这是一个编程错误。这可能是真的,但如果有多个指针指向同一个对象,则需要考虑所有指针。所以在本例中,Richards comment applies.FWIW,我不同意这种“总是将事物设置为空”的胡说八道。当指针超出范围,或者当它所属的结构被释放时,释放指针。然后,不管您是否将其设置为null,因为您已经设计了代码,所以无论如何都不会再次使用它。比在指针周围闲逛要安全得多,这些指针可能是空的,也可能不是空的,它们的用户必须随时检查。例外情况是,在执行诸如清除缓存而不销毁缓存之类的操作时,您希望释放缓存,并将其设置为null以指示不再存在缓存。将指针设置为null是一种很好的做法。在许多不同的级别上,出于许多不同的原因。在我的C89参考资料中(我不记得是从哪里得到的),对
free()
的描述是:“如果ptr是空指针,则不会发生任何操作。”@pmg感谢纠正我,在我的脑海中我认为是这样的。显然,我应该仔细检查,因为C89中的行为确实是相同的。