這是我之前的question regarding exceptions的後續行動。有沒有更好的方法來實現這種內存管理?
我有一些遺留代碼,我試圖維護。它有一個我很難理解的自定義內存管理組件。
我的對系統的理解如下:
調用功能要求一個將要分配給它的一些存儲器,提供所需的存儲器中的初始量(needed
),和最大量(max
)。這就要求:
base = VirtualAlloc(0, max, MEM_RESERVE, PAGE_NOACCESS);
我的理解保留內存,但不提供訪問。換句話說,如果我嘗試寫入保留段,我會得到訪問衝突。
然後調用:
VirtualAlloc(base, needed, MEM_COMMIT, PAGE_READWRITE);
這使得起始於base
訪問needed
的內存量。
當試圖檢測何時需要訪問更多內存時,粘滯部分會出現。我的理解是系統嘗試在發生訪問衝突異常時捕獲並在地址上調用VirtualAlloc
以使內存可訪問。
它通過聲明以下方法不這樣:
unsigned long __cdecl
exceptionCatch(struct _EXCEPTION_RECORD* er, void*, struct _CONTEXT* cr, void*)
{
if(er->ExceptionCode == EXCEPTION_ACCESS_VIOLATION
&& ExtendBuffer((void*)er->ExceptionInformation[1]))
return ExceptionContinueExecution;
return ExceptionContinueSearch;
}
然後,它註冊以此作爲堆棧(我認爲)的頂部的異常處理程序,使用該特別可怕一段代碼:
void __cdecl SetHandler(bExceptionRegistration& v)
{
__asm
{
mov eax, 8[ebp] ; get exception register record to install
mov ecx, fs:[0] ; get current head of chain
cmp ecx, eax ; should we be at head?
jb search
mov [eax], ecx ; save current head
mov fs:[0], eax ; install new record at head
jmp short ret1
search:
cmp [ecx], eax ; at proper location yet?
ja link
mov ecx, [ecx] ; get next link
jmp search
link:
mov edx, [ecx]
mov [eax], edx ; point to next
mov [ecx], eax
ret1:
}
}
通過實例化方法範圍中的特定類來調用此方法。它看起來只是將處理程序應用於當前的堆棧上下文;和in一樣,如果異常不會傳播到當前方法,則在當前方法中不會處理被調用函數中拋出的異常。
所有這些的結果是,不僅沒有捕獲到訪問衝突,而且它禁用了當前堆棧頂部的異常處理。我在exceptionCatch
函數中設置了斷點,並且執行看起來不會進入它。
我想我的主要問題是:
- 有什麼特別的原因,爲什麼這不應該工作? 編輯:根據我自己的測試和評論在這裏,我認爲彙編代碼是問題領域。
- 更重要的是,有沒有更好的方式來做我認爲代碼試圖做的事情?
我不認爲像set_unexpected
是可行的,因爲內存管理只適用於這個特定的庫和客戶端應用程序可以(在我們的情況下,確實)有自己的意外的異常處理程序。
編輯:
設置和每個堆棧的處理程序不落的是通過聲明一個類bExceptionRegistration
下面的類構造函數和析構函數來完成:
bExceptionRegistration :: bExceptionRegistration() : function(exceptionCatch)
{
SetHandler(*this);
}
bExceptionRegistration :: ~bExceptionRegistration()
{
UnsetHandler(*this);
}
因此,實際設置處理對於特定的堆棧範圍,您將擁有:
void someFunction()
{
bExceptionRegistration er;
// do some stuff here
}
編輯:我猜可能是所有這些最合適的解決方案是用代碼__try, __except
塊代替bExceptionRegistration
聲明。然而,我希望避免這種情況,因爲它在很多地方。
處理程序的安裝看起來很可疑。無論如何,有一個例子在http://msdn.microsoft.com/en-us/library/windows/desktop/aa366803%28v=vs.85%29.aspx –
我想最初的意圖是做同樣的事情'__try,__except'實際上並沒有用很多這些子句點代碼。這很有幫助,謝謝! – tvStatic
這段代碼的想法似乎與我的[這裏](http://stackoverflow.com/q/8004945/968261)類似,只是你的代碼不太清楚。這種方法的問題是,需要非常小心地執行try,__try和異常過濾器,以免吞下或禁用其他人的異常或損壞程序狀態。 –