• [原]PInvoke导致栈破坏


    项目中遇到一个诡异的问题,程序在升级到.net4.6.1后会崩溃,提示访问只读内存区。大概现象如下:

    1. debug版不崩溃,release版稳定崩溃。
    2. 只有x64位的程序崩溃,32位及anycpu编译出来的程序运行不会崩溃。
    3. 出问题的代码范围很小

    以上信息,各位有什么想法呢?

    由于release版可以稳定重现,而且范围不大,故通过二分排除法很快定位到了导致问题的代码。

    最后发现并不是由于升级.net版本导致的,而是程序本身的问题: x64下MemoryStatus结构体中的成员有些不是4字节大小,而是8字节大小了。而我们的代码依然按4字节定义的。

    我写了一个模拟程序来模拟出问题的代码。 参见后面的代码。

    总结: 如果不是那么稳定的崩溃,恐怕解决这个问题还会花些时间的吧,how lucky I am!!!

    BTW: 启用托管调试助手(MDA)有时候会对调试问题有极大的帮助,虽然我这次调试没有借助MDA,但我第一个想到的就是MDA

    完整的测试代码如下(如想重现问题,请编译x64版本)

    1. using System.Runtime.InteropServices; 
    2. namespace ConsoleApplication1 
    3. class Program 
    4. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance""CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes"),StructLayout(LayoutKind.Sequential)] 
    5. public struct MemoryStatus 
    6. /// --- 
    7. [MarshalAs(UnmanagedType.U4)] 
    8. public uint dwLength; 
    9. /// --- 
    10. [MarshalAs(UnmanagedType.U4)] 
    11. public uint dwMemoryLoad; 
    12. /// --- 
    13. [MarshalAs(UnmanagedType.U4)] 
    14. public uint dwTotalPhys; 
    15. /// --- 
    16. [MarshalAs(UnmanagedType.U4)] 
    17. public uint dwAvailPhys; 
    18. /// --- 
    19. [MarshalAs(UnmanagedType.U4)] 
    20. public uint dwTotalPageFile; 
    21. /// --- 
    22. [MarshalAs(UnmanagedType.U4)] 
    23. public uint dwAvailPageFile; 
    24. /// --- 
    25. [MarshalAs(UnmanagedType.U4)] 
    26. public uint dwTotalVirtual; 
    27. /// --- 
    28. [MarshalAs(UnmanagedType.U4)] 
    29. public uint dwAvailVirtual; 
    30. [DllImport("kernel32.dll")] 
    31. public static extern void GlobalMemoryStatus(ref MemoryStatus memoryStatus)
    32. class CMyClass 
    33. public int n1 = 0
    34. struct CMyStruct 
    35. public CMyClass data; 
    36. static void Main(string[] args) 
    37. CMyStruct myObj = new CMyStruct(); myObj.data = new CMyClass(); 
    38. MemoryStatus memoryStatus = new MemoryStatus(); 
    39. // this line will corrupt the stack if we run in x64, because memoryStatus is defined on the stack 
    40. GlobalMemoryStatus(ref memoryStatus); 
    41. // myObj.data is corrupted 
    42. System.Console.WriteLine("{0}", myObj.data); 
  • 相关阅读:
    收藏的网站
    记录
    在我的收藏列表里取消收藏功能的实现(不使用直接操作dom的方法)
    uniapp预览图片
    uni-app 中如何打开外部应用,如:浏览器、淘宝、AppStore、QQ等
    uniapp打包上架ios
    uniapp实现倒计时
    uniapp实现支付功能
    uniapp关闭页面回弹效果
    uniapp中使用websocket实现实时聊天功能
  • 原文地址:https://www.cnblogs.com/bianchengnan/p/9458130.html
Copyright © 2020-2023  润新知