zoukankan      html  css  js  c++  java
  • MapViewOfFile引起的问题。。。 (续)

    前一遍说到了为什么访问内存会越界,以及我们是如何找到根本原因的。

    在知道为什么有越界访问之后,我们下一个问题是:为什么第一次调用mapviewoffile会失败?为什么第二次调用mapviewoffile会成功了?

    查阅了msdn一下。如果在调用MapViewOfFile()的时候,dwNumberOfBytesToMap如果大于文件的size,那么该call就会失败,并且error code是access denied。

    这个解释貌似和我们发生的很贴切。因为第一次size太大了,第一次就会失败。但是如果第二次我们指明map到文件末尾,那么就会成功。

    但是,我们审阅了我们的代码后,觉得不会发生这样的情况。size是根据文件信息读出来的,因而不会有错。

    那会是什么引起的了?

    因为message会不断的增加,所以message writer会check当前的buffer有没有写完。如果快写完了,那么就flush当前的view,close当前的handle。然后调用createmappingfile(),创建一个更大的MMF。同时为给这块shared memory取一个新的名字。

    会不会是message reader这边用错了handle了?

    看一下handle的information。

    0:000> !handle 0x00000cb0  f
    Handle 00000cb0
      Type             Section
      Attributes       0
      GrantedAccess    0x4:
             None
             MapRead
      HandleCount      2
      PointerCount     4
      Name             \BaseNamedObjects\3835699D-D3CE-4847-BFCA-A50791DF408D_Log_FileMap10

    最后的数字,10,是writer新取的instance number。这个数字很蹊跷,因为应该不会这么大。

    看一下实际上应该是多少。

    0:000> dt _HeaderLogMessageInfoStruct 0x04dbb6e8+0x05c
    MsgMMFReader!_HeaderLogMessageInfoStruct
       +0x000 NumberOfRecords  : 0x5112
       +0x004 WriteNewLogRecordOffset : 0x260070
       +0x008 WriteNewRecordIntoBlobOffset : 0x284719
       +0x00c SizeOfLogMMFFile : 0x2a0000
       +0x010 SizeOfDataMMFFile : 0x2a0000
       +0x014 CurrentLogMappingNumberInWriter : 2
       +0x018 CurrentBlobMappingNumberInWriter : 1
       +0x01c UnreadInfoMsgCnt : 0xfffffe1d
       +0x020 UnreadWarningMsgCnt : 0x122b
       +0x024 UnreadErrorMsgCnt : 0x21f
       +0x028 TotalInfoMsgsCount : 5469
       +0x02c TotalWarningMsgsCount : 4651
       +0x030 TotalErrorMsgsCount : 853
       +0x034 InformationMsgsViewed : 0
       +0x035 WarningMsgsViewed : 0
       +0x036 ErrorMsgsViewed  : 0
       +0x038 FirstRecIn24HourWindow : 0x2636
       +0x03c FileCreationTimeStamp : _SYSTEMTIME
       +0x04c LastTouchTimeStamp : _SYSTEMTIME

    我们看到,Writer那边的instance number才是2。而reader那边居然用的是10。这才是导致MapViewOfFIle失败的真正原因。

    又重新看了遍code。发现代码那边有check number change scenario。但是,代码是这么写的:

    if (m_currentLogMappingNumber < m_msgLogHeaderStruct.CurrentLogMappingNumberInWriter)
    {
    // remap the mmf
    }

    这个地方用的是比较大小来决定需不需要重新mapviewoffile。这个才是真真正正的root cause! 应该用“!=”来判断!

    把这个地方改为"!="后,这个问题再也没有重现过。

  • 相关阅读:
    打砖块代码解析
    C语言拾遗(一):整型提升
    高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(下) <转>
    c10k测试:每连接新线程回显服务器(echo server) (转)
    高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(上) <转>
    java基础总结equals与==
    Java的运行机制概括
    Java 基础总结反射的基本操作
    python爬取基础网页图片
    px,dp,sp以及像素密度
  • 原文地址:https://www.cnblogs.com/xiaxi/p/2027219.html
Copyright © 2011-2022 走看看