我用VC6仿照ATL中的thunk做了一个在我的thunk中会遇到DEP错误,可是我用wtl做的窗口程序缺可以正确运行。我知道DEP是怎么一回事,可是ATL的窗口类和thunk也是建立在堆栈上的,没用VirtualAlloc分配内存,为什么能顺利执行呢?我的thunk代码基本和atl中的是一样,这是为什么呢?

解决方案 »

  1.   

    基本一样不代表完全一样。thunk受芯片影响,看看ATL中的thunk定义,是分成不同平台进行条件编译的,或许你参考了错误的平台版本。
      

  2.   

    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;
        }
      

  3.   

    我看的是ATL3.0,它的确没用VirtualAlloc。我知道用VirtualAlloc可以避免DEP的问题。可是我在VC6.0下使用WTL建立工程,它的thunk是窗口类的数据成员,而窗口类是在堆栈上创建的。VC6编译出的WTL程序在DEP下依旧能正确运行。但我的thunk如果在堆栈上创建,程序在DEP下是无法运行的。这是另我费解的地方,我想知道ATL3.0究竟利用了操作系统或者处理器的什么特性,能够避免DEP。用VirtualAlloc创建thunk有一个我不太喜欢的地方:必须去管理VirtualAlloc分配的内存。这个问题我发重复了,我在
    http://topic.csdn.net/u/20090313/12/f726abd7-2a6a-4284-9b21-2e1db56c14a4.html
    列有ATL和我的thunk的汇编代码,你可以看看。
      

  4.   

    手头没有ATL3.0的代码,无法判断文件的改变有多大,但大致应该差不多,最终的thunk实例肯定不是在栈上创建的,而是用new分配的,最终thunk类重载了new操作符。
      

  5.   

    为什么我使用thunk就没遇到过DEP的问题呢?
    我没用VirtualAlloc
    DEP是开启的
    但还是运行得好好的
    难道是我的物理内存不够大,所以分配到虚拟内存了?
      

  6.   

    ATL3出来时那还是98年,DEP还没出来,不可能采用避免DEP的技术。
    DEP的设计者不能让原先正常运行ATL程序一下子全都崩溃了,所以DEP有一条“豁免”规则。DEP看到窗口过程或对话框过程试图执行形如C7 44 24 04 ?? ?? ?? ?? E9 ?? ?? ?? ?? 的代码时,放行。
    后来的WTL7,WTL8虽说是兼容ATL3,但是考虑的不周全。比如,ATL3+WTL8,使用CPageSetupDlg,在开启DEP的机子上运行,就会崩溃。因为此thunk替换的不是窗口过程也不是对话框过程。