高级话题:P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
时间:2010-10-13 来源:不及格的程序员-八神
作者:不及格的程序员
情况描述:
我在win32 dll 项目中封装了段asm代码调用另一个dll中的函数. 在我的win32 dll项目中公开的函数声明如下:
1 extern "C" _declspec(dllexport) void No(const char* source, char* result)2 {
3 _asm
4 {
5 mov eax, source
6 push eax
7 mov eax, result
8 push eax
9 call pFun //pFun 是我从另一个dll中用GetProcAddress函数提取的函数地址,这个函数规则是被调用者清除栈;
10 //下面使用eax寄存器,向调用者返回结果,而实际上我们的函数声明并没有返值,这种调用在我的winxp上调用是成功的.
11 //但是在另一台win7系统中,当这此函数返回时却总是失败,报异常.
12 //由于我的最终项目是wcf项目托管于iis7下,当发生异常时,提示ntdll堆被破坏.....
13 mov eax,dword ptr [result]
14 add eax,1
15 mov dword ptr [result],eax
16 }
17 }
下面是我在C#项目中声明的函数导入代码;
[DllImport("No.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern void No(string strArg0, byte[] strArg1); //此种调用方式,在winxp,win7系统都可以正常运行,结果是通过strArg1传递的.
//注意:下面代码声明了string类型的返回值,也就是获取eax返回的地址.
private static extern string No(string strArg0, byte[] strArg1);
此种调用方式不能在win7系统下运行,但也是仅仅是第一次报异常,当第二次调用此函数时,就可以通过返回值取到结果.
我的问题是为什么这种方式会报异常呢?
难道win7下CLR jit编译做了更严格的内存检查吗?
或者与JIT没有关系,而是由于系统api的低层函数有更多的检查呢?
我目前还没有找到这个问题所在,但我非常有兴趣....想知道原因,与大家共同讨论一次吧.
相关阅读 更多 +