zoukankan      html  css  js  c++  java
  • [原]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); 
  • 相关阅读:
    cpu降频问题
    配置 logrotate 指导
    Ubuntu 和 Ros 对应版本关系
    Git 文件管理
    Win10(UEFI启动) 安装Ubuntu16.04双系统
    Clion ROS开发环境设置
    clion 创建快捷方式和配置ros开发环境
    Ubuntu 16.04安装 CastXML
    eigen3 版本信息查看
    ubunutu eigen3包的查找
  • 原文地址:https://www.cnblogs.com/bianchengnan/p/9458130.html
Copyright © 2011-2022 走看看