原, 总结, 调试, 调试案例 

项目中遇到一个诡异的问题,程序在升级到.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); 







[原]PInvoke导致栈破坏的更多相关文章

  1. 转:C 函数调用栈

    第一篇: 转自:http://kingj.iteye.com/blog/1555017 本文转自  http://blog.csdn.net/eno_rez/article/details/21586 ...

  2. 对抗栈帧地址随机化/ASLR的两种思路和一些技巧

    栈帧地址随机化是地址空间布局随机化(Address space layout randomization,ASLR)的一种,它实现了栈帧起始地址一定程度上的随机化,令攻击者难以猜测需要攻击位置的地址. ...

  3. 深入理解golang 的栈

    线程栈(thread stacks)介绍 先回顾下linux的内存空间布局   简书_stack02.png 当启动一个C实现的thread时,C标准库会负责分配一块内存作为这个线程的栈.标准库分配这 ...

  4. cve-2010-3333 Microsoft Office Open XML文件格式转换器栈缓冲区溢出漏洞 分析

    用的是泉哥的POC来调的这个漏洞 0x0 漏洞调试    Microsoft Office Open XML文件格式转换器栈缓冲区溢出漏洞 Microsoft Office 是微软发布的非常流行的办公 ...

  5. CSAPP阅读笔记-变长栈帧,缓冲区溢出攻击-来自第三章3.10的笔记-P192-P204

    一.几个关于指针的小知识点: 1.  malloc是在堆上动态分配内存,返回的是void *,使用时会配合显式/隐式类型转换,用完后需要用free手动释放. alloca是标准库函数,可以在栈上分配任 ...

  6. Go语言是如何处理栈的

    转自:http://tonybai.com/2014/11/05/how-stacks-are-handled-in-go/ Go 1.4Beta1刚刚发布,在Go 1.4Beta1中,Go语言的st ...

  7. java栈和队列

    栈    可变长数组实现    链表实现    数组与链表的对比队列    链表实现 栈 下压栈(简称栈)是一种基于后进后出(LIFO)策略的集合类型.这里学习分别用数组和链表这两种基础数据结构来实现 ...

  8. 更改Linux默认栈空间的大小

    有时候在Linux写C++程序处理大量的数据,程序内部需要分配很大的数组来存放一些数据,但有时候分配的数组太大的话运行时会出现段错误.这种情况可能是分配的数组大小超过了Linux系统的默认栈空间的大小 ...

  9. C语言数据结构----栈与递归

    本节主要说程序中的栈函数栈的关系以及栈和递归算法的关系. 一.函数调用时的栈 1.程序调用时的栈是也就是平时所说的函数栈是数据结构的一种应用,函数调用栈一般是从搞地质向低地址增长的,栈顶为内存的低地址 ...

随机推荐

  1. Mac Go 环境变量配置

    GOPATH 是工作目录,就是你打代码,代码的存放目录 GOROOT 是Go的安装目录,我下载的是免安装版的 现在的Go环境变量就是设置成这个样子, 终于Bee不会报错了!!!

  2. statement 、prepareStatement的用法和解释

    转自:http://blog.csdn.net/QH_JAVA/article/details/48245945   一.prepareStatement 的用法和解释 1.PreparedState ...

  3. DevOps专题|Lua引擎打造超轻量级客户端

    Lua 作为一门轻量级脚本语言,源码使用标准C语言发布,语法简洁,非常适合嵌入式.客户端.游戏等场景. Lua引擎语言特点 轻量级 源码简单,以lua最新版5.3.5为例,加上lua自身提供的lib库 ...

  4. MyBatis:配置解析

    配置解析 核心配置文件 mybatis-config.xml 系统核心配置文件 MyBatis 的配置文件包含了会深深影响 MyBatis 行为的设置和属性信息. 能配置的内容如下: configur ...

  5. 可重入排他锁ReentrantLock源码浅析

    1.引子 "ReentrantLock"单词中的“Reentrant”就是“重入”的意思,正如其名,ReentrantLock是一个支持重入的排他锁,即同一个线程中可以多次获得同步 ...

  6. UVA - 10118 Free Candies(免费糖果)(dp---记忆化搜索)

    题意:桌上有4堆糖果,每堆有N(N<=40)颗.佳佳有一个最多可以装5颗糖的小篮子.他每次选择一堆糖果,把最顶上的一颗拿到篮子里.如果篮子里有两颗颜色相同的糖果,佳佳就把它们从篮子里拿出来放到自 ...

  7. Python爬虫连载1-urllib.request和chardet包使用方式

    一.参考资料 1.<Python网络数据采集>图灵工业出版社 2.<精通Python爬虫框架Scrapy>人民邮电出版社 3.[Scrapy官方教程](http://scrap ...

  8. 【前缀思想】二叉树中所有距离为 K 的结点

    863. 二叉树中所有距离为 K 的结点 class Solution { Map<TreeNode,String>map=new HashMap<>(); String pa ...

  9. MyBatis项目报错:The server time zone value '�й�׼' is unrecognized or represents more than one time zone

    问题来源:在部署Spring + MyBatis项目的时候,运行时报错The server time zone value '�й�׼' is unrecognized or represents m ...

  10. JavaScript—面向对象小例子

    什么是面向对象 要是以前别人问我.随口道来,封装继承多态,万物皆对象...一大推.说的自己都以为自己掌握了面向对象.呵呵一笑.确实掌握了 只是不会用..... 什么是面向对象编程 以前 学.Net 虽 ...