我有一个疑问:
void *a = malloc(40);
free(a);
如果我认为 malloc(40) 分配了 40 字节的内存并返回该内存的地址,然后 free(a) 解除/释放了该内存,但不对该内存中的位模式执行任何操作。因此,假设分配了相同的内存以表示void *b,然后在打印b指向的地址处的值时,给了我相同的值,或者它给了我一个垃圾值,为什么?
我假设你有这种情况:
void * a = malloc(40);
free(a);
void * b = malloc(40);
assert(a == b);
这当然是完全合理的,因为内存可能会被重用。
但是,自a == b
年以来,您已经回答了自己的问题:b
的值与a
的值相同!
我相信你问错了问题,你实际上对比较b
所指的记忆感兴趣。那是完全不同的一壶鱼。在两次malloc
通话之间可能发生任何事情。没有什么是可以保证的。malloc
调用的返回值所指向的内存未初始化,您无法对其内容做出任何假设。按理说,在典型的、优化的 C 库中,内存不会发生变化,但不能保证。"安全"运行时环境可能会选择使用特定的测试模式覆盖释放或分配的内存,以便更好地检测无效访问。
它可以给你任何价值。
C/C++ 标准并不要求值是任何特定的。在技术术语中,任何未初始化的变量/内存的值都是不确定的。
简而言之,您的程序不应依赖此值作为特定值,如果它特定,则它是不可移植的。
它不能保证任何事情。从malloc获得的打印块可能会打印以前的数据,也可能不会。有很多东西可以改变下一个malloc块(所以下一个地址会不同)或改变旧的内存块本身。
free通常会修改您释放的内存。
这是一个常见的技巧,尤其是在调试模式下,可以免费使用一些固定模式覆盖内存,以便更容易判断您是在双重释放内存,还是只是操作释放的内存。
同样,malloc 可能会用不同的模式覆盖内存,以明显表明内存未初始化。
>malloc 和 free 是 C 风格的内存管理,而不是 C++。C++替代项是新的和删除运算符。至于free()之后留在内存中的位模式,是的,它是相同的位模式。如果要手动删除位模式,可以在编写 WinApi 代码时使用 memset() 或 ZeroMemory()。
它会给你一些垃圾值,因为函数free()会将指定的字节设置为某种模式,这将使内存知道字节被释放和未初始化。话虽如此,您不太可能也极不可能遇到问题中定义的情况。即使你会再次被分配相同的字节,相信我,你绝不会认出它们:-)
AFAIK,free()通常将内存设置为与Visual Studio 0xFE 0xEE,这大致意味着内存已分配,但现在已释放。这些值称为Sentinel 值,这意味着堆仍归进程所有,但未在使用中。从过程中释放的内存将显示"?? ??"。
首先,代码不是 c++,而是普通的 c。
原因是,那里存在free()
/delete
,因此系统可以注意到内存区域再次可用于分配。
为什么它应该做任何事情?
但是,这是一个安全问题。我相信一些面向安全的现代系统在将内存提供给应用程序之前会将其归零。然后,如果您第一次使用malloc()
,您将获得与calloc等效的。无论如何,如果您碰巧释放了内存,然后再次分配它,则可能能够读取自己的数据。
这种行为的简单原因很简单。将内存归零将非常耗时,您可以手动完成。实际上,它O(n)
复杂。如果你写了一个重用其内存的数字运算器,你不在乎你在malloc()
之后得到什么,因为很可能你应该覆盖它,而且你绝对不希望你的 FLOPS 在调用free()
时受到不必要的memset()
的负面影响。
如果要确保调用后没有任何内容可以读取内存free
则需要在调用free()
之前使用memset(a, 0, SIZE)
。