程序啟動時訪問了未初始化的類指針引發內存訪問違例導致程序崩潰的問題排查

目錄

1、問題說明

2、使用Windbg動態調試去初步分析

3、使用Windbg詳細分析

4、最后


VC++常用功能開發匯總(專欄文章列表,歡迎訂閱,持續更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/124272585C++軟件異常排查從入門到精通系列教程(專欄文章列表,歡迎訂閱,持續更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931C++軟件分析工具從入門到精通案例集錦(專欄文章,持續更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/131405795C/C++基礎與進階(專欄文章,持續更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html開源組件及數據庫技術(專欄文章,持續更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html網絡編程與網絡問題分享(專欄文章,持續更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_2276111.html? ? ? ?最近在聯調程序的新功能時,更新了底層模塊的庫之后,出現了啟動報錯導致程序啟動失敗的問題。這個問題有一定的代表性,在這里給大家分享一下問題的排查過程。

1、問題說明

? ? ? ?當前軟件的新需求基本開發完成,目前正處于調試與bug修改的過程中,因為登錄當前的平臺出現注冊失敗的問題,軟件重啟了幾次還是有問題,于是手動將代碼中的dll都換成最新的版本(拷貝終端組件整體編譯的庫,更新加入到版本控制的底層庫),并將頭文件更新成最新的。更新完成后,在VS中重新編譯代碼,開啟調試,結果程序一啟動就報錯了,彈出如下的提示框:

查看此時的函數調用堆棧,顯示崩潰在medaisdk.dll中,但看不到中間的模塊,如下:

這個崩潰是必現的,程序始終啟動不起來,導致沒法繼續進行業務聯調。

? ? ? ?此外,還有個奇怪的現象,同一個release版本的軟件,在一個測試同事的Win10系統上啟動并沒有問題,可以正常運行。但在另一個測試同事的Win7系統中一啟動就崩潰,是必現的!

后來排查得知,是代碼中訪問了一個未初始化的指針變量(野指針)引發內存訪問違例導致的。在release下,未初始化的變量值不會自動初始化,是分配內存時內存中殘留的值,是隨機值。
所以從Win7和Win10系統中的不同表現可以看出,兩個系統的內存管理機制是有差異的,正是因為有差異,導致同一個版本的軟件在兩個系統中有不同的表現。


?? ?在這里,給大家重點推薦一下我的幾個熱門暢銷專欄:

專欄1:(該專欄訂閱量接近350個,有很強的實戰參考價值,廣受好評!)

C++軟件異常排查從入門到精通系列教程(專欄文章列表,歡迎訂閱,持續更新...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/article/details/125529931

本專欄根據近幾年C++軟件異常排查的項目實踐,系統地總結了引發C++軟件異常的常見原因以及排查C++軟件異常的常用思路與方法,詳細講述了C++軟件的調試方法與手段,以圖文并茂的方式給出具體的實戰問題分析實例,帶領大家逐步掌握C++軟件調試與異常排查的相關技術,適合基礎進階和想做技術提升的相關C++開發人員!

專欄中的文章都是通過項目實戰總結出來的(通過項目實戰積累了大量的異常排查素材和案例),有很強的實戰參考價值!專欄文章還在持續更新中,預計文章篇數能更新到200篇以上!

專欄2:?

C/C++基礎與進階(專欄文章,持續更新中...)icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_11931267.html

以多年的開發實戰為基礎,總結并講解一些的C/C++基礎與進階內容,以圖文并茂的方式對相關知識點進行詳細地展開與闡述!專欄涉及了C/C++領域的多個方面的內容,同時給出C/C++及網絡方面的常見筆試面試題,并詳細講述Visual Studio常用調試手段與技巧!

專欄3:?

開源組件及數據庫技術icon-default.png?t=N7T8https://blog.csdn.net/chenlycly/category_12458859.html

以多年的開發實戰為基礎,分享一些開源組件及數據庫技術!


2、使用Windbg動態調試去初步分析

? ? ? ?于是決定使用Windbg動態分析一下,看看到底是什么原因導致的。因為程序啟動時就發生了崩潰,沒法先啟動程序再把Windbg附加上去,所以需要直接使用Windbg去啟動程序,這樣才能監測到程序啟動過程中的異常。

? ? ? ?用Windbg動態啟動程序,感知到了異常,查看此時的函數調用堆棧,然后找來函數調用堆棧中相關模塊的pdb文件,設置到Widnbg中,重新查看函數調用堆棧,堆棧中顯示了詳細的函數名稱和代碼行號:

從函數調用堆棧得知,在程序啟動時調用了終端組件終端組件業務初始化接口,然后終端組件層在創建音視頻組的編解碼器時產生了內存訪問違例,進而產生崩潰。

? ? ? ?初步懷疑可能是終端組件庫與音視頻庫mediasdk.dll版本不一致導致的,可能是mediasdk.dll的頭文件修改了(修改了函數參數或者修改了結構體),只發布了dll庫文件,沒有發布頭文件導致的。當時因為手頭有很多事情要處理,沒有去深究這個問題,于是嘗試讓音視頻組重新發布mediasdk.dll庫和頭文件,看看發布后還沒有問題。

3、使用Windbg詳細分析

? ? ? ?但mediasdk.dll庫文件和頭文件重新發布后,終端組件的相關模塊重新編譯,然后拷貝最新的終端組件及底層的庫重新編譯主程序,啟動調試運行,結果啟動時還是報錯。看來并不是版本不對導致的問題。

? ? ? 于是使用Windbg啟動程序,感知到異常中斷,拿來pdb文件,查看詳細的函數調用堆棧,和維護mediasdk.dll模塊的同事一起對照代碼進行詳細分析。崩潰時的堆棧如下:

從堆棧中可以看出,代碼崩潰在mediasdk!CVidEncWrapper::Id函數中,查看該函數的源碼,該函數中只是簡單地返回一個整型變量的值:

所以引發問題的點應該不在該函數中,需要沿著函數調用堆棧往上看,看調用mediasdk!CVidEncWrapper::Id接口的函數。

? ? ? ?另外,查看發生崩潰的這條匯編指令,首先是訪問了一個內核態地址0xcdcdf001引發的內存訪問違例(用戶態的代碼不能訪問內核態的內存地址)。然后查看這條匯編指令中用到的寄存器eax,崩潰時該寄存器的值為0xcdcdcdcd。以前我講過一些C++程序中常見的異常值0xcdcdcdcd、0xdddddddd、0xfeeefeee等,這幾個異常值的說明如下:

所以第一眼看到這個0xcdcdcdcd,根據上面的含義說明,就能大概判斷代碼中使用了未初始化的堆內存變量,可能是mediasdk!CVidEncWrapper::Id函數所在的類對象有問題,查看這條返回整型變量的匯編指令,按講返回成員變量的值,當前類對象地址應該是存放在ecx寄存器中的,按講返回成員變量的值,直接使用ecx就行,為啥會使用eax寄存器呢?

? ? ? ?要確定這個問題很簡單,直接查看匯編代碼上下文就知道了。于是在菜單欄中點擊 View -> Disassembly,查看匯編代碼上下文:

從匯編代碼就找到答案了。對于被調用函數CVidEncWrapper::Id,主調函數肯定是將CVidEncWrapper類對象的首地址通過ecx傳進來的,匯編代碼中先將ecx中的C++類對象首地址,拷貝到[ebp-4]棧內存上,然后又將[ebp-4]棧內存中的值拷貝到eax中,然后執行發生崩潰的這條指令,所以執行該條崩潰指令時,eax中存放的就是當前類對象的首地址。

? ? ? ?所以給CVidEncWrapper::Id函數傳入的CVidEncWrapper對象首地址為0xcdcdcdcd,肯定使用的是一個未初始化的指針變量導致的。所以沿著函數調用堆棧,查看調用CVidEncWrapper::Id的函數mediasdk!CKdvEncoder::CKdvEncoder,這是CKdvEncoder類的構造函數。根據函數調用堆棧中顯示的cpp路徑及代碼行號,找到對應的源碼位置,如下:

這行代碼是一個打印日志的宏Mc_Enter,這就是個宏,并沒有看到對CVidEncWrapper::Id函數調用啊,是不是Windbg中指示的行號有問題!
我不了解音視頻組的代碼,音視頻組維護代碼的也是一個剛接手的剛畢業小哥,對代碼也不熟悉。于是以“Id()”為關鍵字搜索,看看是哪些地方調用了CVidEncWrapper::Id函數。結果剛才的那個打印日志的宏定義中調用了:

這就對上了,說明Windbg指示的行號是沒問題的。對于宏,在代碼編譯時會被替換成定義的內容。

? ? ? ?這個打印日志的宏是放置在CXXXEncoder類的構造函數的入口處,而對指針變量m pcXXXVideoEncoder的初始化放在宏的下一行,所以在宏定義中訪問了沒有初始化的指針變量m_pcXXXVideoEncoder,該指針變量在Debug下會被初始化為0xcdcdcdcd(指針變量的內存區域中會被填充成0xcdcdcdcd),所以將0xcdcdcdcd作為一個CVidEncWrapper類對象的首地址,調用CVidEncWrapper::Id接口去讀取類中的成員變量m dwIndex的值,讀成員變量m dwIndex的值,就是去讀取該變量在內存中的內容,即訪問該變量的內存。

? ? ? ?類成員變量的內存位于所在CVidEncWrapper類對象中,是相對于類對象首地址的偏移,即eax+2234h = 0xcdcdcdcd + 2234h = 0xcdcdf001,所以要讀取成員變量m dwIndex的值,就是去訪問該變量的內存地址0xcdcdf001中的內容,但這個地址對于32為程序,是個內核態內存地址,當前代碼是用戶態的代碼,是不能訪問內核態地址的,所以產生了內存訪問違例,程序進而發生崩潰。

? ? ? ?解決辦法是,在CXXXEncoder構造函數中將對指針變量m_pcXXXVideoEncoder初始化的代碼調整到打印日志那句宏Mc_Enter代碼前面去就好了。保證在使用前就被初始化。

4、最后

? ? ? ?當前這個問題是必現的,為啥之前沒有出過問題呢?查看音視頻組代碼的修改記錄,在打印宏Mc_Enter的定義處,修改了宏的實現代碼。當時修改代碼后,只在release下做了測試,沒有測試Debug版本的,這個問題在Debug下是必現的。

? ? ? ?最開始我們說過,使用問題庫的Relase軟件版本(通過release安裝包安裝的),在Win10系統上可以正常運行的,沒有暴露出問題。但這個版本在Win7上啟動會直接報錯的,這是Win7和Win10中的內存管理機制不同導致的。現在大部分人用的都是Win10,所以可能很難將問題暴露出來。所以有兩點需要注意一下:

1)Release版本沒問題,不代表Debug版本沒問題;
2)Win10系統上運行沒問題,不代表在其他系統(比如Win7)上運行沒問題。

此外,還有兩點值得注意一下:

1)通過異常值0xcdcdcdcd,初步推斷出是變量未初始化引起的,然后以這個線索為切入點,快速定位問題;
2)在崩潰的那條匯編代碼中,沒有通過ecx去訪問類中成員變量的內存,而是使用eax,查看一下CVidEncWrapper::Id函數的匯編代碼就知道了。查看上下文便知道,當前類對象的首地址已經傳給了eax了,所以在崩潰的額那條匯編指令中使用了eax。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/213609.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/213609.shtml
英文地址,請注明出處:http://en.pswp.cn/news/213609.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

20、XSS——XSS跨站腳本

文章目錄 一、XSS漏洞概述1.1 XSS簡介 二、XSS漏洞分類2.1 反射型XSS2.2 存儲型XSS2.3 DOM型XSS 三、XSS payload構造以及變形3.1 XSS payload構造3.2 XSS payload 變形 一、XSS漏洞概述 1.1 XSS簡介 XSS被稱為跨站腳本攻擊(Cross-site scripting)&…

linux dpdk 介紹

DPDK(Data Plane Development Kit)是一個由英特爾發起的開源項目,旨在提供一個快速、高性能的數據平面開發工具包,使網絡應用能夠在通用處理器上實現網絡功能虛擬化(NFV)和軟件定義網絡(SDN&…

k8s volumes and data

Overview 傳統上,容器引擎(Container Engine)不提供比容器壽命更長的存儲。由于容器被認為是瞬態(transient)的,這可能會導致數據丟失或復雜的外部存儲選項。Kubernetes卷共享 Pod 生命周期,而不是其中的容器。如果容器終止,數據…

排序的簡單理解(上)

1. 排序的概念及引用 1.1 排序的概念 排序:所謂排序,就是使一串記錄,按照其中的某個或某些關鍵字的大小,遞增或遞減的排列起來的操作(按照我們的需求能夠有序的將數據信息排列起來)。 穩定性:假…

TeeChart.NET 2023.11.17 Crack

.NET 的 TeeChart 圖表控件提供了一個出色的通用組件套件,可滿足無數的圖表需求,也針對重要的垂直領域,例如金融、科學和統計領域。 數據可視化 數十種完全可定制的交互式圖表類型、地圖和儀表指示器,以及完整的功能集&#xff0c…

醫療設備智慧管理助力醫院提質增效,阿基米德amp;健康界實踐分享

近日,蘇州阿基米德網絡科技有限公司與醫療領域頭部級媒體健康界,聯合舉辦“數智為擎 提質增效——醫學裝備智慧管理創新發展論壇”的直播活動。 直播現場,來自上海交通大學醫學院附屬同仁醫院、中華醫學會航海醫學分會、蘇州阿基米德的專家們…

統信UOS_麒麟KYLINOS上使用命令行配置NTP服務器

原文鏈接:統信UOS/麒麟KYLINOS上使用命令行配置NTP hello,大家好啊,今天我要給大家介紹的是在統信UOS/麒麟KYLINOS操作系統上使用命令行配置NTP(Network Time Protocol)服務器的方法。在內網環境下,許多企業…

13、C++異常處理

13、c異常處理 拋出異常捕獲異常未拋出異常時的流程拋出異常時的流程捕獲異常匹配順序異常說明異常處理構造函數中的異常析構函數中的異常標準庫異常類 拋出異常 throw 異常對象可以拋出基本類型的對象,如:throw -1;throw "內存分配失敗!";也可以拋出類類…

AVP對縱向控制ESP(Ibooster)的需求規范

目錄 1. 版本記錄... 3 2. 文檔范圍和控制... 4 2.1 目的/范圍... 4 2.2 文檔沖突... 4 2.3 文檔授權... 4 2.4 文檔更改控制... 4 3. 功能概述... 5 4. 系統架構... 6 5. 主要安全目標... 7 5.1 …

FreeSSL申請免費域名證書

本文詳細講解如何申請免費證書,需要先準備好域名,將服務器IP和域名綁定。 1、注冊FreeSSL賬號 網址: https://freessl.org/ 2、申請流程 登錄后首頁輸入域名,然后點擊Create certificate,跳轉到證書申請頁面。 或者…

Pytorch深度強化學習1-6:詳解時序差分強化學習(SARSA、Q-Learning算法)

目錄 0 專欄介紹1 時序差分強化學習2 策略評估原理3 策略改進原理3.1 SARSA算法3.2 Q-Learning算法 0 專欄介紹 本專欄重點介紹強化學習技術的數學原理,并且采用Pytorch框架對常見的強化學習算法、案例進行實現,幫助讀者理解并快速上手開發。同時&#…

老人的數目

給你一個下標從 0 開始的字符串 details 。details 中每個元素都是一位乘客的信息,信息用長度為 15 的字符串表示,表示方式如下: 前十個字符是乘客的手機號碼。接下來的一個字符是乘客的性別。接下來兩個字符是乘客的年齡。最后兩個字符是乘…

QGIS 加載在線XYZ地圖圖層

QGIS 加載在線XYZ地圖圖層 定義并添加必應XYZ圖層 Go to Layer > Add Layer > Add XYZ Layer…Click NewName as BingMaps(as you wish)URL as http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g1click OkSelect XYZ Connections as Bing Maps(Which you creat…

PR自動剪輯視頻工具AI智能剪輯插件AutoPod

推薦一款可以提高剪輯效率,節約時間成本的AI人工智能自動剪輯視頻制作工具pr插件Autopod,輔助你更快地完成視頻內容的編輯工作。 Autopod 插件是一款應用于 Adobe Premiere Pro 軟件的插件,用于自動剪輯。該插件能夠識別和處理視頻和音頻素材…

Spring Boot 常用注解分類

目錄 1.核心注解:2.配置相關注解:3.控制器相關注解:4.數據訪問相關注解:5.測試相關注解:6.條件注解:7.AOP相關注解:8.定時任務相關注解:9.消息隊列相關注解:10.Spring Se…

函數式編程解析:定義、功能與Java實踐

目錄 一、函數式編程1.1 什么是函數式編程1.2 函數式編程特征1.2.1 純函數1.2.2 函數是一等公民 1.3 函數式編程在java中的實踐 參考資料 一、函數式編程 1.1 什么是函數式編程 函數式編程(Functional Programming)是一種編程范式,它將計算…

ES6中的迭代器和set、map集合

什么是迭代器? 一種機制,也是一種接口,為數據結構提供統一訪問接口,依次處理數據據結構成員 只要實現了迭代器接口,就可以使用for...of循環遍歷。 /*** 迭代器是一種機制 是一種接口 只要數據解構實現了接口 就可…

力扣labuladong一刷day36天

力扣labuladong一刷day36天 一、96. 不同的二叉搜索樹 題目鏈接:https://leetcode.cn/problems/unique-binary-search-trees/ 思路:這是一道典型的動態規劃題,從n3來看 子樹有幾種形態 (0, 2)、(1, 1)、(2, 0)有規律可循,即為左…

飛天使-linux操作的一些技巧與知識點4

文章目錄 ansible配置文件的優先級嘗試開始進行操作ansible常用模塊ansible 的playbook示例安裝phpplaybook中變量的引用 ansible yum install -y ansible 測試是否可用 ansible localhost -m ping /etc/ansible/ansible.cfg :主配置文件,配置 ansible…

大公司求我用Kotlin寫個通用爬蟲模板

bug虐我千百遍,我待他如初戀。每次深夜挑燈都是我與bug較量的時間。今天我要說的就是寫一個爬蟲模版,自動抓取百度圖片的教程,這次使用Kotlin編寫的爬蟲程序在Scrapy框架下完成的,如有不足歡迎指正。 首先,使用Kotlin編…