delete指標時coredump的分析之旅

來源:互聯網
上載者:User

    很詭異,竟然在delete 指標時候crash,這個很少見~~~分析這個問題費了不少周折,記錄在此。如能協助到他人,不勝開心。

    拿到的運行時候堆棧包含如下部分:

.......

Back chain word     : 183831f8
        b930a150  [1003a150],CXC1734416%2_R1E       ??:0  heap_free

  Back chain word     : 18383208
        b92ff0dc  [1002f0dc],CXC1734416%2_R1E       ??:0  free

  Back chain word     : 18383218
        ba161414  [10e91414],CXC1734416%2_R1E       ??:0  operator delete

  開始以為是對指標重複釋放,代碼走讀後發現排除此種可能。然後懷疑多線程記憶體同步有問題,後排除。

  有同事懷疑是OS的問題,不過一般我不會懷疑OS的,比較OS一般都是很穩定的,而且這次OS沒有重大升級。為了排除這種可能,還是解碼了一下堆棧的頂部資訊

註:下面的資訊其實是在 heap_free之上,所以同事懷疑是OS問題 

Stacktrace :
  Using stackpointer  : 0041b9cc

  Back chain word     : 097873b0
        008136d8  [008136d8],CXC1729957_R81B13      ??:0  Cs_reportUnexpectedSignal_v

  Back chain word     : 097873f0
        00828ac0  [00828ac0],CXC1729957_R81B13      /vobs/cello/cls_src/CLS_CRX90145_1/ERROR-MANAGER_CNX9011053_2/src/swu/error/error_handler.c:768  eman_install_appl_exten
  Back chain word     : 09787408
        009d9f10  [009d9f10],CXC1729957_R81B13      ??:0  splaycmp_hunt_from

  Back chain word     : 09787448
        009dc700  [009dc700],CXC1729957_R81B13      ??:0  zzkrn_get_fsem

  Back chain word     : 09787450
        00a1d258  [00a1d258],CXC1729957_R81B13      ??:0  zzkrn_create_context

  Back chain word     : 09787460
        00a1b414  [00a1b414],CXC1729957_R81B13      ??:0  zzkrn_create_context

  Back chain word     : 09787498
        009b2514  [009b2514],CXC1729957_R81B13      ??:0  ose_hfmi_get_heap_reference

  Back chain word     : 097874c0
        009b410c  [009b410c],CXC1729957_R81B13      ??:0  zzheap_realloc

  Back chain word     : 09787500
        009b910c  [009b910c],CXC1729957_R81B13      ??:0  l_buddy_query_req

  Back chain word     : 09787540
        009b4784  [009b4784],CXC1729957_R81B13      ??:0  buf_check_header

  Back chain word     : 097875a0
        009b1bc8  [009b1bc8],CXC1729957_R81B13      ??:0  l_heap_error

  Back chain word     : 11c8ef68
        00a1b414  [00a1b414],CXC1729957_R81B13      ??:0  zzkrn_create_context

  Back chain word     : 11c8ef70
        009b11c8  [009b11c8],CXC1729957_R81B13      ??:0  ose_handle_create_heap

簡單推測,應該是delete拋出異常被OS捕獲,然後發出某種signal終止應用程式,由此應該不是OS的問題。既然不是OS的問題,還是從自身找原因:)

因為這是個必現的問題,單步跟蹤是個很好的方法。但由於程式跑在嵌入式OS上面,之前一直不太清楚怎麼單步,幸運的是終於有老外同事共用了單步的方法^_^

雖然編譯和上傳load module有點麻煩,沒辦法,誰讓單步比較好用呢。

      設定斷點後單步跟蹤,設定指標為watch point,其實意義不大。單步觀察調用棧,果然如同之前設想,在解構函式中逐個調用各個attribute的解構函式。

在單步過程中還有一個插曲,就是inline 函數的調用。開始沒有注意是inline的,發現GDB對某些函數不能單步,直接嘗試GDB中運行會導致GDB收到SIGTRAP,異常退出,開始以為是這個地方的原因,仔細一看發現是inline函數。哎。。。重新單步跟蹤後,發現所有解構函式執行完成後程式crash,開始懷疑最後一個解構函式的地方。檢查後發現並沒有可以懷疑的地方,然後仔細檢查記憶體資料的內容終於發現端倪:

開始的資料:

