简体   繁体   English

释放后是否可以强制Linux使虚拟内存无效

[英]Is it possible to force Linux to invalidate virtual memory after free

On Windows, I have noticed that trying to dereference a pointer to recently freed memory results in a crash, trapped by Visual Studio stating that the memory is invalid. 在Windows上,我注意到尝试取消对最近释放的内存的指针的引用会导致崩溃,Visual Studio捕获该崩溃,指出该内存无效。 This is as expected. 这是预期的。 However, executing the same application and code path leading to dereferencing a pointer to recently freed memory does not immediately cause a crash in Linux. 但是,执行相同的应用程序和代码路径导致取消对最近释放的内存的指针的引用不会立即导致Linux崩溃。 This suggests to me that the Linux kernel (or GNU C++ run-time) does not invalidate freed memory very quickly, even on debug builds. 这向我表明,即使在调试版本中,Linux内核(或GNU C ++运行时)也不会很快使释放的内存无效。 The application takes much longer to crash. 该应用程序需要更长的时间才能崩溃。 Is this the case? 是这样吗 If so, can I force the memory to be unmapped more quickly? 如果是这样,我可以强制更快地取消对内存的映射吗? If not then what's going on? 如果没有,那是怎么回事?

Have you tried http://valgrind.org/ ? 您尝试过http://valgrind.org/吗? It's purpose is to help track down problems such as the one you've described. 目的是帮助跟踪问题,例如您所描述的问题。

Most implementations of new / delete do not return memory immediately to the system, or at least don't return smaller blocks. 大多数new / delete实现都不会立即将内存返回给系统,或者至少不会返回较小的块。 I'm rather surprised that your code crashed under Windows simply by dereferencing a pointer to the memory; 令您惊讶的是,您的代码仅通过取消引用指向内存的指针而在Windows下崩溃了; are you sure you didn't do more than that (eg use the value you read through the pointer). 您确定自己没有做更多的事情(例如,使用通过指针读取的值)。

How big was the block? 块有多大? Many implementations use different strategies depending on the size of the block, and will free very large blocks immediately. 许多实现根据块的大小使用不同的策略,并且会立即释放非常大的块。 (IIRC, Linux will do a mmap immediately for very large blocks, and unmap it immediately when you free it. Of course, if you reallocate memory between the free and dereferencing the pointer, it's possible that the address is in the newly allocated space, and it won't crash.) (IIRC,Linux会立即对非常大的块执行mmap ,并在释放它时立即取消映射。当然,如果您在释放和取消引用指针之间重新分配内存,则地址可能在新分配的空间中,而且不会崩溃。)

In the end: the granularity of mapping is the page, and you cannot expect the allocator to block up a complete page for each allocation, just so that it can invalidate the memory immediately on deallocation. 最后:映射的粒度是页面,您不能指望分配器会为每个分配阻塞一个完整的页面,只是这样它就可以在释放时立即使内存无效。 (A page is probably at least 4K, and you don't want to loose 4K address space each time you allocate 16 bytes.) Short of tracking all memory accesses (like ValGrand or Purify), and running a lot slower, the only alternative is to use garbage collection, to ensure that the memory isn't reallocated as long as there is a pointer to it, and overwrite it completely on deallocation (ie in delete or free ) with values that are likely to cause problems if used ( 0xDEADBEEF , or something like that). (一个页面可能至少为4K,并且您不想每次分配16个字节时就释放4K地址空间。)缺少跟踪所有内存访问(如ValGrand或Purify)的方法,并且运行速度慢得多,这是唯一的选择是使用垃圾回收,以确保只要有指向它的内存就不会重新分配内存,并在释放时(例如,在deletefree )使用可能会引起问题的值( 0xDEADBEEFdelete其完全覆盖, 或类似的东西)。 And even then, you're not really guaranteed that you'll crash— 0xDEADBEEF could be a valid value for what you think you're reading. 即使这样,也不能保证会崩溃— 0xDEADBEEF对于您所阅读的内容可能是有效的值。 (But this does allow eg setting a flag in the constructor, resetting it in the destructor, and testing it in each function. For code that has to be actively defensive.) (但这确实允许例如在构造函数中设置标志,在析构函数中将其重置以及在每个函数中对其进行测试。对于必须主动防御的代码。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM