SORRY,看错你的原意了,所以不介意你的嘲讽。不知道你从哪确定ATL没有调用VirtualAlloc的?看看源码就知道了,ATL并不特殊,它一样需要调用VirtualAlloc,但是它会判断当前环境是不是支持DEP来决定使用HeapAlloc还是使用VirtualAlloc。看看它的调用代码片段: if (ATLTHUNK_USE_HEAP()) { // <------ 这里判断DEP环境是否调用标准堆 // // On a non-NX capable platform, use the standard heap. // thunkEntry = (PATL_THUNK_ENTRY)HeapAlloc(GetProcessHeap(), 0, sizeof(ATL::_stdcallthunk)); if (thunkEntry == NULL) { goto outOfMemory; } return thunkEntry; } // // Attempt to pop a thunk structure from the list and return it // thunkEntry = (PATL_THUNK_ENTRY)__AtlInterlockedPopEntrySList(__AtlThunkPool); if (thunkEntry != NULL) { return &thunkEntry->Thunk; } // ------- 下面就是啦 ---------- // // The thunk list was empty. Allocate a new page of executable // memory. // thunkPage = (PATL_THUNK_ENTRY)VirtualAlloc(NULL, PAGE_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (thunkPage == NULL) { goto outOfMemory; }
// On a non-NX capable platform, use the standard heap.
// thunkEntry = (PATL_THUNK_ENTRY)HeapAlloc(GetProcessHeap(),
0,
sizeof(ATL::_stdcallthunk));
if (thunkEntry == NULL) {
goto outOfMemory;
} return thunkEntry;
} //
// Attempt to pop a thunk structure from the list and return it
// thunkEntry = (PATL_THUNK_ENTRY)__AtlInterlockedPopEntrySList(__AtlThunkPool);
if (thunkEntry != NULL) {
return &thunkEntry->Thunk;
} // ------- 下面就是啦 ----------
//
// The thunk list was empty. Allocate a new page of executable
// memory.
// thunkPage = (PATL_THUNK_ENTRY)VirtualAlloc(NULL,
PAGE_SIZE,
MEM_COMMIT,
PAGE_EXECUTE_READWRITE);
if (thunkPage == NULL) {
goto outOfMemory;
}
http://topic.csdn.net/u/20090313/12/f726abd7-2a6a-4284-9b21-2e1db56c14a4.html
列有ATL和我的thunk的汇编代码,你可以看看。
我没用VirtualAlloc
DEP是开启的
但还是运行得好好的
难道是我的物理内存不够大,所以分配到虚拟内存了?
DEP的设计者不能让原先正常运行ATL程序一下子全都崩溃了,所以DEP有一条“豁免”规则。DEP看到窗口过程或对话框过程试图执行形如C7 44 24 04 ?? ?? ?? ?? E9 ?? ?? ?? ?? 的代码时,放行。
后来的WTL7,WTL8虽说是兼容ATL3,但是考虑的不周全。比如,ATL3+WTL8,使用CPageSetupDlg,在开启DEP的机子上运行,就会崩溃。因为此thunk替换的不是窗口过程也不是对话框过程。