一个奇怪的错误,找到了错误点,也找到了解决方法,但是结果不满意
楔子
在对类进行实例化的时候,会调用.Ctor默认构造函数。
它一般的首先调用的是函数
JIT_TrialAllocSFastMP_InlineGetThread
实例化,然后再调用.Ctor。这是一个实例化的整体思路。
问题
问题就出在,如果在VS Debug CLR上的.Ctor的汇编代码上打上断点,那么结果就会出错。如果你不打这个断点。结果就不会出错。错误如下:
意思是,打上断点造成的错误? 继续运行下去整个程序直接结束了。
探究
看下错误堆栈:
KernelBase.dll!00007fff09a088e2() 未知 未加载任何符号。
coreclr.dll!CHECK::Setup(const char * message=0x000002948594b430, const char * condition=0x00007ffe5c48e524, const char * file=0x00007ffe5c492990, int line=0x00001be0) 行 198 C++ 已加载符号。
coreclr.dll!CLRVectoredExceptionHandlerPhase3(_EXCEPTION_POINTERS * pExceptionInfo=0x000000ecb6f79bd0) 行 7135 C++ 已加载符号。
coreclr.dll!CLRVectoredExceptionHandlerPhase2(_EXCEPTION_POINTERS * pExceptionInfo=0x000000ecb6f79bd0) 行 6889 C++ 已加载符号。
coreclr.dll!CLRVectoredExceptionHandler(_EXCEPTION_POINTERS * pExceptionInfo=0x000000ecb6f79bd0) 行 6856 C++ 已加载符号。
coreclr.dll!CLRVectoredExceptionHandlerShim(_EXCEPTION_POINTERS * pExceptionInfo=0x000000ecb6f79bd0) 行 7547 C++ 已加载符号。
ntdll.dll!RtlpCallVectoredHandlers() 未知 已加载符号。
ntdll.dll!RtlDispatchException() 未知 已加载符号。
ntdll.dll!KiUserExceptionDispatch() 未知 已加载符号。
coreclr.dll!_hpCodeHdr::GetNumberOfUnwindInfos() 行 331 C++ 已加载符号。
coreclr.dll!_hpCodeHdr::GetUnwindInfo(unsigned int iUnwindInfo=0x00000000) 行 341 C++ 已加载符号。
coreclr.dll!CEEJitInfo::WriteCode(EEJitManager * jitMgr=0x00000294d6bdeba0) 行 10883 C++ 已加载符号。
GetNumberOfUnwindInfos()这个函数出现了异常,进去看看,函数原型如下:
UINT GetNumberOfUnwindInfos()
{
SUPPORTS_DAC;
return pRealCodeHeader->nUnwindInfos;
}
原来是pRealCodeHeader这个结构体为空造成的异常。那么它是从哪里来的呢?
看堆栈有个WriteCode函数,进入里面看下:
void CEEJitInfo::WriteCode(EEJitManager * jitMgr)
{
// 此处省略
WriteCodeBytes();、
// 此处省略
}
它里面调用了WriteCodeBytes函数:
void CEEJitInfo::WriteCodeBytes()
{
if (m_CodeHeaderRW != m_CodeHeader)
{
ExecutableWriterHolder<void>codeWriterHolder((void*)m_CodeHeader,m_codeWriteBufferSize);
memcpy(codeWriterHolder.GetRW(), m_CodeHeaderRW, m_codeWriteBufferSize);
}
}
m_CodeHeader的成员变量就是pRealCodeHeader。那么m_CodeHeader哪里来的呢?
m_CodeHeader通过codeWriterHolder调用MapViewOfFile进行地址映射,当 codeWriterHolder.GetRW()变量改变的时候,m_CodeHeader就进行改变。那么问题就出在这里,当断点到.Ctor上面的时候,运行到这两句代码:
ExecutableWriterHolder<void> codeWriterHolder((void *)m_CodeHeader, m_codeWriteBufferSize);
memcpy(codeWriterHolder.GetRW(), m_CodeHeaderRW, m_codeWriteBufferSize);
m_CodeHeader并没有改变,而断点其它函数都会改变。
难道是断点引起的MapViewOfFile错误?
结果
原因是找到了,但是解决问题的方式有点不爽。看上面两句代码,变量
codeWriterHolder.GetRW()
通过m_CodeHeaderRW变量赋值了,但是m_CodeHeader并没有被赋值上。所以这里可以把m_CodeHeaderRW地址指向的值八字节一个单位,复制到m_CodeHeader地址指向的值。这样就可以解决问题。
看似解决了问题,实际上为啥赋值不上,是否是MapViewOfFile的原因,或者是个微软的BUG?因为MapViewOfFile不开源,也看不到代码,所以无从查证。
结尾
作者:江湖评谈
相关文章
- 为产业创新“解码”,网易数创的服务方法论
- 昇腾的武汉故事:种下一颗种子,长出一片树林
- “笨鸟”荣耀的2021
- 网易智企跃入元宇宙,想成为To B的“头号玩家”
- DoubleTake for Mac(全景图制作软件) v2.6.10注册激活版
- 智改数转水循环在线监测系统,提升企业安全生产!
- “东方树叶”走红背后,起底农夫山泉的“科研军团”
- 入局智能健身镜,小度破圈进行时
- 新能源车企凶猛下沉,“新车商”是一条捷径吗?
- 一辈子不管贫穷富裕,一定要做好这三件事 - 我的闪存
- 服装卖货的技巧 - 我的闪存
- 成功的秘诀 - 我的闪存
- 最好赚钱的六个行业 - 我的闪存
- 穷人与富人对钱的区别 - 我的闪存
- 关于赚钱方式 - 我的闪存
- 余世维 有效沟通执行力企业管理销售培训 视频讲座
- UML建模图实战笔记
- 使用U盘的PE系统安装Windows10操作系统 - 初学者系列 - 学习者系列文章
- u深度win10pe装机版制作教程
- UML建模工具IBM.Rational.Rose.Enterprise软件下载