已经释放内存
C 中是否有任何方法可以知道内存块之前是否已被 free() 释放?我可以做一些像...
if(isFree(pointer))
{
//code here
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
C 中是否有任何方法可以知道内存块之前是否已被 free() 释放?我可以做一些像...
if(isFree(pointer))
{
//code here
}
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(5)
好吧,如果您需要检查指针是否已被释放,您可能需要检查您的设计。您永远不必跟踪指针的引用计数或指针是否被释放。另外,有些指针不是动态分配的内存,所以我希望您指的是用 malloc() 调用的指针。这是我的观点,但如果你有一个可靠的设计,你应该知道你的指针指向的东西何时被使用。
我看到这个不起作用的唯一地方是在整体内核中,因为内存中的页面由于共享映射等原因需要使用计数。
在您的情况下,只需将未使用的指针设置为 NULL 并检查即可。这为您提供了一种有保证的方式来了解已分配的结构中是否有未使用的字段。一个简单的规则是,无论何时释放需要以上述方式检查的指针,只需将其设置为 NULL 并将 isFree() 替换为 if point == NULL。这样就不需要跟踪引用计数,并且您可以确定指针是否有效并且没有指向垃圾。
Ok if you need to check whether a pointer has already been freed you may want to check your design. You should never have to either track reference count on a pointer or if it's freed. Also some pointers are not dynamically allocated memory so I hope you mean ones called with malloc(). This is my opinion but again if you have a solid design you should know when the things your pointers point to are done being used.
The only place I have seen this not work is in monolithic kernels because pages in memory need a usage count because of shared mappings among other things.
In your case simply set unused pointers to NULL and check that. This gives you a guaranteed way of knowing in the case that you have unused fields in structures that were malloced. A simple rule is wherever you free a pointer that needs to be checked in the above way just set it to NULL and replace isFree() with if pointer == NULL. This way no reference count needs to be tracked and you know for sure if your pointer is valid and not pointing to garbage.
不,没有办法。
但是,您可以使用一些代码规则,如下所示:
始终始终始终使用 malloc 保护分配:
释放指针后,将其设置为 0
任何您想要的地方要使用你的“被释放”功能,只需在评论中说
更新
@Jesus即可:
如果可能的话,这通常是一个很好的做法;问题是在现实生活中用 C 语言通常是不可能的。以包含双向链接行列表的文本编辑器为例。该列表非常简单:
我定义一个
guarded_malloc
函数,该函数分配内存并使用
newLine()
创建列表节点,我在字符串
s
中添加文本到我的行,不要怀疑我应该使用有界长度的形式,这只是一个例子。
现在,如何实现删除释放后超出范围的
line
内容?No, there is no way.
You can, however, use a little code discipline as follows:
Always always always guard allocations with malloc:
After freeing a pointer, set it to 0
Anywhere you'd be tempted to use your "is freed" function, just say
Update
@Jesus in comments says:
That's generally good practice when possible; the problem is that in real life in C it's often not possible. Consider as an example a text editor that contains a doubly-linked list of lines. The list is really simple:
I define a
guarded_malloc
function that allocates memoryand create list nodes with
newLine()
I add text in string
s
to my lineand don't quibble that I should be using the bounded-length forms, this is just an example.
Now, how can I implement deleting the contents of a
line
I created with thechar * contents
going out of scope after freeing?我发现没有人能够解释为什么你想要的东西从根本上来说是不可能的。释放资源(在本例中为内存,但这同样适用于基本上任何资源)意味着将其返回到可供重用的资源池。系统可以对“地址 X 处的内存块是否已被释放?”提供合理答案的唯一方法。是为了防止该地址被重用,并为其存储一个状态标志,指示它是否已“释放”。但在本例中,它实际上并未被释放,因为它不可重用。
正如其他人所说,您试图回答这个问题的事实意味着您存在需要解决的基本设计错误。
I see nobody has addressed the reason why what you want is fundamentally impossible. To free a resource (in this case memory, but the same applies to basically any resource) means to return it to a resource pool where it's available for reuse. The only way the system could provide a reasonable answer to "Has the memory block at address X already been freed?" is to prevent this address from ever being reused, and store with it a status flag indicating whether it was "freed". But in this case, it has not actually been freed, since it is not available for reuse.
As others have said, the fact that you're trying to answer this question means you have fundamental design errors you need to address.
一般来说,可移植地执行此操作的唯一方法是替换内存分配函数。但是,如果您只关心自己的代码,一种相当常见的技术是在
free()
后将指针设置为NULL
,因此任何后续使用都会抛出异常或段错误:In general the only way to do this portably is to replace the memory allocation functions. But if you're only concerned about your own code, a fairly common technique is to set pointers to
NULL
after youfree()
them, so any subsequent use will throw an exception or segfault:对于特定于平台的解决方案,您可能对 Win32 函数感兴趣 IsBadReadPtr(以及其他类似的)。该函数将能够(几乎)预测从特定内存块读取时是否会出现分段错误。
注意:Microsoft 已弃用 IsBadReadPtr。
然而,这在一般情况下并不能保护你,因为操作系统对 C 运行时堆管理器一无所知,并且如果调用者传入的缓冲区没有你期望的那么大,那么堆块的其余部分从操作系统的角度来看将继续可读。
除了指向的位置之外,指针没有任何信息。你能做的最好的事情就是说“我知道这个特定的编译器版本如何分配内存,所以我将取消引用内存,将指针向后移动 4 个字节,检查大小,确保它匹配......”等等。您不能以标准方式执行此操作,因为内存分配是实现定义的。更不用说他们可能根本没有动态分配它。
顺便说一句,我建议阅读 Steve McGuire 的“编写可靠的代码”。关于内存管理的优秀章节。
For a platform-specific solution, you may be interested in the Win32 function IsBadReadPtr (and others like it). This function will be able to (almost) predict whether you will get a segmentation fault when reading from a particular chunk of memory.
Note: IsBadReadPtr has been deprecated by Microsoft.
However, this does not protect you in the general case, because the operating system knows nothing of the C runtime heap manager, and if a caller passes in a buffer that isn't as large as you expect, then the rest of the heap block will continue to be readable from an OS perspective.
Pointers have no information with them other than where they point. The best you can do is say "I know how this particular compiler version allocates memory, so I'll dereference memory, move the pointer back 4 bytes, check the size, makes sure it matches..." and so on. You cannot do it in a standard fashion, since memory allocation is implementation defined. Not to mention they might have not dynamically allocated it at all.
On a side note, I recommend reading 'Writing Solid Code' by Steve McGuire. Excellent sections on memory management.