Advanced Debugging
About AdvDbg Consult Train Services Products Tools Community Contact  
欢迎光临 高端调试 登录 | 注册 | FAQ
 
  ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
 
  格蠹调试套件(GDK)
  格蠹学院
  小朱书店
  老雷的微博
  《软件调试》
  《格蠹汇编》
  《软件调试(第二版)》
沪ICP备11027180号-1

.Net程序调试

帖子发起人: 不及格的程序员-八神   发起时间: 2010-10-13 15:30 下午   回复: 10

Print Search
帖子排序:    
   2010-10-13, 15:30 下午
ioriwellings 离线,最后访问时间: 2011/1/4 2:56:38 不及格的程序员-八神

发帖数前50位
男
注册: 2009-11-11
发 贴: 22
P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
情况描述:

我在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的低层函数有更多的检查呢?

我目前还没有找到这个问题所在,但我非常有兴趣....想知道原因,与大家共同讨论一次吧.
不及格的程序员-八神
IP 地址: 已记录   报告
   2010-10-13, 15:51 下午
ioriwellings 离线,最后访问时间: 2011/1/4 2:56:38 不及格的程序员-八神

发帖数前50位
男
注册: 2009-11-11
发 贴: 22
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
张老师,你有Intel 指令集参考手册 的中文版pdf吗?
不及格的程序员-八神
IP 地址: 已记录   报告
   2010-10-13, 17:44 下午
s5689412 离线,最后访问时间: 2015/10/10 9:37:32 sPhinX

发帖数前25位
注册: 2008-06-28
发 贴: 50
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
中文版......,这个东西硬邦邦的,翻译成中文看不懂的还是看不懂,还不如看原文准确,应该没有人翻译这个吧?
IP 地址: 已记录   报告
   2010-10-13, 23:52 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
我也有兴趣, :-)要看一下哪里出异常, 把能重现问题的执行文件发给我一份,我来看一下
关于IA32 SDM,国内的确有个兴趣小组翻译过, 搜索一下应该可以搜到, 记得本站的一个朋友参与过这个翻译

IP 地址: 已记录   报告
   2010-10-14, 09:07 上午
ioriwellings 离线,最后访问时间: 2011/1/4 2:56:38 不及格的程序员-八神

发帖数前50位
男
注册: 2009-11-11
发 贴: 22
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?

附件: TestRelease.rar
Reply Quote
我目前只有这本.还算不错

英特尔64和IA-32架构软件开发人员的手册卷3 中文版-部分

花了一点时间 针对这次的问题写了一个Demo.
附件里是Release版的测试程序.
可以在xp下正常运行,但是放到win7下会出错.

下面的贴子我会贴上源码工程,可以在调试模式(F5)运行能发现异常的报告,但是以非调试(Ctrl+F5)就不会提示异常可以正常运行.
非常有意思.
不及格的程序员-八神
IP 地址: 已记录   报告
   2010-10-14, 10:48 上午
ioriwellings 离线,最后访问时间: 2011/1/4 2:56:38 不及格的程序员-八神

发帖数前50位
男
注册: 2009-11-11
发 贴: 22
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?

附件: TestInvoke.rar
Reply Quote
源码工程,包含win32dll与托管项目,我已设好依赖项.

不及格的程序员-八神
IP 地址: 已记录   报告
   2010-10-14, 22:45 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
原因是把返回值声明成了string,即:
private static extern string TestFunA(byte[] result);
对于PInvoke函数,返回值如果声明为string,那么CLR便认为,被调用的函数是使用CoTaskMemAlloc分配的内存,而且需要CLR来释放这个内存。异常正是释放返回的内存时发生的。
声明可以改为:
[DllImport("TestedDLL.dll", EntryPoint = "TestFun", CallingConvention = CallingConvention.Cdecl)]
private static extern System.IntPtr TestFunB(byte[] result);

对应的函数可以改为:
var result = new byte[36];
IntPtr returnValue = TestFunB(result);
MessageBox.Show("result:" + System.Text.Encoding.Default.GetString(result));
MessageBox.Show("eax: " + Marshal.PtrToStringAnsi(returnValue));

IP 地址: 已记录   报告
   2010-10-15, 09:28 上午
ioriwellings 离线,最后访问时间: 2011/1/4 2:56:38 不及格的程序员-八神

发帖数前50位
男
注册: 2009-11-11
发 贴: 22
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
张老师,您是通过调试的手段发现这个问题的还是之前看过关于clr平台调用时内存分配规则的描述呢?
msdn上有一些文章描述了您说的这种情况,而且还有些是与win具体版本有关,比如vista也会出问题.

下面是调试的调用栈:
ntdll.dll!_DbgBreakPoint@0()
ntdll.dll!_RtlpBreakPointHeap@4() + 0x28 字节
ntdll.dll!_RtlpValidateHeapEntry@12() + 0x113 字节
ntdll.dll!_RtlDebugFreeHeap@12() + 0x97 字节
ntdll.dll!_RtlFreeHeapSlowly@12() + 0x228bf 字节
ntdll.dll!_RtlFreeHeap@12() + 0x17646 字节
ole32.dll!CRetailMalloc_Free() + 0x1c 字节
ole32.dll!_CoTaskMemFree@4() + 0x13 字节
[托管到本机的转换]
mscorlib.dll!System.StubHelpers.CSTRMarshaler.ClearNative(System.IntPtr pNative) 行 111 + 0x1c 字节 C#
TestInvoke.exe!TestInvoke.Form1.btnError_Click() C#

我看到了的确调用了那个清除内存的方法,但是我却在反汇编里看不到谁调用了ClearNative方法呢????
是由于函数返回时,clr马上调用了它,而在我们的反汇编代码里没有体现吗?


不及格的程序员-八神
IP 地址: 已记录   报告
   2010-10-15, 20:09 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
通过调试看到,CoTaskMemFree在释放DLL里的常量...
IP 地址: 已记录   报告
   2010-10-19, 17:13 下午
ioriwellings 离线,最后访问时间: 2011/1/4 2:56:38 不及格的程序员-八神

发帖数前50位
男
注册: 2009-11-11
发 贴: 22
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
可是即使是clr在回收内存,为什么Release版能够在xp中运行通过,
而在win7则不能呢? 哪些新的规则在限制着它呢?
不及格的程序员-八神
IP 地址: 已记录   报告
   2010-10-19, 22:56 下午
Raymond 离线,最后访问时间: 2020/7/3 3:40:25 格蠹老雷

发帖数前10位
注册: 2005-12-19
发 贴: 1,303
Re: P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?
Reply Quote
错误检查的严格程度不同而已
IP 地址: 已记录   报告
高端调试 » 软件调试 » .Net程序调试 » P/Invoke调用dll函数,将本来void的函数声明为带返回值的,在win7出错,在winxp下正常,理由是?

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2020 ADVDBG.ORG All Rights Reserved.