When we free()
memory in C, why is that memory not filled with zero? Is there a good way to ensure this happens as a matter of course when calling free()
?
当我们在C中释放()内存时,为什么内存中没有填满0 ?在调用free()时,是否有一种很好的方法确保发生这种情况?
I'd rather not risk leaving sensitive data in memory released back to the operating system...
我不想冒险将敏感数据留在内存中,并将其释放回操作系统……
15 个解决方案
#1
22
Zeroing out the memory block when freeing it will require extra time. Since most of time there's actually no need in it it is not done by default.
清除内存块时,将需要额外的时间。因为大多数时候实际上不需要它,它不是默认的。
If you really need (say you used memory for storing a password or a cryptographic key) - call memset()
before freeing the block. Writing an utility function that chains memset()
and free()
is not a problem either.
如果您确实需要(假设您使用内存存储密码或密码密钥),请在释放块之前调用memset()。编写一个连锁memset()和free()的实用程序函数也不是问题。
#2
6
C why is the memory not explictly set to zero in the free implementation .
为什么在*实现中内存没有明确地设置为零。
Because of speed.
因为速度。
Because after we free the memory any how we set it to zero after freeing.
因为在释放内存之后,我们将内存设置为0。
Eh?
是吗?
#3
6
If you want the memory to be set to 0 when you free it, you'll have to do it yourself before you free()
it. If you try after you free()
it there are no guarantees that it hasn't been allocated again. For instance you can use memset()
for that.
如果要在释放内存时将内存设置为0,那么在释放内存()之前,您必须自己执行。如果您在free()之后尝试,则不能保证没有再次分配它。例如,您可以为此使用memset()。
free()
doesn't guarantee that the memory will be cleared because C doesn't guarantee that malloc()
will return initialized memory. Either way you have to initialize it yourself after it's been allocated, so there's no point in clearing it when it's free()
'd
free()并不保证内存将被清除,因为C不保证malloc()将返回初始化的内存。无论哪种方式,都必须在分配之后自己初始化它,所以在空闲()'d时清除它是没有意义的
#4
6
The original C philosophy was to have keep implicit effects to an absolute minimum. If a programmer wants a pointer zeroed after the memory pointed to is freed, that's what the programmer should write. Those of us who do often use a macro like this one:
最初的C哲学是将隐式效应保持到绝对最小。如果一个程序员想要一个在内存指向被释放后的指针归零,那就是程序员应该写的东西。我们中的一些人经常使用像这样的宏:
#define FREE(P) ((void)(free((P)), (P) = NULL))
Of course if the expression passed to FREE
has side effects, one has just opened a large can of worms...
当然,如果传递给FREE的表达式有副作用,我们就会打开一罐虫子……
#5
6
free() doesn't release memory back to the OS - it releases back to the process's heap manager. For efficiency reasons, it is not zero'd out.
free()不会将内存释放回操作系统——它会将内存释放回进程的堆管理器。出于效率的原因,它并不是零。
When a process allocates virtual memory, most OS's will hand it a zero'd page. This prevents memory from "leaking" from one process to the other and causing a security issue like you mention.
当一个进程分配虚拟内存时,大多数操作系统会给它一个零页。这可以防止内存从一个进程“泄漏”到另一个进程,并像您提到的那样导致安全问题。
If you have data in your process that you don't want to keep in memory (for example, a user's password), you are responsible for zeroing it out. Windows provides the SecureZeroMemory API for this.
如果您的进程中有不想保存在内存中的数据(例如,用户的密码),那么您有责任将其调零。Windows为此提供了SecureZeroMemory API。
#6
6
[Edit: this is an attempt to answer the original poster's question. The question may or may not have been changed by shog9's edit - it's hard to say since the original was unclear...]
[编辑:这是对原海报问题的回答。这个问题可能会被幕府将军的修改所改变,也可能没有——很难说,因为原文是不清楚的……
If you mean, as others have assumed, setting 0 for every byte of the memory block being freed, then you cannot do that after freeing the block. Attempting to do it yields undefined behaviour. So if you're doing that, then you have badly misunderstood memory allocation.
如果您的意思是,如其他人假设的那样,为正在释放的内存块的每个字节设置0,那么在释放该块之后就不能这样做。试图这样做会产生未定义的行为。如果你这么做,那么你就误解了内存分配。
But I'm guessing when you say "we set it to zero after freeing", you're maybe talking about code like this:
但我猜,当你说“我们在释放后将其设置为0”时,你可能是在说这样的代码:
free(ptr);
ptr = NULL;
If so, then the reason free can't set ptr to NULL, is that free only receives the value from the variable ptr. It has no way of modifying ptr, because you aren't passing the variable ptr itself into free. You're just passing the address currently stored in it. This is part of the design of the C language - when you call a function passing a value, then the callee cannot tell how that value was computed, or what variable might contain it in the caller's code. Making an exception to this language rule just for free would be crazy, even if it were possible.
如果是,那么free不能将ptr设置为NULL的原因是,free只接收来自变量ptr的值。它没有修改ptr的方法,因为你没有将变量ptr本身传递给free。您只是传递当前存储在其中的地址。这是C语言设计的一部分——当您调用一个传递值的函数时,被调用者不能告诉这个值是如何计算的,或者在调用者的代码中包含什么变量。为了免费而对这一语言规则破例将是疯狂的,即使它是可能的。
In any case, not everyone zeroes out pointers after freeing them. Some people think it's a good safety measure, other people think it is not. Whatever you think of it, though, the code doesn't zero the memory, it only zeros the pointer to the memory. If you want to write a function which clears the pointer for you, then you can:
在任何情况下,不是每个人都在释放指针后将指针调零。有些人认为这是一个很好的安全措施,有些人认为不是。不管你怎么想,代码不会把内存归零,它只会把指向内存的指针归零。如果你想写一个函数来为你清除指针,那么你可以:
void free_and_clear(void **pptr) {
free(*pptr);
*pptr = NULL;
}
Then use it like this:
然后像这样使用:
free_and_clear(&ptr);
Note that this passes a pointer to the variable ptr, instead of the value of ptr. So free_and_clear can modify ptr. But this puts some restrictions on how you can use it which don't apply to free - you need a pointer to a modifiable value, rather than just a value.
注意,这会传递一个指向变量ptr的指针,而不是ptr的值。所以free_and_clear可以修改ptr。但这对如何使用它提出了一些限制,这些限制不适用于free——您需要一个指向可修改值的指针,而不仅仅是一个值。
#7
5
memset(ptr, 0, size);
free(ptr);
i think you want this...
我想你想要这个…
#8
3
C was originally designed as a system implementation language, and so C operations are generally as fast and as close to the metal as is practical. One key point in the design philosophy is that you can take several fast operations and make them into one slower and safer operation, but you can't take slower and safer operations and make a faster one.
C最初被设计为一种系统实现语言,因此C操作通常尽可能快和接近金属。设计理念的一个关键要点是,您可以采取几个快速操作,并使它们成为一个更慢和更安全的操作,但您不能采取更慢和更安全的操作,而使一个更快的操作。
If you want a zero-and-free function, you can write one, and use it instead of free()
. If you're concerned with security, I'd recommend it.
如果您想要一个零和*函数,可以编写一个,并使用它而不是free()。如果你担心安全问题,我建议你这么做。
#9
2
Setting the result of a freed pointer to zero may seem to be bullshit, but if the pointer is inadvertently accessed later, you'll get a segfault (at least in a real OS), and the debugger will point to where this abomination is happening. But as others have noted, when you call "free" later, all free has is the address to free, and nothing else.
将释放的指针的结果设置为0似乎是胡扯,但是如果稍后无意中访问指针,您将获得一个segfault(至少在真实操作系统中是这样),调试器将指向发生这种令人厌恶的事情的位置。但正如其他人所注意到的,当你稍后调用“free”时,所有的free都是要free的地址,其他什么都没有。
#10
2
If I understand the question correctly the OP wants to not leave sensitive information "out there" in fear of it being compromised. As the previous posters pointed out freeing the memory before releasing it is the answer to wiping the data.
如果我正确地理解了这个问题,OP希望不留下敏感信息,以免被泄露。正如前面的海报所指出的,在释放内存之前释放内存是清除数据的答案。
However, it is far from the answer to what the OP is trying to achieve. For starters zeroing the memory is 100% useless in securing your application. Even if the memory page is allocated to another running process, in most OSs this procedure is non-deterministic and no sane hacker will EVER use such a technique to compromise your data.
然而,这远不是OP试图实现的目标。对于初学者来说,为内存调零在保护应用程序时是完全无用的。即使内存页被分配给另一个正在运行的进程,在大多数OSs中,这个过程是不确定的,任何理智的黑客都不会使用这种技术来破坏您的数据。
What a sane hacker would do is whack your program into a disassembler and debug through it until they figure out where the data is and then use it. Since a call to memset is bleedingly obvious once you are a competent disassemblerator(yes, disassemblerator :) ) our hypothetical hacker would just get to the data before memset happens.
一个正常的黑客会做的是把你的程序敲进一个反汇编程序,然后通过它进行调试,直到他们找到数据在哪里,然后使用它。因为当你是一个有能力的拆卸器(是的,拆卸器:)的时候,对memset的调用就变得非常明显了,我们假设的黑客在memset发生之前就会得到数据。
To really answer your question. If you are trying to protect some sensitive data inside your C program you are getting in the domain that is far beyond normal C/C++ programmers(like myself) into realm of writing virtual machines for executing your data sensitive operations.
真正回答你的问题。如果您试图在您的C程序中保护某些敏感数据,那么您所处的领域远远超出了普通的C/ c++程序员(如我自己)的范围,从而可以编写用于执行数据敏感操作的虚拟机。
The fact that you even ask this question means that it would be reckless for you to develop something that requires this level of protection. Also it will absolutely not be the first stop in protecting your data. Pick the low hanging fruit first and there is plenty info on the web about that.
事实上,你甚至问了这个问题,这意味着你开发需要这种程度的保护的东西是不顾后果的。而且它绝对不会是保护你的数据的第一站。首先选择低挂的水果,网上有很多关于这个的信息。
#11
1
A very specific answer to the question "Why is the memory not set to 0 after freeing it?" is "Because the language specification does not define that behavior.
对于“为什么在释放内存之后内存没有设置为0”这个问题,一个非常具体的回答是“因为语言规范没有定义这种行为”。
From the draft ANSI C spec: "The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation."
从ANSI C规范草案:“*功能导致ptr指向的空间被释放,也就是说,提供了进一步的分配。”
#13
0
Because it would be a pure waste of time.
因为那纯粹是浪费时间。
#14
0
Once you free memory using free(), the value & the memory allocated at that particular address gets deleted (freed) but the pointer still points to that address. If you try to de-reference that pointer you will get Segmentation fault or Bus error. So, its safe to assign NULL value to the pointer once the memory pointed by the pointer is freed. You may refer < Setting variable to NULL after free >
使用free()释放内存之后,在该特定地址分配的值和内存将被删除(释放),但指针仍然指向该地址。如果您尝试去引用那个指针,您将会得到分割错误或总线错误。因此,在释放指针所指向的内存之后,将空值赋给指针是安全的。您可以将< Setting variable to NULL after free >
#15
0
There's also bzero(3).
还有bzero(3)。
#1
22
Zeroing out the memory block when freeing it will require extra time. Since most of time there's actually no need in it it is not done by default.
清除内存块时,将需要额外的时间。因为大多数时候实际上不需要它,它不是默认的。
If you really need (say you used memory for storing a password or a cryptographic key) - call memset()
before freeing the block. Writing an utility function that chains memset()
and free()
is not a problem either.
如果您确实需要(假设您使用内存存储密码或密码密钥),请在释放块之前调用memset()。编写一个连锁memset()和free()的实用程序函数也不是问题。
#2
6
C why is the memory not explictly set to zero in the free implementation .
为什么在*实现中内存没有明确地设置为零。
Because of speed.
因为速度。
Because after we free the memory any how we set it to zero after freeing.
因为在释放内存之后,我们将内存设置为0。
Eh?
是吗?
#3
6
If you want the memory to be set to 0 when you free it, you'll have to do it yourself before you free()
it. If you try after you free()
it there are no guarantees that it hasn't been allocated again. For instance you can use memset()
for that.
如果要在释放内存时将内存设置为0,那么在释放内存()之前,您必须自己执行。如果您在free()之后尝试,则不能保证没有再次分配它。例如,您可以为此使用memset()。
free()
doesn't guarantee that the memory will be cleared because C doesn't guarantee that malloc()
will return initialized memory. Either way you have to initialize it yourself after it's been allocated, so there's no point in clearing it when it's free()
'd
free()并不保证内存将被清除,因为C不保证malloc()将返回初始化的内存。无论哪种方式,都必须在分配之后自己初始化它,所以在空闲()'d时清除它是没有意义的
#4
6
The original C philosophy was to have keep implicit effects to an absolute minimum. If a programmer wants a pointer zeroed after the memory pointed to is freed, that's what the programmer should write. Those of us who do often use a macro like this one:
最初的C哲学是将隐式效应保持到绝对最小。如果一个程序员想要一个在内存指向被释放后的指针归零,那就是程序员应该写的东西。我们中的一些人经常使用像这样的宏:
#define FREE(P) ((void)(free((P)), (P) = NULL))
Of course if the expression passed to FREE
has side effects, one has just opened a large can of worms...
当然,如果传递给FREE的表达式有副作用,我们就会打开一罐虫子……
#5
6
free() doesn't release memory back to the OS - it releases back to the process's heap manager. For efficiency reasons, it is not zero'd out.
free()不会将内存释放回操作系统——它会将内存释放回进程的堆管理器。出于效率的原因,它并不是零。
When a process allocates virtual memory, most OS's will hand it a zero'd page. This prevents memory from "leaking" from one process to the other and causing a security issue like you mention.
当一个进程分配虚拟内存时,大多数操作系统会给它一个零页。这可以防止内存从一个进程“泄漏”到另一个进程,并像您提到的那样导致安全问题。
If you have data in your process that you don't want to keep in memory (for example, a user's password), you are responsible for zeroing it out. Windows provides the SecureZeroMemory API for this.
如果您的进程中有不想保存在内存中的数据(例如,用户的密码),那么您有责任将其调零。Windows为此提供了SecureZeroMemory API。
#6
6
[Edit: this is an attempt to answer the original poster's question. The question may or may not have been changed by shog9's edit - it's hard to say since the original was unclear...]
[编辑:这是对原海报问题的回答。这个问题可能会被幕府将军的修改所改变,也可能没有——很难说,因为原文是不清楚的……
If you mean, as others have assumed, setting 0 for every byte of the memory block being freed, then you cannot do that after freeing the block. Attempting to do it yields undefined behaviour. So if you're doing that, then you have badly misunderstood memory allocation.
如果您的意思是,如其他人假设的那样,为正在释放的内存块的每个字节设置0,那么在释放该块之后就不能这样做。试图这样做会产生未定义的行为。如果你这么做,那么你就误解了内存分配。
But I'm guessing when you say "we set it to zero after freeing", you're maybe talking about code like this:
但我猜,当你说“我们在释放后将其设置为0”时,你可能是在说这样的代码:
free(ptr);
ptr = NULL;
If so, then the reason free can't set ptr to NULL, is that free only receives the value from the variable ptr. It has no way of modifying ptr, because you aren't passing the variable ptr itself into free. You're just passing the address currently stored in it. This is part of the design of the C language - when you call a function passing a value, then the callee cannot tell how that value was computed, or what variable might contain it in the caller's code. Making an exception to this language rule just for free would be crazy, even if it were possible.
如果是,那么free不能将ptr设置为NULL的原因是,free只接收来自变量ptr的值。它没有修改ptr的方法,因为你没有将变量ptr本身传递给free。您只是传递当前存储在其中的地址。这是C语言设计的一部分——当您调用一个传递值的函数时,被调用者不能告诉这个值是如何计算的,或者在调用者的代码中包含什么变量。为了免费而对这一语言规则破例将是疯狂的,即使它是可能的。
In any case, not everyone zeroes out pointers after freeing them. Some people think it's a good safety measure, other people think it is not. Whatever you think of it, though, the code doesn't zero the memory, it only zeros the pointer to the memory. If you want to write a function which clears the pointer for you, then you can:
在任何情况下,不是每个人都在释放指针后将指针调零。有些人认为这是一个很好的安全措施,有些人认为不是。不管你怎么想,代码不会把内存归零,它只会把指向内存的指针归零。如果你想写一个函数来为你清除指针,那么你可以:
void free_and_clear(void **pptr) {
free(*pptr);
*pptr = NULL;
}
Then use it like this:
然后像这样使用:
free_and_clear(&ptr);
Note that this passes a pointer to the variable ptr, instead of the value of ptr. So free_and_clear can modify ptr. But this puts some restrictions on how you can use it which don't apply to free - you need a pointer to a modifiable value, rather than just a value.
注意,这会传递一个指向变量ptr的指针,而不是ptr的值。所以free_and_clear可以修改ptr。但这对如何使用它提出了一些限制,这些限制不适用于free——您需要一个指向可修改值的指针,而不仅仅是一个值。
#7
5
memset(ptr, 0, size);
free(ptr);
i think you want this...
我想你想要这个…
#8
3
C was originally designed as a system implementation language, and so C operations are generally as fast and as close to the metal as is practical. One key point in the design philosophy is that you can take several fast operations and make them into one slower and safer operation, but you can't take slower and safer operations and make a faster one.
C最初被设计为一种系统实现语言,因此C操作通常尽可能快和接近金属。设计理念的一个关键要点是,您可以采取几个快速操作,并使它们成为一个更慢和更安全的操作,但您不能采取更慢和更安全的操作,而使一个更快的操作。
If you want a zero-and-free function, you can write one, and use it instead of free()
. If you're concerned with security, I'd recommend it.
如果您想要一个零和*函数,可以编写一个,并使用它而不是free()。如果你担心安全问题,我建议你这么做。
#9
2
Setting the result of a freed pointer to zero may seem to be bullshit, but if the pointer is inadvertently accessed later, you'll get a segfault (at least in a real OS), and the debugger will point to where this abomination is happening. But as others have noted, when you call "free" later, all free has is the address to free, and nothing else.
将释放的指针的结果设置为0似乎是胡扯,但是如果稍后无意中访问指针,您将获得一个segfault(至少在真实操作系统中是这样),调试器将指向发生这种令人厌恶的事情的位置。但正如其他人所注意到的,当你稍后调用“free”时,所有的free都是要free的地址,其他什么都没有。
#10
2
If I understand the question correctly the OP wants to not leave sensitive information "out there" in fear of it being compromised. As the previous posters pointed out freeing the memory before releasing it is the answer to wiping the data.
如果我正确地理解了这个问题,OP希望不留下敏感信息,以免被泄露。正如前面的海报所指出的,在释放内存之前释放内存是清除数据的答案。
However, it is far from the answer to what the OP is trying to achieve. For starters zeroing the memory is 100% useless in securing your application. Even if the memory page is allocated to another running process, in most OSs this procedure is non-deterministic and no sane hacker will EVER use such a technique to compromise your data.
然而,这远不是OP试图实现的目标。对于初学者来说,为内存调零在保护应用程序时是完全无用的。即使内存页被分配给另一个正在运行的进程,在大多数OSs中,这个过程是不确定的,任何理智的黑客都不会使用这种技术来破坏您的数据。
What a sane hacker would do is whack your program into a disassembler and debug through it until they figure out where the data is and then use it. Since a call to memset is bleedingly obvious once you are a competent disassemblerator(yes, disassemblerator :) ) our hypothetical hacker would just get to the data before memset happens.
一个正常的黑客会做的是把你的程序敲进一个反汇编程序,然后通过它进行调试,直到他们找到数据在哪里,然后使用它。因为当你是一个有能力的拆卸器(是的,拆卸器:)的时候,对memset的调用就变得非常明显了,我们假设的黑客在memset发生之前就会得到数据。
To really answer your question. If you are trying to protect some sensitive data inside your C program you are getting in the domain that is far beyond normal C/C++ programmers(like myself) into realm of writing virtual machines for executing your data sensitive operations.
真正回答你的问题。如果您试图在您的C程序中保护某些敏感数据,那么您所处的领域远远超出了普通的C/ c++程序员(如我自己)的范围,从而可以编写用于执行数据敏感操作的虚拟机。
The fact that you even ask this question means that it would be reckless for you to develop something that requires this level of protection. Also it will absolutely not be the first stop in protecting your data. Pick the low hanging fruit first and there is plenty info on the web about that.
事实上,你甚至问了这个问题,这意味着你开发需要这种程度的保护的东西是不顾后果的。而且它绝对不会是保护你的数据的第一站。首先选择低挂的水果,网上有很多关于这个的信息。
#11
1
A very specific answer to the question "Why is the memory not set to 0 after freeing it?" is "Because the language specification does not define that behavior.
对于“为什么在释放内存之后内存没有设置为0”这个问题,一个非常具体的回答是“因为语言规范没有定义这种行为”。
From the draft ANSI C spec: "The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation."
从ANSI C规范草案:“*功能导致ptr指向的空间被释放,也就是说,提供了进一步的分配。”
#12
#13
0
Because it would be a pure waste of time.
因为那纯粹是浪费时间。
#14
0
Once you free memory using free(), the value & the memory allocated at that particular address gets deleted (freed) but the pointer still points to that address. If you try to de-reference that pointer you will get Segmentation fault or Bus error. So, its safe to assign NULL value to the pointer once the memory pointed by the pointer is freed. You may refer < Setting variable to NULL after free >
使用free()释放内存之后,在该特定地址分配的值和内存将被删除(释放),但指针仍然指向该地址。如果您尝试去引用那个指针,您将会得到分割错误或总线错误。因此,在释放指针所指向的内存之后,将空值赋给指针是安全的。您可以将< Setting variable to NULL after free >
#15
0
There's also bzero(3).
还有bzero(3)。