是否有可能發現一段內存被野指針修改了?
如題,
在C中,1. 一個野指針(如未初始化或者已經釋放了的指針等),其地址恰好落在某一塊使用中的內存中,並且進行了寫入,就會導致數據錯誤。2. 如果落在了mmap的地址空間內,甚至會錯誤修改文件。
像這種情況,是否存在方法去檢測內存有沒有被野指針修改。我自己想的方案可能有兩個,1. 通過某種內存池進行管理,有可能能檢測到。但暫時沒有進一步想法。
2. 備份內存,每次進行比對是否一致。但這個方法有兩個缺點,2.1. 不適用大塊內存,效率慢2.2. 不適合大範圍改,只能在小範圍代碼使用,否則修改量太大。
如果是查bug的話,用mprotect保護可能被寫壞的內存區,並且用backtrace來判斷是否是符合預期的寫入邏輯。ob的竹翁曾經用此法查過一個很隱蔽的bug
附上 竹翁(@楊志豐) 當時分享的blog 走下神壇的內存調試器--定位多線程內存越界問題實踐總結
如果你經過若干次debug知道這個指針是多少,你可以在VS裡面下一個數據斷點,被改的時候立刻停下來。
你所說的是C語言最大的坑,我覺得沒有之一,對野指針的各種吐槽已經很多,我也不錦上添花了。說解決方法,還是有的,只是調試非常複雜。對於你所說的可能寫文件,可能修改其它內存等等,出現的癥狀是不確定的,一般而言有概率會出現COREDUMP,針對COREDUMP做分析就可以了。
把未初始化的數據初始化為某個值,最好對應指針是非法地址空間,如5a,a5啥的,看操作系統內存映射,x64位系統無論5a還是a5都是非法地址,這樣可以找出靜態數據裡面的未初始化指針,對於動態分配內存,修改分配入口,對分配的數據進行初始化,5a或者a5。至於delete,可以用偽釋放,即實際不釋放內存,初始化為某個值,然後加入隊列,然後遍歷隊列判斷值是否改變即可。
如果bug已經發生並且知道修改地址,可以裡面內存斷點調試
有可能,但具體原理我不是很清楚,我跟你胡謅一個。
有個神奇的工具,叫做 Valgrind,可以檢查各種內存問題。Intel Inspector XE 是另一個知名的內存問題檢查工具。
Your program is then run on a synthetic CPU provided by the Valgrind core. As new code is executed for the first time, the core hands the code to the selected tool. The tool adds its own instrumentation code to this and hands the result back to the core, which coordinates the continued execution of this instrumented code.
Valgrind 實際上是將程序運行在沙箱里。
如果能在每個 memory access 的地方都檢查一遍,顯然是可以達到目的的——順便還可以檢查uninitialized stack access,但是代價非常高。Intel Inspector XE 表示會有 60-80x 的 time overhead,我推測它的技術應該和valgrind相似。
微軟開發支持(收費服務)曾經要求DUMP內存分析。結果故障過了沒數據,也就不了了之
@vczh 答案顯然不能用在實際的程序運行過程中,其他人的方法代價太高不可行。簡單的來說,解決這個問題的難點在於如何對memory進行高效的監測,這種問題一看就知道必須使用硬體特性,否則代價無法忍受。實際上,這已經屬於一個學術問題,open question. 學術屆也已經有了相關的研究,運用的是 HTM (Hardware transactional memory) 和硬體虛擬化技術,用來方便、快速、高效地檢測惡意程序是否擅自修改了用戶進程或者 kernel 內存。有興趣的話可以看看 HPCA 14 的best paper &
如果是檢測一塊內存是否被修改,可以利用內存寫入斷點的原理,Windows下可以用VirtualProtectEx函數修改那一塊內存的讀寫屬性為PAGE_EXECUTE_READ,然後用SEH接收異常就好了,觸發了異常就是內存被寫入了,至於如何判斷這個寫入是不是野指針乾的,個人感覺難度較大
推薦閱讀:
※如何設計內存池?
※為什麼調用 std::map::clear() 後內存佔用率沒有降低?
※最近電腦每次開機內存佔用與上次關機時差不多,只有重啟後內存才會降到20左右,這是怎麼回事啊?
※電腦內存突然佔用過多是為什麼?
※如何理解 Objective-C 中的 strong 和 weak ?