当我们用C free()
内存时,为什么那个内存没有填充零?在调用free()
时,是否有一种很好的方法可以确保这种情况发生?
我宁愿不冒险将内存中的敏感数据释放回操作系统......
答案 0 :(得分:22)
释放存储器块时将其清零需要额外的时间。由于大部分时间实际上没有必要,因此默认情况下不会这样做。
如果您确实需要(比如您使用内存存储密码或加密密钥) - 在释放块之前调用memset()
。编写链memset()
和free()
的效用函数也不是问题。
答案 1 :(得分:6)
C为什么在免费实现中内存没有明确地设置为零。
因速度快。
因为我们释放了内存后我们如何在释放后将其设置为零。
嗯?
答案 2 :(得分:6)
如果您希望在释放内存时将内存设置为0,则必须在之前 free()
之前自行执行此操作。如果您在free()
之后尝试它,则无法保证它没有再次分配。例如,您可以使用memset()
。
free()
不保证将清除内存,因为C不保证malloc()
将返回初始化内存。无论哪种方式,你必须在分配之后自己初始化它,所以在free()
'
答案 3 :(得分:6)
[编辑:这是试图回答原始海报的问题。 shog9的编辑可能会也可能没有改变这个问题 - 由于原版不清楚而很难说... ...
如果你的意思是,正如其他人所假设的那样,为被释放的内存块的每个字节设置0,那么在释放块之后就不能这样做了。尝试这样做会产生未定义的行为。所以,如果你这样做,那么你就会严重误解内存分配。
但我猜你说“我们在释放后将它设置为零”,你可能会谈论这样的代码:
free(ptr);
ptr = NULL;
如果是这样,那么free的原因无法将ptr设置为NULL,那就是free只接收来自变量ptr的值。它没有办法修改ptr,因为你没有将变量ptr本身传递给free。您只是传递当前存储在其中的地址。这是C语言设计的一部分 - 当你调用一个传递值的函数时,被调用者无法告诉该值是如何计算的,或者调用者的代码中可能包含哪个变量。即使有可能,对这个语言规则的例外是免费的也是疯狂的。
在任何情况下,并不是每个人在释放它们之后都会将指针归零。有些人认为这是一个很好的安全措施,其他人则认为不是。无论你如何看待它,代码都不会将内存归零,它只会将指针归零到内存。如果你想编写一个为你清除指针的函数,那么你可以:
void free_and_clear(void **pptr) {
free(*pptr);
*pptr = NULL;
}
然后像这样使用它:
free_and_clear(&ptr);
请注意,这会传递指向变量ptr的指针,而不是ptr的值。所以free_and_clear可以修改ptr。但是这对你如何使用它有一些限制,这些限制不适用于free - 你需要一个指向可修改值的指针,而不仅仅是一个值。
答案 4 :(得分:6)
最初的C哲学是将隐含效应保持在绝对最小值。 如果程序员想要在释放指向的内存后将指针归零,那就是程序员应该写的东西。我们这些经常使用像这样的宏的人:
#define FREE(P) ((void)(free((P)), (P) = NULL))
当然如果传递给FREE
的表达式有副作用,那么刚刚开了一大堆蠕虫......
答案 5 :(得分:6)
free()不会将内存释放回操作系统 - 它会释放回进程的堆管理器。出于效率原因,它不是零。
当进程分配虚拟内存时,大多数操作系统会将其归为零页面。这可以防止内存从一个进程“泄漏”到另一个进程,并导致出现像您提到的安全问题。
如果您的进程中有数据不想保留在内存中(例如,用户的密码),则您有责任将其清零。 Windows为此提供了SecureZeroMemory API。
答案 6 :(得分:5)
memset(ptr, 0, size);
free(ptr);
我想你想要这个...
答案 7 :(得分:3)
C最初被设计为系统实现语言,因此C操作通常与实际操作一样快且接近金属。设计理念中的一个关键点是,您可以进行多次快速操作,使其成为一种速度更慢,更安全的操作,但是您不能采取更慢,更安全的操作并使速度更快。
如果你想要一个零和免费的功能,你可以写一个,然后使用它而不是free()
。如果你担心安全问题,我会推荐它。
答案 8 :(得分:2)
问题的一个非常具体的答案“为什么在释放后将内存设置为0?”是“因为语言规范没有定义那种行为。
从草案ANSI C规范:“自由函数导致ptr指向的空间 取消分配,即可供进一步分配。“
答案 9 :(得分:2)
将释放指针的结果设置为零似乎是废话,但如果稍后无意中访问指针,您将获得段错误(至少在实际操作系统中),并且调试器将指向此处憎恶正在发生。但正如其他人所指出的那样,当你以后称之为“免费”时,所有免费的都是免费的地址,而不是别的。
答案 10 :(得分:2)
如果我正确地理解了这个问题,那么OP希望不要将敏感信息“留在那里”而担心它会受到损害。正如之前的海报所指出的,在释放之前释放内存就是擦除数据的答案。
然而,它远未解决OP试图实现的目标。对于初学者来说,将内存归零在保护应用程序方面是无用的。即使将内存页面分配给另一个正在运行的进程,在大多数操作系统中,此过程也是不确定的,并且没有理智的黑客会使用这种技术来破坏您的数据。
一个理智的黑客会做的是将你的程序打入反汇编程序并通过它进行调试,直到找出数据的位置然后再使用它。因为一旦你是一个称职的反汇编程序(是的,反汇编程序:),对memset的调用就显而易见了。)我们假设的黑客只会在memset发生之前获取数据。
真正回答你的问题。如果您正在尝试保护C程序中的某些敏感数据,那么您将进入远远超出正常C / C ++程序员(如我自己)的领域,进入编写虚拟机以执行数据敏感操作的领域。
你甚至提出这个问题的事实意味着你开发一些需要这种保护水平的东西是不计后果的。此外,它绝对不是保护数据的第一站。首先选择低悬的水果,网上有很多信息。
答案 11 :(得分:0)
因为这会浪费时间。
答案 12 :(得分:0)
使用free()释放内存后,值&在该特定地址分配的内存被删除(释放),但指针仍然指向该地址。如果您尝试取消引用该指针,则会出现Segmentation fault或Bus错误。因此,一旦指针指向的内存被释放,就可以安全地为指针分配NULL值。你可以参考< Setting variable to NULL after free>
答案 13 :(得分:0)
还有bzero(3)。