有沒有一種方法可以僅從其記憶體地址來識別物件是存盤在堆疊上還是堆上?我問是因為在除錯和記憶體地址出現錯誤時知道這一點會很有用。
例如:
如果有記憶體地址:0x7fd8507c6
我可以根據該地址確定有關物件的任何資訊嗎?
uj5u.com熱心網友回復:
您沒有提及您使用的是哪個作業系統。我將回答 Microsoft Windows,因為這是我過去 25 年來一直在使用的那個。我已經忘記了我對 Unix/Linux 的大部分了解。
如果您只有地址而沒有其他資訊 - 對于 32 位 Windows,您可以判斷它是用戶空間(低 2GB)還是內核空間(高 2GB),但僅此而已(假設您沒有 /3GB 引導選項)。
如果您有地址并且可以運行一些代碼,則可以使用 VirtualQuery() 來獲取有關地址的資訊。如果你得到一個非零的回傳值,你可以使用回傳的 MEMORY_BUFFER_INFORMATION 資料中的資料。
State、Type 和 Protect 值將告訴您記憶體的可能用途 - 無論是記憶體映射、DLL (Type & MEM_IMAGE != 0) 等。如果記憶體是執行緒的堆疊或者它是否在堆中。但是,您可以確定地址是否在不是堆或堆疊的記憶體中(DLL 中的記憶體不在堆疊或堆中,不可訪問的記憶體不在堆疊或堆中)。
要確定執行緒堆疊在哪里,您可以檢查應用程式中的所有頁面,在執行緒堆疊的末尾尋找保護頁面。然后,您可以使用存盤在 PE 標頭中的默認堆疊大小來推斷堆疊空間的位置(或者如果您不能這樣做,只需使用 1MB 的默認大小 - 很少有人更改它)和您擁有的地址(是它在您推斷的空間中?)。
要確定地址是否在記憶體堆中,您需要列舉應用程式堆(GetProcessHeaps()),然后列舉每個堆(HeapWalk()),檢查堆管理的區域。并非所有 Windows 堆都可以列舉。
要獲得更多資訊,您需要跟蹤每個堆的分配/解除分配等,并存盤所有這些資訊以供使用。
您還可以跟蹤執行緒何時創建/銷毀/退出并以這種方式計算執行緒地址。
根據我創建記憶體泄漏檢測工具(需要此資訊)和許多其他工具的經驗,這是一個廣泛的答案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/519698.html