{<EcXpuBoardEqmiD> = {<EcEcmiD> = {_vptr.EcEcmiD = 0xb9f580c0}, clientProcessId = {_vptr.EcClientProcessIdD = 0xb9f8b288,
      static rtg_EcClientProcessIdD_fields = {{name = 0xb9f05814 "myValue", offset = 4, type = 0xb9f343d4, modifier = 0x0}}, myValue = 66851}, clientId = {
      _vptr.EcClientIdD = 0xb9f8b298, static rtg_EcClientIdD_fields = {{name = 0xb9f05814 "myValue", offset = 4, type = 0xb9f343a4, modifier = 0x0}, {
          name = 0xb9f0597c "valid", offset = 8, type = 0xb9f342e4, modifier = 0x0}}, myValue = 0, valid = true}}, result = 4294967295, auxPiuType = {myValue = 49152},
  operState = 4294967295, availStatus = {static rtg_RbsAvailStatusCollectionD_fields = 0xb9f1e07c, myValue = 0}, admState = 4294967295, ledInfo = {
    redLed = EQC_LED_NOT_APPLICABLE, greenLed = EQC_LED_NOT_APPLICABLE, yellowLed = EQC_LED_NOT_APPLICABLE, blueLed = EQC_LED_NOT_APPLICABLE}, errorCode = {myValue = 1},
  hubPosition = {_vptr.BlibStringD = 0xb9f8c790, static rtg_BlibStringD_fields = {{name = 0xb9f1a040 "m_capacity", offset = 4, type = 0xb9f343a4, modifier = 0x0}, {
        name = 0xb9f1a04c "m_contents", offset = 8, type = 0xb9f34314, modifier = 0xb9f1c64c}, {name = 0xb9f1a058 "m_size", offset = 12, type = 0xb9f343a4,
        modifier = 0x0}}, m_capacity = 3, m_contents = 0x4085e680 "NA", m_size = 2, static emptystring = ""},
uniqueHwId = {uniqueHwIdLength = 65 'A',
    uniqueHwId = "\000\0000ecMtrCdciTimer\000\022"}}

core dump前:

{<EcEcmiD> = {_vptr.EcEcmiD = 0xb9f8b200}, clientProcessId = {_vptr.EcClientProcessIdD = 0x0, static rtg_EcClientProcessIdD_fields = {{
          name = 0xb9f05814 "myValue", offset = 4, type = 0xb9f343d4, modifier = 0x0}}, myValue = 0}, clientId = {_vptr.EcClientIdD = 0x0,
      static rtg_EcClientIdD_fields = {{name = 0xb9f05814 "myValue", offset = 4, type = 0xb9f343a4, modifier = 0x0}, {name = 0xb9f0597c "valid", offset = 8,
          type = 0xb9f342e4, modifier = 0x0}}, myValue = 0, valid = false}}, result = RBS_OK, auxPiuType = {myValue = 0}, operState = RBS_OPER_DISABLED, availStatus = {
    static rtg_RbsAvailStatusCollectionD_fields = 0xb9f1e07c, myValue = 0}, admState = RBS_ADMIN_LOCKED, ledInfo = {redLed = EQC_LED_NOT_APPLICABLE,
    greenLed = EQC_LED_NOT_APPLICABLE, yellowLed = EQC_LED_NOT_APPLICABLE, blueLed = EQC_LED_NOT_APPLICABLE}, errorCode = {myValue = 0}, hubPosition = {
    _vptr.BlibStringD = 0x0, static rtg_BlibStringD_fields = {{name = 0xb9f1a040 "m_capacity", offset = 4, type = 0xb9f343a4, modifier = 0x0}, {
        name = 0xb9f1a04c "m_contents", offset = 8, type = 0xb9f34314, modifier = 0xb9f1c64c}, {name = 0xb9f1a058 "m_size", offset = 12, type = 0xb9f343a4,
        modifier = 0x0}}, m_capacity = 0, m_contents = 0x0, m_size = 0, static emptystring = ""}, uniqueHwId = {uniqueHwIdLength = 0 '\0',
    uniqueHwId = '\0' <repeats 18 times>}}

難道uniqueHwId 是定長數組?檢查代碼後果然如此!!!看到uniqueHwId = "\000\0000ecMtrCdciTimer\000\022" ,推測應該是隨機值。在分配記憶體後,對資料進行賦值時使用長度65做終止條件,導致寫越界。後檢查在出問題的時候,uniqueHwId
確實沒有初始化,從而導致隨機值。分析道這裡,立刻響起Inside c++ object model裡面關於new/delete的深入說明,實際上編譯器會在分配的記憶體首位處加上格外的一些資料,比較這塊記憶體的大小,起始地址等其他必要資訊,而這些資訊就是給delete使用的,主要可以保證釋放記憶體。而且還可能在記憶體尾巴處填寫“保護資料”,一旦檢測到這些資料被擦寫,即認為有錯可以啟用異常或者其他錯誤機制。這樣的話,就可以解釋core dump的原因了,程式由于越界寫導致new的尾巴保護資料被擦寫,在delete時候拋出異常導致crash.

   分析到這來,其實就是一個普通的越界寫的問題,但是由於掩蓋在new/delete的內幕之下,又多少帶了些神秘色彩。一般來說,越界寫會導致隨機crash,當出現這種情況時候很容易懷疑越界寫。但這次,卻只有在delete的時候crash,讓我忽略了忘這方面考慮。

  總結:

     一些看似複雜的問題其實只是小問題的組合,適當的排除,分解逐步細化問題,直至發現真相

   不要輕易懷疑OS和成熟的library,寧肯多懷疑自己:)

    注意積累(就像new/delete的原理一樣,還以為在這種高度整合的產品了不需要這些知識一樣,說不準以前覺得沒用的東西就會跳出來告訴你“我很有用的”)

   多用google, 英文搜尋關鍵詞,呵呵~~

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.