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! 应该用“!=”来判断!

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

  • 相关阅读:
    树莓派frp添加为服务管理
    liunx开源打印驱动foo2zjs编译小坑
    树莓派中实现ll命令
    Windows中使用QEMU创建树莓派虚拟机
    C#打印条码BarTender SDK打印之路和离开之路(web平凡之路)(转)
    数据库连接池问题 Max Pool Size
    C#时间
    XAF 如何从Excel复制多个单元格内容到GridView(收藏)
    C#日期处理(转) 太忘记了,备忘
    C#、devExpress 的 给bandedGrid加菜单功能 :复制、粘贴的例子(转)
  • 原文地址:https://www.cnblogs.com/xiaxi/p/2027219.html
Copyright © 2011-2022 走看看