使用和了解Valgrind核心
使用和了解Valgrind核心
目錄
2.1。Valgrind與您的程序一致2.2。入門2.3。評論2.4。報告錯誤2.5。抑制錯誤2.6。核心命令行選項(xiàng)本章介紹了Valgrind核心服務(wù),命令行選項(xiàng)和行為。這意味著它是相關(guān)的,無論你使用什么特定的工具。這些信息應(yīng)該足以使您有效地日常使用Valgrind。與Valgrind核心相關(guān)的高級主題在Valgrind的核心內(nèi)容中介紹:高級主題。
術(shù)語的一點(diǎn):本章中大多數(shù)提及“Valgrind”是指Valgrind的核心服務(wù)。
2.1。Valgrind與您的程序一致
Valgrind旨在盡可能不侵入。它直接與現(xiàn)有的可執(zhí)行文件一起工作。您不需要重新編譯,重新鏈接或以其他方式修改要檢查的程序。
你這樣調(diào)用Valgrind:
valgrind [valgrind-options] your-prog [your-prog-options]最重要的選項(xiàng)是--tool哪個Valgrind工具運(yùn)行。例如,如果要ls -l使用內(nèi)存檢查工具M(jìn)emcheck?運(yùn)行命令?,請發(fā)出以下命令:
valgrind --tool = memcheck ls -l但是,Memcheck是默認(rèn)值,所以如果要使用它,您可以省略該--tool選項(xiàng)。
無論使用哪種工具,Valgrind在啟動之前都會控制您的程序。調(diào)試信息是從可執(zhí)行文件和關(guān)聯(lián)的庫中讀取的,以便在適當(dāng)?shù)臅r候可以根據(jù)源代碼位置來編寫錯誤消息和其他輸出。
然后您的程序在由Valgrind核心提供的合成CPU上運(yùn)行。當(dāng)?shù)谝淮螆?zhí)行新代碼時,核心將代碼移動到所選擇的工具。該工具為此添加了自己的測試代碼,并將結(jié)果轉(zhuǎn)回核心,該核心協(xié)調(diào)該儀器化代碼的持續(xù)執(zhí)行。
各種工具之間添加的儀器代碼量有很大差異。在比例的一端,Memcheck添加代碼來檢查每個內(nèi)存訪問和每個計算的值,使其運(yùn)行速度比本機(jī)慢10-50倍。另一方面,Nulgrind最小的工具根本不添加任何工具,只能造成4倍的減速。
Valgrind模擬程序執(zhí)行的每個指令。因此,活動工具不僅會檢查應(yīng)用程序中的代碼,還可以檢查所有支持動態(tài)鏈接庫(包括C庫,圖形庫等)的配置文件。
如果您使用錯誤檢測工具,Valgrind可能會檢測系統(tǒng)庫中的錯誤,例如您必須使用的GNU C或X11庫。您可能不會對這些錯誤感興趣,因?yàn)槟赡軣o法控制該代碼。因此,Valgrind允許您選擇性地抑制錯誤,通過將它們記錄在Valgrind啟動時讀取的抑制文件中。構(gòu)建機(jī)制選擇默認(rèn)抑制,為您的機(jī)器上檢測到的操作系統(tǒng)和庫提供合理的行為。為了使寫入更容易,您可以使用該?--gen-suppressions=yes選項(xiàng)。這告訴Valgrind為每個報告的錯誤打印一個壓縮,然后您可以將其復(fù)制到抑制文件中。
不同的錯誤檢查工具報告不同種類的錯誤。因此,抑制機(jī)制允許您說明每種抑制適用的工具或工具。
2.2。入門
首先,請考慮重新編譯應(yīng)用程序和支持啟用調(diào)試信息的庫(-g選項(xiàng))可能是有益的。沒有調(diào)試信息,最好的Valgrind工具將能夠做的是猜測一個特定的代碼段所屬的功能,這使得錯誤消息和分析輸出幾乎沒用。隨著-g,您將收到指向相關(guān)源代碼行的消息。
另外您可能想要考慮的一個選項(xiàng)是,如果您正在使用C ++,那么-fno-inline。這使得更容易看到函數(shù)調(diào)用鏈,這可以幫助減少在大型C ++應(yīng)用程序上導(dǎo)航時的混亂。例如,使用Memcheck調(diào)試OpenOffice.org在使用此選項(xiàng)時會更容易一些。您不需要這樣做,但是這樣做有助于Valgrind產(chǎn)生更準(zhǔn)確,更少的混淆錯誤報告。如果您打算使用GNU GDB或其他調(diào)試器調(diào)試程序,那么您可能已經(jīng)設(shè)置好了。或者,Valgrind選項(xiàng)?--read-inline-info=yes指示Valgrind讀取描述內(nèi)聯(lián)信息的調(diào)試信息。這樣,即使應(yīng)用程序使用內(nèi)聯(lián)編譯,函數(shù)調(diào)用鏈也將被正確顯示。
如果您打算使用Memcheck:在極少數(shù)情況下,已經(jīng)觀察到編譯器優(yōu)化(等于-O2?或者等等,有時候-O1)生成的代碼會使Memcheck錯誤地報告未初始化的值錯誤或缺少未初始化的值錯誤。我們已經(jīng)詳細(xì)研究了這一點(diǎn),不幸的是結(jié)果是這樣做會給已經(jīng)是一個緩慢的工具帶來進(jìn)一步的顯著的放緩。所以最好的解決方案是關(guān)閉優(yōu)化。因?yàn)檫@經(jīng)常使事情變得難以控制,所以使用合理的妥協(xié)?-O。這使您獲得更高優(yōu)化水平的大部分優(yōu)勢,同時保持Memcheck的假陽性或假陰性的機(jī)會相對較小。也,-Wall您應(yīng)該編譯代碼, 因?yàn)樗梢宰R別Valgrind在較高優(yōu)化級別可能會錯過的一些或所有問題。(-Wall?一般來說,使用也是一個好主意)所有其他工具(據(jù)我們所知)不受優(yōu)化級別的影響,對于像Cachegrind這樣的分析工具,最好在其正常優(yōu)化級別編譯程序。
Valgrind了解GCC 3.1及更高版本使用的DWARF2 / 3/4格式。用于“stabs”調(diào)試格式的讀者(在3.1之前由GCC版本使用)在Valgrind 3.9.0中被禁用。
準(zhǔn)備好滾動時,按上述方法運(yùn)行Valgrind。請注意,您應(yīng)該在此運(yùn)行真實(shí)的(機(jī)器代碼)可執(zhí)行文件。如果您的應(yīng)用程序是由例如shell或Perl腳本啟動的,那么您需要修改它才能在真正的可執(zhí)行文件上調(diào)用Valgrind。直屬Valgrind的運(yùn)行這些腳本會導(dǎo)致你得到有關(guān)錯誤報告?/bin/sh,?/usr/bin/perl或者你使用任何解釋。這可能不是你想要的,可能會令人困惑。你可以通過提供這個選項(xiàng)來強(qiáng)制這個問題?--trace-children=yes,但仍然可能會有混亂。
2.3。評論
Valgrind工具寫一個評論,一串文本,詳細(xì)的錯誤報告和其他重大事件。評論中的所有行都具有以下形式:
== 12345 == some-message-from-Valgrind的12345是進(jìn)程ID。該方案可以方便地將程序輸出與Valgrind注釋區(qū)分開來,也可以容易地區(qū)分不同流程的注釋,這些流程由于任何原因而被合并在一起。
默認(rèn)情況下,Valgrind工具只會將重要信息寫入評論,以免發(fā)生帶有次要重要信息的信息。如果您想了解有關(guān)正在發(fā)生的更多信息,請重新運(yùn)行,將-v選項(xiàng)傳遞給Valgrind。第二個?-v給出更多的細(xì)節(jié)。
您可以將注釋引導(dǎo)到三個不同的地方:
默認(rèn)值:將其發(fā)送到文件描述符,默認(rèn)情況下為2(stderr)。所以,如果你給核心沒有選項(xiàng),它將寫入標(biāo)準(zhǔn)錯誤流的注釋。如果要將其發(fā)送到其他文件描述符,例如9號,您可以指定?--log-fd=9。
這是最簡單和最常見的安排,但是當(dāng)Valgrinding整個進(jìn)程的樹,特別是stdin / stdout / stderr特定的文件描述符可用于自己使用時,可能會導(dǎo)致問題。
一個較少侵入性的選項(xiàng)是將注釋寫入您指定的文件?--log-file=filename。有特殊的格式說明符可用于在日志文件名中使用進(jìn)程ID或環(huán)境變量名。如果您的程序調(diào)用多個進(jìn)程(特別是MPI程序),這些是有用的/必要的。有關(guān)?詳細(xì)信息,請參閱基本選項(xiàng)部分。
最簡單的選擇是將評論發(fā)送到網(wǎng)絡(luò)套接字。套接字被指定為IP地址和端口號對,如下所示:--log-socket=192.168.0.1:12345如果要將輸出發(fā)送到主機(jī)IP 192.168.0.1端口12345(注意:我們不知道12345是否是預(yù)先存在的重要性的端口)。您也可以省略端口號:?--log-socket=192.168.0.1在這種情況下,使用默認(rèn)端口1500。該默認(rèn)值由VG_CLO_DEFAULT_LOGPORT源中的常量定義?。
請注意,不幸的是,您必須在此使用IP地址,而不是主機(jī)名。
如果您沒有在另一端收聽東西,寫入網(wǎng)絡(luò)套接字是毫無意義的。我們提供一個簡單的監(jiān)聽程序,?valgrind-listener它接受指定端口上的連接,并將發(fā)送到stdout的任何東西復(fù)制。大概有人會告訴我們這是一個可怕的安全隱患。人們似乎有可能在充分的時間內(nèi)寫出更復(fù)雜的聽眾。
valgrind-listener可以接受多達(dá)50個Valgrinded進(jìn)程的同時連接。在每行輸出的前面,打印當(dāng)前活動連接數(shù)在圓括號中。
valgrind-listener?接受三個命令行選項(xiàng):
-e --exit-at-zero當(dāng)連接的進(jìn)程的數(shù)量恢復(fù)為零時,退出。沒有這個,它將永遠(yuǎn)運(yùn)行,就是直到你發(fā)送Control-C。
默認(rèn)情況下,監(jiān)聽器最多可以連接50個進(jìn)程。偶爾,這個數(shù)字太小了。使用此選項(xiàng)提供不同的限制。例如?--max-connect=100。
將其偵聽的端口從默認(rèn)端口(1500)更改。指定的端口必須在1024到65535之間。同樣的限制適用于由--log-socketValgrind本身指定的端口號?。
如果Valgrinded進(jìn)程無法連接到偵聽器,無論什么原因(偵聽器未運(yùn)行,無效或無法訪問的主機(jī)或端口等),Valgrind將切換回寫入stderr的注釋。任何失去與收聽者建立連接的進(jìn)程也是如此。換句話說,殺死偵聽器不會殺死向其發(fā)送數(shù)據(jù)的進(jìn)程。
關(guān)于評論和工具分析輸出之間的關(guān)系,這里是一個重要的一點(diǎn)。評論包含Valgrind核心和所選工具的混合信息。如果工具報告錯誤,它會將其報告給評論。但是,如果該工具進(jìn)行概要分析,則根據(jù)工具,配置文件數(shù)據(jù)將被寫入某種文件,并且與執(zhí)行的--log-*選項(xiàng)無關(guān)?。評論意圖是一個低帶寬,人類可讀的頻道。另一方面,分析數(shù)據(jù)通常是大量的,沒有進(jìn)一步的處理是沒有意義的,這就是為什么我們選擇這種安排。
2.4。報告錯誤
當(dāng)錯誤檢查工具檢測到程序發(fā)生不良情況時,會將錯誤信息寫入評論。這是Memcheck的一個例子:
== 25832 ==大小4讀取無效 == 25832 == at 0x8048724:BandMatrix :: ReSize(int,int,int)(bogon.cpp:45) == 25832 == by 0x80487AF:main(bogon.cpp:66) == 25832 ==地址0xBFFFF74C不是stack'd,malloc'd或free'd該消息表示該程序?qū)Φ刂?xBFFFF74C執(zhí)行了一個非法的4字節(jié)讀取操作,只要Memcheck可以告訴,它不是有效的堆棧地址,也不對應(yīng)于任何當(dāng)前的堆塊或最近釋放的堆塊。讀取是在bogon.cpp同一文件的第66行從第45?行發(fā)出的。對于與識別的(當(dāng)前的或釋放的)堆塊相關(guān)聯(lián)的錯誤,例如讀取釋放的內(nèi)存,Valgrind不僅報告發(fā)生錯誤的位置,而且在相關(guān)聯(lián)的堆塊被分配/釋放的地方。
Valgrind記得所有錯誤報告。當(dāng)檢測到錯誤時,將與舊報告進(jìn)行比較,以查看是否重復(fù)。如果是這樣,則會注意到錯誤,但不會發(fā)出進(jìn)一步的評論。這樣就避免了一大堆重復(fù)的錯誤報告。
如果您想知道每個錯誤發(fā)生多少次,請運(yùn)行該-v選項(xiàng)。執(zhí)行完成后,所有的報告將隨著它們的發(fā)生次數(shù)一并打印出來并排序。這使得很容易看出哪些錯誤最常發(fā)生。
在相關(guān)操作實(shí)際發(fā)生之前報告錯誤。例如,如果您正在使用Memcheck并且您的程序嘗試從地址零讀取,Memcheck會發(fā)出一個消息,這樣會產(chǎn)生一個消息,您的程序可能會因分段錯誤而死亡。
一般來說,您應(yīng)該按照報告的順序嘗試修復(fù)錯誤。不這樣做可能會令人困惑。例如,當(dāng)在Memcheck上運(yùn)行時,將未初始化的值復(fù)制到多個存儲器位置并稍后使用它們的程序?qū)⑸啥鄠€錯誤消息。第一個這樣的錯誤消息可能給出最直接的線索,導(dǎo)致問題的根本原因。
檢測重復(fù)錯誤的過程是相當(dāng)昂貴的,如果您的程序產(chǎn)生大量錯誤,可能會成為顯著的性能開銷。為了避免嚴(yán)重的問題,Valgrind將會在收到1000個不同的錯誤后立即停止收集錯誤,總共有10,000,000個錯誤。在這種情況下,您可以停止您的程序并修復(fù)它,因?yàn)閂algrind在此之后不會告訴您任何其他有用的東西。請注意,在刪除了抑制誤差之后,1,000 / 10,000,000的限制適用。這些限制在m_errormgr.c必要時定義并可以增加。
為了避免這種限制,您可以使用該?--error-limit=no選項(xiàng)。那么Valgrind總是會顯示錯誤,不管有多少。仔細(xì)使用此選項(xiàng),因?yàn)樗赡軐π阅苡胁涣加绊憽?/p>
2.5。抑制錯誤
錯誤檢查工具可以檢測系統(tǒng)庫中的許多問題,例如預(yù)裝了操作系統(tǒng)的C庫。你不能輕易地修復(fù)這些錯誤,但是您不希望看到這些錯誤(是的,有很多!)所以Valgrind在啟動時讀取一個錯誤列表來抑制。./configure系統(tǒng)構(gòu)建時腳本創(chuàng)建默認(rèn)壓縮文件?。
您可以隨時修改并添加到抑制文件,或者更好地編寫自己的文件。允許多個壓縮文件。如果您的項(xiàng)目的一部分包含您不能或不想修復(fù)的錯誤,但您不想不斷提醒他們,這是有用的。
注:?到目前為止添加鎮(zhèn)壓最簡單的方法是使用--gen-suppressions=yes在描述選項(xiàng)核心命令行選項(xiàng)。這會自動產(chǎn)生抑制。為獲得最佳效果,您可能需要--gen-suppressions=yes手動編輯輸出?,在這種情況下,請閱讀本節(jié)。
描述要抑制的每個錯誤都是非常具體地描述的,以最大限度地減少抑制指令無意中抑制一些你想要看到的類似錯誤的可能性。抑制機(jī)制旨在允許精確而靈活地規(guī)定誤差來抑制。
如果使用該-v選項(xiàng),則在執(zhí)行結(jié)束時,Valgrind將為每個使用的抑制打印一行,給出其使用次數(shù),其名稱以及定義了抑制的文件名和行號。根據(jù)抑制類型,文件名和行號可選地附加附加信息(例如通過memcheck泄漏抑制抑制的塊數(shù)和字節(jié)數(shù))。以下是運(yùn)行中使用的禁用valgrind -v --tool=memcheck ls -l:
--1610-- used_suppression:2 dl-hack3-cond-1 /usr/lib/valgrind/default.supp:1234 --1610-- used_suppression:2 glibc-2.5.x-on-SUSE-10.2-(PPC)-2a /usr/lib/valgrind/default.supp:1234允許多個禁止文件。Valgrind負(fù)載抑制模式,$PREFIX/lib/valgrind/default.supp除非?--default-suppressions=no已指定。您可以通過指定--suppressions=/path/to/file.supp一次或多次來要求從其他文件添加抑制?。
如果您想了解有關(guān)抑制的更多信息,請查閱現(xiàn)有的壓縮文件,同時閱讀以下文檔。glibc-2.3.supp源文件中的文件提供了一些很好的例子。
每個抑制都有以下組件:
-
第一行:它的名字。這僅僅提供了一個方便的名稱到抑制,由此它在使用鎮(zhèn)壓的打印輸出時,程序完成內(nèi)容中所指。名字不重要,任何識別字符串都會做。
-
第二行:抑制的工具的名稱(如果多于一個,以逗號分隔),以及由冒號分隔的抑制本身的名稱(nb:不允許有空格),例如:
tool_name1,tool_name2:suppression_name回想一下,Valgrind是一個模塊化系統(tǒng),其中不同的儀器工具可以在運(yùn)行時觀察您的程序。由于不同的工具檢測到不同種類的錯誤,因此有必要說明抑制對哪些工具有意義。
工具在啟動時會抱怨工具不明白對此的任何抑制。工具忽略不針對他們的抑制。因此,將所有工具的禁止放在同一個壓縮文件中是相當(dāng)實(shí)用的。
-
下一行:少數(shù)抑制類型在第二行之后有額外的信息(例如,Param?對Memcheck?的抑制)
-
剩余行:這是錯誤的調(diào)用上下文 - 導(dǎo)致它的函數(shù)調(diào)用鏈。最多可以有24行。
位置可以是共享對象或函數(shù)的名稱。他們開始?obj:和?fun:分別。要匹配的功能和對象名稱可能會使用通配符?*和??。
重要說明:?C ++函數(shù)名稱必須被?破壞。如果您手動寫入抑制,請使用該--demangle=no選項(xiàng)在錯誤消息中獲取被破壞的名稱。一個被破壞的C ++名稱的例子是?_ZN9QListView4showEv。這是GNU C ++編譯器在內(nèi)部使用的形式,以及在壓縮文件中必須使用的形式。等效的被清空的名字,QListView::show()就是你在C ++源代碼級別看到的。
位置線也可以簡單地“?...”(三個點(diǎn))。這是一個幀級通配符,匹配零個或多個幀。幀級通配符是有用的,因?yàn)樗鼈兛梢匀菀椎睾雎愿信d趣的幀之間不同數(shù)量的不感興趣的幀。當(dāng)編寫壓縮時,這通常是重要的,這些抑制是針對編譯器完成的功能內(nèi)聯(lián)量的變化而進(jìn)行的。
-
最后,整個鎮(zhèn)壓必須在花括號之間。每個大括號必須是自己的第一個字符。
當(dāng)抑制錯誤與抑制中的所有細(xì)節(jié)匹配時,抑制只會抑制錯誤。以下是一個例子:
{__gconv_transform_ascii_internal / __ mbrtowc / mbtowcMEMCHECK:值4有趣的:__ gconv_transform_ascii_internal有趣的:__ MBR * TOC好玩的:mbtowc }這意味著:僅對于Memcheck,當(dāng)數(shù)據(jù)大小為4時,當(dāng)該函數(shù)發(fā)生在函數(shù)__gconv_transform_ascii_internal中時,當(dāng)從名稱匹配的任何函數(shù)調(diào)用該函數(shù)時?,禁止使用未初始化的值錯誤,當(dāng)?__mbr*toc從?mbtowc。在任何其他情況下都不適用。為用戶識別此抑制的字符串是__gconv_transform_ascii_internal/__mbrtowc/mbtowc。
(有關(guān)Memcheck抑制類型的詳細(xì)信息,請參閱編寫抑制文件。)
另一個例子,再次為Memcheck工具:
{libX11.so.6.2 / libX11.so.6.2 / libXaw.so.7.0MEMCHECK:值4OBJ:/usr/X11R6/lib/libX11.so.6.2OBJ:/usr/X11R6/lib/libX11.so.6.2OBJ:/usr/X11R6/lib/libXaw.so.7.0 }這樣可以抑制libX11.so.6.2從任何位置調(diào)用時在同一個庫中的任何地方調(diào)用?時的任何大小4未初始化值錯誤libXaw.so.7.0。不符合要求的位置是令人遺憾的,但是關(guān)于所有你可以期望的,因?yàn)樵谶@個例子的Linux發(fā)行版上發(fā)布的X11庫已經(jīng)刪除了它們的符號表。
雖然上述兩個例子并不清楚,但您可以自由地混合obj:和?fun:排除一些壓制。
最后,這里是一個使用三個框架通配符的例子:
{一個做作-示例MEMCHECK:泄漏有趣:的malloc...好玩的:DDD...好玩的:CCC...好玩的:主 } 這樣做會抑制Memcheck內(nèi)存泄漏錯誤,在分配是通過main?調(diào)用(盡管任意數(shù)量的中介,包括零)?ccc,通過調(diào)用ddd和最終調(diào)用?來完成的malloc.。2.6。核心命令行選項(xiàng)
如上所述,Valgrind的核心接受一組共同的選擇。這些工具還可以接受特定于工具的選項(xiàng),這些選項(xiàng)是為每個工具單獨(dú)記錄的。
在大多數(shù)情況下,Valgrind的默認(rèn)設(shè)置成功地給出了合理的行為。我們按粗略類別分組可用的選項(xiàng)。
2.6.1。工具選擇選項(xiàng)
單一最重要的選項(xiàng)。
--tool=<toolname> [default: memcheck]運(yùn)行Valgrind工具toolname,例如memcheck,cachegrind,callgrind,helgrind,drd,massif,lackey,none,exp-sgcheck,exp-bbv,exp-dhat等
2.6.2。基本選項(xiàng)
這些選項(xiàng)適用于所有工具。
-h --help顯示所有選項(xiàng)的幫助,包括核心和所選工具。如果該選項(xiàng)重復(fù),則相當(dāng)于給予?--help-debug。
--help與之一樣,但也列出了通常僅用于Valgrind開發(fā)人員的調(diào)試選項(xiàng)。
顯示Valgrind內(nèi)核的版本號。工具可以有自己的版本號。有一個方案來確保只有核心版本是已知的工具才能執(zhí)行的工具。這樣做是為了盡量減少由于工具與核心版本不兼容而產(chǎn)生的奇怪問題的機(jī)會。
靜默運(yùn)行,只打印錯誤消息。如果您正在進(jìn)行回歸測試或有其他自動化測試機(jī)器,那么有用。
更冗長?提供有關(guān)程序各個方面的更多信息,例如:加載的共享對象,使用的禁用,檢測和執(zhí)行引擎的進(jìn)度以及有關(guān)異常行為的警告。重復(fù)該選項(xiàng)會增加詳細(xì)程度。
啟用后,Valgrind將跟蹤通過exec系統(tǒng)調(diào)用發(fā)起的子進(jìn)程。這對于多進(jìn)程程序是必需的。
請注意,Valgrind確實(shí)會追蹤到一個fork(的孩子)?,因?yàn)?fork這樣一個進(jìn)程的相同拷貝就很難,所以這個選項(xiàng)可能被命名得很糟。然而,大多數(shù)fork電話的孩子?立即打電話exec?。
此選項(xiàng)僅在指定時--trace-children=yes才有效果?。它允許一些孩子被跳過。該選項(xiàng)為Valgrind不應(yīng)該跟蹤的可執(zhí)行文件的名稱使用逗號分隔的模式列表。這些模式可以包括元字符??和*,它們具有通常的意義。
這可以用于從Valgrind上運(yùn)行的進(jìn)程樹中修剪不感興趣的分支。但是,使用它時應(yīng)該小心。當(dāng)Valgrind跳過跟蹤到可執(zhí)行文件時,它不會跳過跟蹤該可執(zhí)行文件,它也跳過跟蹤任何可執(zhí)行文件的子進(jìn)程。換句話說,該標(biāo)志不僅僅是引起跟蹤停止在指定的可執(zhí)行文件 - 它跳過跟蹤任何一個指定的可執(zhí)行文件的整個進(jìn)程子樹。
這是一樣的?--trace-children-skip,有一個區(qū)別:關(guān)于是否追蹤到子進(jìn)程的決定是通過檢查子進(jìn)程的參數(shù)而不是其可執(zhí)行文件的名稱來進(jìn)行的。
啟用后,Valgrind不會顯示任何來自fork調(diào)用的子進(jìn)程的調(diào)試或記錄輸出。這可以使輸出在處理創(chuàng)建子進(jìn)程時更不容易混淆(盡管更具誤導(dǎo)性)。它特別有用--trace-children=。如果要求XML輸出(--xml=yes),則強(qiáng)烈建議使用此選項(xiàng),否則來自子級和父級的XML可能會混淆,這通常會使其無用。
當(dāng)Valgrind的將提供“gdbserver的”功能?--vgdb=yes或--vgdb=full指定的。這允許外部GNU GDB調(diào)試器在Valgrind上運(yùn)行時控制和調(diào)試程序。?--vgdb=full引起顯著的性能開銷,但提供更精確的斷點(diǎn)和觀察點(diǎn)。有關(guān)詳細(xì)說明,請參閱使用Valgrind的gdbserver和GDB調(diào)試程序。
如果嵌入式gdbserver已啟用但目前沒有使用gdb,則vgdb?命令行實(shí)用程序可以從shell向Valgrind發(fā)送“監(jiān)視器命令”。Valgrind內(nèi)核提供一組?Valgrind監(jiān)視器命令。工具可以選擇提供特定于工具的監(jiān)視器命令,這些命令在工具特定的章節(jié)中有所記錄。
當(dāng)Valgrind gdbserver啟用--vgdb=yes或時,使用此選項(xiàng)?--vgdb=full。報告錯誤的工具將number在凍結(jié)程序并等待您與GDB連接之前等待“?”錯誤報告。因此,值為零將導(dǎo)致在執(zhí)行程序之前啟動gdbserver。這通常用于在執(zhí)行前插入GDB斷點(diǎn),并且還可以與不報告錯誤的工具(如Massif)一起使用。
當(dāng)Valgrind gdbserver啟用--vgdb=yes或時,使用此選項(xiàng)?--vgdb=full。--vgdb-error報告之后,將為每個錯誤調(diào)用Valgrind gdbserver?。您還可以詢問為其他事件調(diào)用Valgrind gdbserver,以下列方式之一指定:
-
一個或多個逗號分隔的列表?startup exit valgrindabexit。
值startup?exit?valgrindabexit分別表示在程序執(zhí)行之前,在程序的最后一個指令之后,在Valgrind異常退出(例如內(nèi)部錯誤,內(nèi)存不足,...)中調(diào)用gdbserver。
注意:startup并且?--vgdb-error=0將會在程序執(zhí)行之前調(diào)用Valgrind gdbserver。此外?--vgdb-error=0,還將導(dǎo)致您的程序停止所有后續(xù)錯誤。
-
all指定完整集。相當(dāng)于?--vgdb-stop-at=startup,exit,valgrindabexit。
-
none?為空集。
啟用后,Valgrind將通過gdbserver monitor命令在出口或請求時打印出打開的文件描述符列表v.info open_fds。與每個文件描述符一起打印文件打開位置的堆棧回溯以及與文件描述符相關(guān)的任何細(xì)節(jié),如文件名或套接字詳細(xì)信息。
啟用后,每個消息之前都會顯示自啟動以來的已經(jīng)逝去的時鐘,表示為天,小時,分鐘,秒和毫秒。
指定Valgrind應(yīng)將其所有消息發(fā)送到指定的文件描述符。默認(rèn)值2是標(biāo)準(zhǔn)錯誤通道(stderr)。請注意,這可能會干擾客戶端自己使用stderr,因?yàn)閂algrind的輸出將與客戶端發(fā)送給stderr的任何輸出交錯。
指定Valgrind應(yīng)將其所有郵件發(fā)送到指定的文件。如果文件名為空,則會導(dǎo)致中止。有三種特殊的格式說明符可以在文件名中使用。
%p被當(dāng)前進(jìn)程ID替換。這對于調(diào)用多個進(jìn)程的程序非常有用。警告:如果您使用--trace-children=yes并且您的程序調(diào)用多個進(jìn)程或您的程序fork而不調(diào)用exec,并且您不使用此說明符(或%q下面的說明符),則所有這些進(jìn)程的Valgrind輸出將進(jìn)入一個文件,可能會混亂并且可能不完整。
%q{FOO}被替換為環(huán)境變量的內(nèi)容FOO。如果?{FOO}部件畸形,會導(dǎo)致中止。此說明符很少需要,但在某些情況下(例如運(yùn)行MPI程序時)非常有用。這個想法是指定一個變量,該變量將為作業(yè)中的每個進(jìn)程設(shè)置不同,例如BPROC_RANK或MPI設(shè)置中適用的任何內(nèi)容。如果未設(shè)置命名環(huán)境變量,則會導(dǎo)致中止。請注意,在某些shell中,?角色{和}角色可能需要使用反斜杠進(jìn)行轉(zhuǎn)義。
%%被替換%。
如果%其后的任何其他字符,則導(dǎo)致中止。
如果文件名指定相對文件名,則將其放入程序的初始工作目錄中:當(dāng)程序在fork之后或exec之后執(zhí)行時,這是當(dāng)前目錄。如果它指定絕對文件名(即以'/'開始),那么它將放在那里。
指定Valgrind應(yīng)將其所有消息發(fā)送到指定IP地址的指定端口。可以省略端口,在這種情況下使用端口1500。如果無法連接到指定的套接字,則Valgrind將返回寫入標(biāo)準(zhǔn)錯誤(stderr)的輸出。此選項(xiàng)旨在與valgrind-listener程序一起使用?。有關(guān)詳細(xì)信息,請參閱?手冊中的注釋。
2.6.3。錯誤相關(guān)選項(xiàng)
所有可以報告錯誤的工具都使用這些選項(xiàng),例如Memcheck,而不是Cachegrind。
--xml=<yes|no> [default: no]啟用時,輸出的重要部分(例如工具錯誤消息)將采用XML格式而不是純文本格式。此外,XML輸出將被發(fā)送到與純文本輸出不同的輸出通道。因此,還必須使用的一個?--xml-fd,--xml-file或?--xml-socket到指定的XML將被發(fā)送。
不太重要的消息將仍然以純文本被打印,但是,因?yàn)閄ML輸出和明文輸出被發(fā)送到不同的輸出信道(純文本輸出的目的地仍然由控制--log-fd,--log-file?和--log-socket)這不應(yīng)引起問題。
此選項(xiàng)旨在使消費(fèi)Valgrind輸出的工具(如GUI前端)變得更簡單。目前這個選項(xiàng)適用于Memcheck,Helgrind,DRD和SGcheck。輸出格式在docs/internals/xml-output-protocol4.txt?Valgrind 3.5.0或更高版本的源代碼樹中的文件?中指定。
GUI請求XML輸出時,推薦的選項(xiàng)是:--xml=yes啟用XML輸出,?--xml-file將XML輸出發(fā)送到(大概是GUI選擇的)文件,--log-file將純文本輸出發(fā)送到第二個GUI選擇的文件,?--child-silent-after-fork=yes,并將?-q純文本輸出限制為由Valgrind本身創(chuàng)建的關(guān)鍵錯誤消息。例如,無法讀取指定的抑制文件將被視為關(guān)鍵錯誤消息。這樣,為了成功運(yùn)行文本輸出文件將為空。但是如果它不是空的,那么它將包含GUI用戶應(yīng)該注意的重要信息。
指定Valgrind應(yīng)將其XML輸出發(fā)送到指定的文件描述符。它必須與之配合使用?--xml=yes。
指定Valgrind應(yīng)將其XML輸出發(fā)送到指定的文件。它必須與之配合使用?--xml=yes。出現(xiàn)在文件名中的任何%p或者?%q序列以與它們完全相同的方式進(jìn)行擴(kuò)展--log-file。有關(guān)--log-file詳細(xì)信息,請參閱說明。
指定Valgrind應(yīng)將指定端口的XML輸出發(fā)送到指定的IP地址。它必須與之配合使用--xml=yes。參數(shù)的形式與使用的形式相同--log-socket。有關(guān)--log-socket?詳細(xì)信息,請參閱說明。
在XML輸出的開始處嵌入一個額外的用戶注釋字符串。僅在--xml=yes指定時才能工作;?否則忽略。
啟用/禁用C ++名稱的自動解碼(解碼)。默認(rèn)啟用。啟用后,Valgrind將嘗試將編碼的C ++名稱轉(zhuǎn)換為接近原始文件的東西。demangler處理由g ++版本2.X,3.X和4.X驅(qū)動的符號。
關(guān)于解密的一個重要事實(shí)是在壓制文件中提到的函數(shù)名稱應(yīng)該處于它們的格式。在搜索適用的抑制方面,Valgrind不會使功能名稱發(fā)生拆分,因?yàn)榉駝t會使壓縮文件內(nèi)容取決于Valgrind的分離機(jī)器的狀態(tài),并且還會減緩抑制匹配。
指定標(biāo)識程序位置的堆棧跟蹤中顯示的最大條目數(shù)。請注意,僅使用前四個功能位置(當(dāng)前功能中的位置,以及其三個直接調(diào)用者的位置)常見錯誤。所以這并不影響所報錯誤的總數(shù)。
最大值為500.請注意,較高的設(shè)置將使Valgrind運(yùn)行速度更慢,并占用更多內(nèi)存,但在使用深嵌套的調(diào)用鏈的程序時可能會很有用。
堆棧掃描支持僅在ARM目標(biāo)上可用。
這些標(biāo)志通過堆棧掃描啟用和控制堆棧展開。當(dāng)正常堆棧展開機(jī)制 - 使用Dwarf CFI記錄和幀指針跟隨失敗時,堆棧掃描可能能夠恢復(fù)堆棧跟蹤。
請注意,堆棧掃描是一種不精確的啟發(fā)式機(jī)制,可能會產(chǎn)生非常誤導(dǎo)的結(jié)果,或者根本沒有。它只能在緊急情況下使用,正常展開失敗,重要的是仍然有堆棧跟蹤。
堆棧掃描是一種簡單的技術(shù):展開器從堆棧中讀取單詞,并嘗試猜測哪些可能是返回地址,通過檢查它們是否指向ARM或Thumb調(diào)用指令。如果是這樣,該詞被添加到回溯。
當(dāng)函數(shù)調(diào)用返回時,會發(fā)生主要的危險,其返回地址被暴露,并且調(diào)用一個新的函數(shù),但新函數(shù)不會覆蓋舊的地址。這樣做的結(jié)果是回溯可能包含已經(jīng)返回的函數(shù)的條目,因此非常混亂。
此實(shí)現(xiàn)的第二個限制是它將僅掃描包含起始堆棧指針的頁面(通常為4KB)。如果堆棧幀較大,則這可能導(dǎo)致軌跡中僅存在少量(甚至不甚甚)。此外,如果您不幸運(yùn),并且在其包含頁面的末尾附近有一個初始堆棧指針,掃描可能會錯過所有有趣的幀。
默認(rèn)情況下,堆棧掃描被禁用。正常的使用情況是要求堆棧跟蹤否則會很短。所以,啟用它,使用--unw-stack-scan-thresh=number。這要求Valgrind嘗試使用堆棧掃描來“擴(kuò)展”包含少于number幀的堆棧跟蹤。
如果堆棧掃描發(fā)生,它將只生成最多指定的幀數(shù)--unw-stack-scan-frames。通常,堆棧掃描會生成這么多垃圾條目,默認(rèn)情況下該值設(shè)置為低值(5)。在任何情況下,堆棧跟蹤大于--num-callers創(chuàng)建指定的值。
啟用后,Valgrind停止報告錯誤,總共有10,000,000個,或者1,000個不同的。這是為了阻止錯誤跟蹤機(jī)制在具有許多錯誤的程序中成為巨大的性能開銷。
如果Valgrind在運(yùn)行中報告任何錯誤,則指定返回的替代退出代碼。當(dāng)設(shè)置為默認(rèn)值(零)時,Valgrind的返回值將始終是正在仿真的進(jìn)程的返回值。當(dāng)設(shè)置為非零值時,將返回該值,如果Valgrind檢測到任何錯誤。這對于使用Valgrind作為自動化測試套件的一部分非常有用,因?yàn)橥ㄟ^檢查返回碼,可以輕松檢測Valgrind報告錯誤的測試用例。
當(dāng)錯誤輸出為純文本(即XML未使用)時,?--error-markers指示在每個錯誤之前(之后)輸出包含begin(end)字符串的行。
這樣的標(biāo)記線便于搜索包含與程序輸出混合的valgrind錯誤的輸出文件中的錯誤和/或提取錯誤。
請注意,空標(biāo)記被接受。因此,只能使用開始(或結(jié)束)標(biāo)記。
啟用/禁用打印非法指令診斷。默認(rèn)情況下啟用,但默認(rèn)為禁用?--quiet。通過給出此選項(xiàng),總是可以明確地覆蓋默認(rèn)值。
啟用該功能后,在程序發(fā)出SIGILL信號之前,每當(dāng)遇到Valgrind無法解碼或轉(zhuǎn)換的指令時,都會打印一條警告消息以及一些診斷信息。通常,非法指令表示程序中的錯誤或缺少對Valgrind特定指令的支持。但有些程序會故意嘗試執(zhí)行可能丟失的指令,并捕獲SIGILL信號以檢測處理器功能。使用此標(biāo)志可以避免在這種情況下您會得到的診斷輸出。
默認(rèn)情況下,錯誤的堆棧跟蹤不會顯示下面的任何函數(shù),main因?yàn)榇蠖鄶?shù)時候它不感興趣C庫東西和/或gobbledygook。或者,如果main堆棧跟蹤中不存在堆棧跟蹤,堆棧跟蹤將不會顯示main類似函數(shù)(如glibc)的?任何函數(shù)__libc_start_main。此外,如果?main跟蹤中存在類似函數(shù),則它們被歸一化為(below main)使得輸出更確定。
如果啟用此選項(xiàng),將顯示所有堆棧跟蹤條目,并且main類似的函數(shù)將不會被歸一化。
默認(rèn)情況下,Valgrind僅顯示堆棧跟蹤中的文件名,但不顯示源文件的完整路徑。當(dāng)在大型項(xiàng)目中使用Valgrind,其中源位于多個不同的目錄中時,這可能是不方便的。?--fullpath-after為這個問題提供了靈活的解決方案。當(dāng)此選項(xiàng)存在時,將顯示每個源文件的路徑,其中包含以下所有重要的注意事項(xiàng):如果string在路徑中找到,則將string省略直到和包含的路徑,否則路徑未修改。注意,string不需要作為路徑的前綴。
例如,考慮一個名為的文件?/home/janedoe/blah/src/foo/bar/xyzzy.c。指定--fullpath-after=/home/janedoe/blah/src/?將導(dǎo)致Valgrind顯示名稱foo/bar/xyzzy.c。
因?yàn)樽址恍枰鳛榍熬Y,所以?--fullpath-after=src/會產(chǎn)生相同的輸出。當(dāng)路徑包含任意機(jī)器生成的字符時,這很有用。例如,/my/build/dir/C32A1B47/blah/src/foo/xyzzy?可以修剪路徑?以foo/xyzzy?使用?--fullpath-after=/blah/src/。
如果您只想看到完整的路徑,只需指定一個空字符串:--fullpath-after=。這不是一個特殊情況,只是上述規(guī)則的邏輯后果。
最后,你可以--fullpath-after?多次使用。任何外觀都會導(dǎo)致Valgrind切換到生成完整路徑并應(yīng)用上述過濾規(guī)則。每個生成的路徑按照--fullpath-after指定的順序與所有指定的字符串進(jìn)行比較。要匹配的第一個字符串將導(dǎo)致路徑被截斷,如上所述。如果不匹配,則顯示完整路徑。當(dāng)源從多個不相關(guān)的目錄中抽取時,這有助于切除前綴。
默認(rèn)情況下,Valgrind在幾個眾所周知的路徑中搜索調(diào)試對象,例如/usr/lib/debug/。
但是,您可能希望將調(diào)試對象放置在任意位置,例如在具有有限本地存儲空間的移動設(shè)備上運(yùn)行Valgrind時的外部存儲。另一個例子可能是您沒有在運(yùn)行Valgrind的系統(tǒng)上安裝調(diào)試對象包的權(quán)限的情況。
在這些情況下,您可以提供絕對路徑作為Valgrind通過指定搜索調(diào)試對象的額外最終位置?--extra-debuginfo-path=/path/to/debug/objects。給定的路徑將被添加到搜索對象的絕對路徑名稱。例如,如果Valgrind正在尋找/w/x/y/zz.so?和--extra-debuginfo-path=/a/b/c指定的debuginfo,那么它將在此處查找一個調(diào)試對象?/a/b/c/w/x/y/zz.so。
該標(biāo)志只能指定一次。如果指定多次,則只會保留最后一個實(shí)例。
這是在3.9.0版本中引入的一個新的,實(shí)驗(yàn)性的功能。
在某些情況下,從存儲在不同機(jī)器上的對象讀取debuginfo可能很方便。使用此標(biāo)志,Valgrind將在本地文件系統(tǒng)中找不到debuginfo對象時查詢運(yùn)行在ipaddr偵聽端口上的debuginfo服務(wù)器port。
debuginfo服務(wù)器必須接受端口上的TCP連接port。debuginfo服務(wù)器包含在源文件中auxprogs/valgrind-di-server.c。它將僅從它啟動的目錄中提供。?port如果未指定,默認(rèn)為客戶端和服務(wù)器的1500。
如果Valgrind?/w/x/y/zz.so通過使用debuginfo服務(wù)器查找debuginfo,它將剝離路徑名組件,并僅zz.so在服務(wù)器上請求。反過來,它將僅在其當(dāng)前工作目錄中查找匹配的debuginfo對象。
根據(jù)Valgrind的要求,debuginfo數(shù)據(jù)以小片段(8 KB)傳輸。使用LZO壓縮每個塊以減少傳輸時間。通過單階段802.11g(WiFi)網(wǎng)絡(luò)鏈路實(shí)現(xiàn)了最佳性能。
請注意,即使使用debuginfo服務(wù)器,也會執(zhí)行使用GNU debuglink CRC方案來匹配主要和調(diào)試對象的檢查。要禁用此類檢查,您還需要指定?--allow-mismatched-debuginfo=yes。
默認(rèn)情況下,Valgrind構(gòu)建系統(tǒng)將為valgrind-di-server目標(biāo)平臺構(gòu)建,這幾乎肯定不是您想要的。到目前為止,我們一直無法找到如何獲取automake / autoconf來構(gòu)建它的構(gòu)建平臺。如果要使用它,則必須使用頂部顯示的命令手動重新編譯它auxprogs/valgrind-di-server.c。
當(dāng)從單獨(dú)的debuginfo對象讀取debuginfo時,Valgrind將默認(rèn)使用GNU debuglink機(jī)制檢查main和debuginfo對象是否匹配。這樣保證它不會從過期的debuginfo對象中讀取debuginfo,并且還可以確保Valgrind不會因?yàn)椴黄ヅ涠罎ⅰ?/p>
此檢查可以使用?--allow-mismatched-debuginfo=yes。當(dāng)debuginfo和主對象沒有以正確的方式拆分時,這可能很有用。盡管如此,使用它時要小心:它禁用所有一致性檢查,并且當(dāng)主要和debuginfo對象不匹配時,Valgrind被觀察到崩潰。
指定一個額外的文件,從中讀取要抑制的錯誤的描述。您可以使用多達(dá)100個額外的壓縮文件。
設(shè)置后yes,Valgrind將在每次顯示錯誤后暫停,并打印行:
????----?Print?suppression???---?[Return/N/n/Y/y/C/c]?----
按Ret或,N Ret或?n Ret導(dǎo)致Valgrind繼續(xù)執(zhí)行而不打印此錯誤的抑制。
按下Y Ret或?y Ret導(dǎo)致Valgrind寫入此錯誤的抑制。如果您不想再聽到有關(guān)該錯誤的信息,可以將其剪切并粘貼到抑制文件中。
設(shè)置時all,Valgrind將會針對每個報告的錯誤打印一個抑制,而不會查詢用戶。
此選項(xiàng)對于C ++程序特別有用,因?yàn)樗鶕?jù)需要打印出具有破壞名稱的抑制。
請注意,打印的壓印盡可能具體。您可能希望通過添加通配符到函數(shù)名稱以及使用幀級別的通配符來尋找類似的通配符。通配設(shè)備功能強(qiáng)大而靈活,并且經(jīng)過仔細(xì)的編輯,您可能只需少量的壓制即可抑制整個系列的相關(guān)錯誤。
有時兩個不同的錯誤被同樣的抑制所壓制,在這種情況下,Valgrind將會多次輸出抑制,但您只需要在壓縮文件中有一個副本(但是不止一個則不會導(dǎo)致問題)。此外,抑制名稱為?<insert a suppression name here>:該名稱并不重要,它只用于-v打印所有使用的抑制記錄的選項(xiàng)。
當(dāng)使用?--gen-suppressions=yes時,Valgrind將停止,以便在發(fā)生每個錯誤時讀取您的鍵盤輸入。默認(rèn)情況下,它從標(biāo)準(zhǔn)輸入(stdin)讀取,這對于關(guān)閉stdin的程序是有問題的。此選項(xiàng)允許您指定從中讀取輸入的備用文件描述符。
此選項(xiàng)僅在Mac OS X上運(yùn)行Valgrind時才有用。
Mac OS X使用延遲調(diào)試信息(debuginfo)鏈接方案。當(dāng)包含debuginfo的對象文件鏈接到一個.dylib或可執(zhí)行文件中時,debuginfo不會被復(fù)制到最終文件中。相反,必須通過在可執(zhí)行文件上運(yùn)行dsymutil系統(tǒng)提供的實(shí)用程序來手動鏈接debuginfo?.dylib。生成的組合debuginfo放在可執(zhí)行文件旁邊的目錄中,或者.dylib擴(kuò)展名.dSYM。
使用--dsymutil=no,Valgrind將檢測?.dSYM目錄丟失或存在的情況,但不符合關(guān)聯(lián)的可執(zhí)行文件,或者.dylib很可能是因?yàn)樗堰^期。在這種情況下,Valgrind會打印一個警告消息,但不采取進(jìn)一步行動。
隨著--dsymutil=yes,Valgrind的意志,在這樣的情況下,自動運(yùn)行dsymutil必要使debuginfo軟最新的。對于所有實(shí)際的目的,如果您始終使用--dsymutil=yes,則絕對不需要dsymutil手動運(yùn)行或作為應(yīng)用程序構(gòu)建系統(tǒng)的一部分運(yùn)行,因?yàn)閂algrind將根據(jù)需要運(yùn)行它。
Valgrind的不會嘗試運(yùn)行dsymutil在任何可執(zhí)行文件或庫?/usr/,?/bin/,?/sbin/,?/opt/,?/sw/,?/System/,?/Library/或?/Applications/?因?yàn)閐symutil總是會在這種情況下失敗。它失敗了,因?yàn)檫@種預(yù)安裝的系統(tǒng)組件的debuginfo在任何地方都不可用,也因?yàn)樗枰@些目錄中的寫入權(quán)限。
使用--dsymutil=yes時要小心,因?yàn)樗鼤?dǎo)致預(yù)先存在的.dSYM?目錄被靜默刪除并重新創(chuàng)建。還要注意的?dsymutil是相當(dāng)慢,有的時候太過分了。
堆棧幀的最大大小。如果堆棧指針移動超過此值,則Valgrind將假定程序正在切換到另一個堆棧。
如果您的程序具有大量堆棧分配的數(shù)組,則可能需要使用此選項(xiàng)。Valgrind跟蹤程序的堆棧指針。如果它改變超過閾值,Valgrind假設(shè)您的程序正在切換到不同的堆棧,Memcheck的行為與堆棧指針變化小于閾值的行為不同。通常這個啟發(fā)式工作原理很好。但是,如果您的程序在堆棧中分配大型結(jié)構(gòu),則該啟發(fā)式將被愚弄,并且Memcheck將會報告大量的無效堆棧訪問。此選項(xiàng)允許您將閾值更改為不同的值。
如果Valgrind的調(diào)試輸出指示您這樣做,您應(yīng)該僅考慮使用此選項(xiàng)。在這種情況下,它會告訴您應(yīng)該指定的新閾值。
通常,在堆棧上分配大型結(jié)構(gòu)是一個壞主意,因?yàn)槟梢暂p松地耗盡堆棧空間,特別是在內(nèi)存有限的系統(tǒng)上,或者希望支持大量線程,每個都有一個小堆棧,并且還因?yàn)殄e誤由Memcheck執(zhí)行的檢查對堆分配數(shù)據(jù)比對堆棧分配的數(shù)據(jù)更有效。如果您必須使用此選項(xiàng),您可能希望考慮將代碼重寫為在堆上分配而不是堆棧。
指定主線程堆棧的大小。
為了簡化內(nèi)存管理,Valgrind在啟動時保留主線程堆棧的所有空間。這意味著它需要在啟動時知道所需的堆棧大小。
默認(rèn)情況下,Valgrind使用當(dāng)前的“ulimit”值作為堆棧大小,或16 MB,以較低者為準(zhǔn)。在許多情況下,這將提供8到16 MB的堆棧大小,對于大多數(shù)應(yīng)用程序幾乎不會溢出。
如果您需要更大的總堆棧大小,請使用--main-stacksize它來指定它。只需將其設(shè)置為您所需的高度,因?yàn)楸A舯饶枰母嗫臻g(即,比您需要的數(shù)百兆字節(jié))約束了Valgrind的內(nèi)存分配器,并可能減少Valgrind可以使用的內(nèi)存總量。這對32位機(jī)器來說真的很重要。
在Linux上,您可以要求一個大小為2GB的堆棧。如果無法分配堆棧,Valgrind將會停止診斷消息。
--main-stacksize只影響程序初始線程的堆棧大小。它對線程棧的大小沒有任何影響,因?yàn)閂algrind不會分配它們。
您可能需要同時使用--main-stacksize?和--max-stackframe在一起。重要的是要理解,--main-stacksize設(shè)置最大堆棧總數(shù),同時--max-stackframe指定任何一個堆棧幀的最大大小。您將必須--main-stacksize為自己找出價值(通常,如果您的應(yīng)用程序發(fā)生故障)。但是--max-stackframe,如果需要,Valgrind會告訴你需要的尺寸。
如在描述中進(jìn)一步討論的--max-stackframe,對于大堆棧的要求是潛在可移植性問題的跡象。最好建議將所有大數(shù)據(jù)放在堆分配的內(nèi)存中。
默認(rèn)情況下,Valgrind最多可處理500個線程。偶爾,這個數(shù)字太小了。使用此選項(xiàng)提供不同的限制。例如?--max-threads=3000。
2.6.4。malloc相關(guān)選項(xiàng)
對于使用自己的版本?malloc(例如Memcheck,Massif,Helgrind,DRD)的工具,適用以下選項(xiàng)。
--alignment=<number> [default: 8 or 16, depending on the platform]默認(rèn)情況下Valgrind的的malloc,?realloc等等,返回塊,其起始地址為8字節(jié)對齊或16字節(jié)對齊(數(shù)值取決于平臺和相匹配的平臺默認(rèn))。此選項(xiàng)允許您指定不同的對齊方式。提供的值必須大于或等于默認(rèn)值小于或等于4096,并且必須是2的冪。
Valgrind的malloc, realloc,等等,在運(yùn)行程序分配的每個堆塊之前和之后添加填充塊。這種填充塊稱為redzones。redzone大小的默認(rèn)值取決于工具。例如,Memcheck在客戶端分配的每個塊之前和之后增加并保護(hù)至少16個字節(jié)。這允許它檢測最多16個字節(jié)的塊欠載或超限。
增加紅色區(qū)域大小可以檢測更大距離的超限,但會增加Valgrind使用的內(nèi)存量。減少紅區(qū)大小將減少Valgrind所需的內(nèi)存,同時也降低了檢測超出/欠載的機(jī)會,因此不推薦使用。
2.6.5。不常見的選項(xiàng)
這些選項(xiàng)適用于所有工具,因?yàn)樗鼈儠绊慥algrind核心的某些模糊工作。大多數(shù)人不需要使用它們。
--smc-check=<none|stack|all|all-non-file> [default: all-non-file for x86/amd64/s390x, stack for other archs]此選項(xiàng)控制Valgrind對自修改代碼的檢測。如果沒有進(jìn)行任何檢查,當(dāng)程序執(zhí)行一些代碼時,用新的代碼覆蓋它,并執(zhí)行新的代碼,Valgrind將繼續(xù)執(zhí)行舊代碼的翻譯。這可能會導(dǎo)致錯誤的行為和/或崩潰。
對于“現(xiàn)代”架構(gòu) - 任何不是x86,amd64或s390x - 的默認(rèn)設(shè)置stack。這是因?yàn)檎_的程序必須采取明確的行動來重新建立代碼修改后的DI緩存一致性。Valgrind遵守并尊重此類行為,結(jié)果是自我修改代碼以零額外成本進(jìn)行透明處理。
對于x86,amd64和s390x,程序不需要通知硬件所需的DI一致性同步。因此,默認(rèn)是all-non-file覆蓋將代碼生成到匿名(非文件備份)mmap'd區(qū)域的正常情況。
四種可用設(shè)置的含義如下。無檢測(none)檢測堆棧上的自修改代碼(由GCC用于實(shí)現(xiàn)嵌套函數(shù))(stack),檢測每個地方的自修改代碼all,并檢測除了文件支持的映射之外的其他修改代碼(all-non-file)。
跑步all會緩慢的下降。運(yùn)行時none很少加快速度,因?yàn)楹苌俚拇a在大多數(shù)程序中動態(tài)生成。該?VALGRIND_DISCARD_TRANSLATIONS客戶端請求是一種替代--smc-check=all?和--smc-check=all-non-file?需要更多的程序員的努力,但允許Valgrind的更快地運(yùn)行您的程序,告訴它準(zhǔn)確翻譯時需要重新制作。
--smc-check=all-non-file提供了更便宜但更有限的版本--smc-check=all。它會將檢查添加到不是源于文件支持的內(nèi)存映射的任何翻譯。生成代碼的典型應(yīng)用程序(例如Web瀏覽器中的JIT)將生成代碼到匿名的mmaped區(qū)域,而瀏覽器的“固定”代碼總是存在于文件支持的映射中。?--smc-check=all-non-file?利用這一觀察,限制檢查可能是JIT生成的代碼的開銷。
啟用后,Valgrind將從DWARF3調(diào)試信息中讀取有關(guān)內(nèi)聯(lián)函數(shù)調(diào)用的信息。這減慢了Valgrind啟動并使其使用更多的內(nèi)存(通常為每個內(nèi)聯(lián)代碼段,6個字和空格用于函數(shù)名稱),但它會導(dǎo)致更多描述性的堆棧跟蹤。對于3.10.0版本,默認(rèn)情況下僅對Linux,Android和Solaris目標(biāo)以及僅用于Memcheck,Helgrind和DRD的工具啟用此功能。以下是一些堆棧跟蹤的示例?--read-inline-info=no:
== 15380 ==有條件的跳轉(zhuǎn)或移動取決于未初始化的值 == 15380 == at 0x80484EA:main(inlinfo.c:6) == == 15380 == 15380 ==有條件跳轉(zhuǎn)或移動取決于未初始化的值 == 15380 == at 0x8048550:fun_noninline(inlinfo.c:6) == 15380 == by 0x804850E:main(inlinfo.c:34) == == 15380 == 15380 ==有條件跳轉(zhuǎn)或移動取決于未初始化的值 == 15380 == at 0x8048520:main(inlinfo.c:6)以下是與以下相同的錯誤?--read-inline-info=yes:
== 15377 ==有條件跳轉(zhuǎn)或移動取決于未初始化的值 == 15377 == at 0x80484EA:fun_d(inlinfo.c:6) == 15377 == by 0x80484EA:fun_c(inlinfo.c:14) == 15377 == by 0x80484EA:fun_b(inlinfo.c:20) == 15377 == by 0x80484EA:fun_a(inlinfo.c:26) == 15377 == by 0x80484EA:main(inlinfo.c:33) == == 15377 == 15377 ==有條件跳轉(zhuǎn)或移動取決于未初始化的值 == 15377 == at 0x8048550:fun_d(inlinfo.c:6) == 15377 == by 0x8048550:fun_noninline(inlinfo.c:41) == 15377 == by 0x804850E:main(inlinfo.c:34) == == 15377 == 15377 ==有條件跳轉(zhuǎn)或移動取決于未初始化的值 == 15377 == at 0x8048520:fun_d(inlinfo.c:6) == 15377 == by 0x8048520:main(inlinfo.c:35)啟用后,Valgrind將從DWARF3調(diào)試信息中讀取有關(guān)變量類型和位置的信息。這顯著減緩了Valgrind的啟動,并使其占用了更多的內(nèi)存,但是對于可以利用它的工具(Memcheck,Helgrind,DRD),它可能會導(dǎo)致更精確的錯誤消息。例如,以下是Memcheck發(fā)出的一些標(biāo)準(zhǔn)錯誤:
== 15363 ==客戶端檢查請求期間發(fā)現(xiàn)的未初始化字節(jié) == 15363 == at 0x80484A9:croak(varinfo1.c:28) == 15363 == 0x8048544:main(varinfo1.c:55) == 15363 ==地址0x80497f7是數(shù)據(jù)符號“global_i2”內(nèi)的7個字節(jié) == == 15363 == 15363 ==客戶端檢查請求期間發(fā)現(xiàn)的未初始化字節(jié) == 15363 == at 0x80484A9:croak(varinfo1.c:28) == 15363 == by 0x8048550:main(varinfo1.c:56) == 15363 ==地址0xbea0d0cc在線程1的堆棧上 == 15363 ==在框架#1中,由主(varinfo1.c:45)創(chuàng)建以下是與以下相同的錯誤?--read-var-info=yes:
== 15370 ==客戶端檢查請求期間發(fā)現(xiàn)的未初始化字節(jié) == 15370 == at 0x80484A9:croak(varinfo1.c:28) == 15370 == by 0x8048544:main(varinfo1.c:55) == 15370 ==位置0x80497f7是global_i2 [7]中的0個字節(jié), == 15370 ==在varinfo1.c中聲明的全局變量:41 == == 15370 == 15370 ==客戶端檢查請求期間發(fā)現(xiàn)的未初始化字節(jié) == 15370 == at 0x80484A9:croak(varinfo1.c:28) == 15370 == 0x8048550:main(varinfo1.c:56) == 15370 ==位置0xbeb4a0cc是本地var“l(fā)ocal”內(nèi)的0個字節(jié) == 15370 ==在線程1的第1幀中的varinfo1.c:46聲明作為其主循環(huán)的一部分,Valgrind調(diào)度程序?qū)⑤喸円詸z查某些活動(例如外部命令或gdb的某些輸入)是否必須由gdbserver處理。在運(yùn)行給定數(shù)量的基本塊(或略大于給定數(shù)量的基本塊)之后,將進(jìn)行此活動輪詢。這個投票相當(dāng)便宜,所以默認(rèn)值設(shè)置得比較低。如果vgdb無法使用ptrace系統(tǒng)調(diào)用中斷Valgrind,如果系統(tǒng)調(diào)用中的所有線程(大部分時間)被阻止,您可能會進(jìn)一步減少此值。
激活時,gdbserver會將Valgrind影子寄存器公開到GDB。這樣,可以使用GDB檢查或更改Valgrind影子寄存器的值。隱藏影子寄存器僅適用于GDB 7.1或更高版本。
要與gdb / vgdb通信,Valgrind gdbserver會創(chuàng)建3個文件(2個命名的FIFO和一個mmap共享內(nèi)存文件)。prefix選項(xiàng)控制創(chuàng)建這些文件的目錄和前綴。
此選項(xiàng)僅在Linux上運(yùn)行Valgrind時才有用。
libc.so所有程序使用的GNU C庫()可能會為自己的用途分配內(nèi)存。通常,當(dāng)程序結(jié)束時,它不會釋放內(nèi)存,因?yàn)長inux內(nèi)核在進(jìn)程退出時會回收所有進(jìn)程資源,所以它只會減慢速度。
glibc作者意識到,當(dāng)出口檢查完成時,這種行為會導(dǎo)致漏洞檢查器(如Valgrind)錯誤地報告glibc中的泄漏。為了避免這種情況,他們提供了一個__libc_freeres?專門用于使glibc釋放其分配的所有內(nèi)存的例程。因此,Memcheck嘗試__libc_freeres在退出時運(yùn)行?。
不幸的是,在一些很舊的glibc版本中,?__libc_freeres足夠錯誤的引起分段錯誤。這在Red Hat 7.1中尤其明顯。所以這個選項(xiàng)是為了禁止運(yùn)行而提供的?__libc_freeres。如果您的程序似乎在Valgrind上運(yùn)行良好,但是在出口處出現(xiàn)segfaults,您可能會發(fā)現(xiàn)?--run-libc-freeres=no修復(fù)盡管可能會錯誤地報告空間漏洞?libc.so。
此選項(xiàng)僅在運(yùn)行Linux或Solaris C ++程序上的Valgrind時才有用。
libstdc++.so由g ++編譯的所有C ++程序使用的GNU標(biāo)準(zhǔn)C ++庫()可能會為自己的用途分配內(nèi)存。通常,當(dāng)程序結(jié)束時,它不會釋放內(nèi)存,因?yàn)閮?nèi)核在進(jìn)程退出時會回收所有進(jìn)程資源,所以它只會減慢速度。
gcc作者意識到,當(dāng)在出口處進(jìn)行泄漏檢查時,此行為會導(dǎo)致漏洞檢查器(如Valgrind)在libstdc ++中錯誤地報告泄漏。為了避免這種情況,他們提供了一個__gnu_cxx::__freeres?專門用于使libstdc ++釋放其已分配的所有內(nèi)存的例程。因此,Memcheck嘗試__gnu_cxx::__freeres在退出時運(yùn)行?。
為了靈活性和不可預(yù)見的問題?__gnu_cxx::__freeres,選擇?--run-cxx-freeres=no存在,盡管可能錯誤地報告空間泄漏?libstdc++.so。
通過Valgrind的其他提示,以非標(biāo)準(zhǔn)或危險的方式稍微修改模擬行為,可能有助于模擬奇怪的功能。默認(rèn)情況下不啟用任何提示。謹(jǐn)慎使用!目前已知的提示有:
-
lax-ioctls:?對于ioctl處理非常松懈;?唯一的假設(shè)是大小是正確的。寫入時不需要初始化完整的緩沖區(qū)。沒有這個,使用一些設(shè)備驅(qū)動程序與大量的奇怪的ioctl命令變得非常麻煩。
-
fuse-compatible:?對可能在FUSE文件系統(tǒng)中阻塞的某些系統(tǒng)調(diào)用啟用特殊處理。在使用一個線程來管理FUSE文件系統(tǒng)的多線程程序上運(yùn)行Valgrind并且另一個線程訪問該文件系統(tǒng)時,這可能是必需的。
-
enable-outer:?當(dāng)運(yùn)行程序本身是Valgrind時,啟用了一些特殊的魔法。
-
no-inner-prefix:?禁止>在外部Valgrind運(yùn)行的內(nèi)部Valgrind中,在每個stdout或stderr輸出行前面打印前綴。當(dāng)在外部/內(nèi)部設(shè)置中運(yùn)行Valgrind回歸測試時,這是非常有用的。請注意,前綴>將始終打印在內(nèi)部調(diào)試日志記錄行的前面。
-
no-nptl-pthread-stackcache:?這個提示僅在Linux上運(yùn)行Valgrind時才有用。
libpthread.sopthread程序使用的GNU glibc pthread庫()維護(hù)一個pthread棧緩存。當(dāng)pthread終止時,用于pthread棧的內(nèi)存和一些線程本地存儲相關(guān)數(shù)據(jù)結(jié)構(gòu)并不總是直接釋放。這個內(nèi)存被保存在高速緩存中(達(dá)到一定的大小),如果啟動了一個新的線程,那么這個內(nèi)存被重新使用。
這個緩存導(dǎo)致helgrind工具在這個緩存的內(nèi)存上報告一些錯誤的正面競爭條件錯誤,因?yàn)閔elgrind不了解內(nèi)部glibc緩存同步原語。所以,當(dāng)使用helgrind時,禁用緩存有助于避免錯誤的正面競爭條件,特別是當(dāng)使用線程本地存儲變量(例如使用?__thread限定符的變量)時。
當(dāng)使用memcheck工具時,禁用高速緩存可確保glibc處理__thread變量所使用的內(nèi)存在線程終止時直接釋放。
注意:Valgrind使用glibc堆棧緩存實(shí)現(xiàn)的一些內(nèi)部知識以及檢查pthread庫的調(diào)試信息來禁用緩存。因此,這種技術(shù)有些脆弱,并且可能對所有g(shù)libc版本都無效。這已經(jīng)在各種平臺上通過各種glibc版本(例如2.11,2.16,2.18)成功測試。
-
lax-doors:?(僅限Solaris)對于無法識別的門文件描述符,關(guān)于門系統(tǒng)調(diào)用處理非常松懈。不需要在寫入時初始化完整的緩沖區(qū)。沒有這一點(diǎn),使用具有完全專有語義的libdoor(3LIB)功能的程序可能會報告大量的誤報。
該--fair-sched選項(xiàng)控制Valgrind使用的鎖定機(jī)制來串行線程執(zhí)行。鎖定機(jī)制控制線程的安排方式,不同的設(shè)置在公平性和性能之間進(jìn)行不同的權(quán)衡。有關(guān)Valgrind線程序列化方案及其對性能和線程調(diào)度的影響的更多詳細(xì)信息,請參閱?計劃和多線程性能。
-
該值--fair-sched=yes?激活公平的調(diào)度程序。簡而言之,如果多個線程準(zhǔn)備運(yùn)行,線程將以輪循方式進(jìn)行安排。該機(jī)制在所有平臺或Linux版本上都不可用。如果不可用,則使用--fair-sched=yes會導(dǎo)致Valgrind終止并出現(xiàn)錯誤。
如果您在Valgrind上運(yùn)行交互式多線程程序(例如Web瀏覽器),則可能會發(fā)現(xiàn)此設(shè)置會提高整體響應(yīng)能力。
-
該值--fair-sched=try?激活公平調(diào)度(如果在平臺上可用)。否則會自動回退--fair-sched=no。
-
該值--fair-sched=no激活一個不能保證線程準(zhǔn)備運(yùn)行的線程之間的公平性,但通常給出最高性能的調(diào)度器。
處理來自該平臺的默認(rèn)內(nèi)核的較小變體的系統(tǒng)調(diào)用和ioctl。這對于在黑客內(nèi)核上運(yùn)行或者支持非標(biāo)準(zhǔn)ioctl的內(nèi)核模塊非常有用。謹(jǐn)慎使用。如果你不明白這個選項(xiàng)是什么,那么你幾乎肯定不需要它。目前已知的變體是:
-
bproc:支持sys_brocx86上的?系統(tǒng)調(diào)用。這是用于在BProc上運(yùn)行的,它是標(biāo)準(zhǔn)Linux的一小部分變體,有時用于構(gòu)建集群。
-
android-no-hw-tls:ARM版Android模擬器的一些版本不提供硬件TLS(線程本地狀態(tài))寄存器,Valgrind在啟動時崩潰。使用此變體選擇TLS的軟件支持。
-
android-gpu-sgx5xx:使用它來支持在Android設(shè)備上處理PowerVR SGX 5XX系列GPU的專有ioctl。未選擇此項(xiàng)不會導(dǎo)致穩(wěn)定性問題,但可能會導(dǎo)致Memcheck在程序執(zhí)行GPU特定的ioctl之后報告錯誤的錯誤。
-
android-gpu-adreno3xx:同樣地,使用它來支持在Android設(shè)備上處理高通Adreno 3XX系列GPU的專有ioctl。
一些遞歸算法,例如平衡二叉樹實(shí)現(xiàn),創(chuàng)建許多不同的堆棧跟蹤,每個包含循環(huán)的調(diào)用。一個周期被定義為由零個或多個其他程序計數(shù)器值分隔的兩個相同的程序計數(shù)器值。然后,Valgrind可能會使用大量內(nèi)存來存儲所有這些堆棧跟蹤。考慮到這種堆棧跟蹤包含重復(fù)的不感興趣的遞歸調(diào)用而不是更有趣的信息,例如已經(jīng)發(fā)起遞歸調(diào)用的函數(shù),這是一個很差的內(nèi)存使用。
該選項(xiàng)--merge-recursive-frames=<number>?指示Valgrind檢測并合并大小最多為<number>?幀的遞歸調(diào)用循環(huán)。當(dāng)檢測到這樣的循環(huán)時,Valgrind將堆棧跟蹤中的循環(huán)記錄為唯一的程序計數(shù)器。
值0(默認(rèn)值)不會導(dǎo)致遞歸調(diào)用合并。值為1將導(dǎo)致簡單遞歸算法(例如,階乘實(shí)現(xiàn))的堆棧跟蹤被折疊。通常需要2的值來折疊由遞歸算法(如二叉樹,快速排序等)等產(chǎn)生的堆棧跟蹤。更復(fù)雜的遞歸算法可能需要更高的值。
注意:通過分析程序計數(shù)器值來檢測遞歸調(diào)用。通過查看函數(shù)名稱來檢測它們。
Valgrind以小碎片(基本塊)翻譯和調(diào)整程序的機(jī)器代碼。翻譯存儲在翻譯高速緩存中,該高速緩存分為多個部分(扇區(qū))。如果緩存已滿,則包含最舊的翻譯的扇區(qū)將被清空并重新使用。如果需要這些舊的翻譯,Valgrind必須重新翻譯和重新設(shè)備相應(yīng)的機(jī)器代碼,這是昂貴的。如果程序的“執(zhí)行指令”工作集很大,則通過減少所需的翻譯次數(shù),增加扇區(qū)數(shù)量可以提高性能。部門按需分配。一旦分配,一個部門永遠(yuǎn)不會被釋放,并占據(jù)相當(dāng)大的空間,--avg-transtab-entry-size?取決于工具和值(Memcheck每個扇區(qū)大約40 MB)。使用選項(xiàng)--stats=yes來獲取有關(guān)部門使用的內(nèi)存以及部門分配和回收的準(zhǔn)確信息。
翻譯基本塊的平均大小。該平均尺寸用于確定扇區(qū)的大小。每個工具提供要使用的默認(rèn)值。如果此默認(rèn)值太小,則翻譯扇區(qū)將變得過快。如果此默認(rèn)值太大,則翻譯部分內(nèi)存的很大一部分將不被使用。請注意,基本塊平移的平均大小取決于工具,并且可能取決于工具選項(xiàng)。例如,memcheck選項(xiàng)--track-origins=yes?增加了基本塊轉(zhuǎn)換的大小。使用--avg-transtab-entry-size調(diào)整扇區(qū)的大小,既可以獲取內(nèi)存或避免過多的重譯。
為了避免與某些系統(tǒng)庫的潛在沖突,Valgrind不會使用下面的地址空間--aspace-minaddr值,保留它,以防庫中特別要求該區(qū)域內(nèi)存。所以根據(jù)平臺,Valgrind猜測到一些“悲觀”的價值。在Linux上,默認(rèn)情況下,Valgrind避免使用第一個64MB,即使這個完整區(qū)域通常沒有沖突。您可以使用該選項(xiàng)--aspace-minaddr使您的內(nèi)存饑餓應(yīng)用程序從更多的這種較低的內(nèi)存中受益。另一方面,如果遇到?jīng)_突,增加aspace-minaddr值可能會解決它。沖突通常會在地址空間較低的范圍內(nèi)出現(xiàn)mmap故障。address提供的頁面必須對齊,并且必須等于或大于0x1000(4KB)。要在平臺上找到默認(rèn)值,請執(zhí)行以下操作?valgrind -d -d date 2>&1 | grep -i minaddr。已知低于0x10000(64KB)的值會在某些分布上產(chǎn)生問題。
對于每個線程,Valgrind需要自己的“私有”堆棧。這些堆棧的默認(rèn)大小在很大程度上是大小尺寸的,因此在大多數(shù)情況下應(yīng)該是足夠的。如果尺寸太小,Valgrind將會發(fā)生故障。在分裂之前,Valgrind可能在接近極限時發(fā)出警告。
--valgrind-stacksize如果產(chǎn)生這樣的(不太可能)警告,或者由于分段違規(guī)導(dǎo)致Valgrind死亡,?請使用該選項(xiàng)。在分離大量C ++符號時已經(jīng)看到這種分段違例。
如果您的應(yīng)用程序使用許多線程并需要大量內(nèi)存,您可以通過使用該選項(xiàng)減小這些Valgrind堆棧的大小來獲得一些內(nèi)存--valgrind-stacksize。
啟用后,Valgrind在某些??情況下會發(fā)出關(guān)于CPU仿真的警告。這些通常不是有趣的。
當(dāng)soname匹配的共享對象sonamepatt加載到進(jìn)程中時,檢查其導(dǎo)出的所有文本符號。如果沒有匹配fnnamepatt,打印錯誤信息并放棄運(yùn)行。這使得有可能確保運(yùn)行不會繼續(xù),除非給定的共享對象包含特定的函數(shù)名稱。
雙方sonamepatt并?fnnamepatt可以用通常的寫入??和*通配符。例如:":*libc.so*:foo?bar"。您可以使用冒號以外的字符分隔兩個模式。第一個字符和分隔符相同只是重要的。例如,上面的例子也可以寫成"Q*libc.so*Qfoo?bar"。?--require-text-symbol允許多個標(biāo)志,在這種情況下,將檢查加載到進(jìn)程中的共享對象。
其目的是支持可靠使用已標(biāo)記的庫。例如,假設(shè)我們有一個GCC的版本,?libgomp.so其中已經(jīng)標(biāo)注了注釋以支持Helgrind。將錯誤的,未注釋的加載到應(yīng)用程序中是太容易和混亂了?libgomp.so。所以這個想法是:例如在標(biāo)記的庫中添加一個文本符號annotated_for_helgrind_3_6,然后給出標(biāo)志?--require-text-symbol=:*libgomp*so*:annotated_for_helgrind_3_6?,以便libgomp.so加載時,Valgrind掃描其符號表,如果符號不存在,則運(yùn)行中止,而不是與未標(biāo)記的圖書館保持沉默。請注意,您應(yīng)該將整個標(biāo)記放在引號中,以阻止擴(kuò)展*?和?通配符的擴(kuò)展。
加載共享庫時,Valgrind會檢查庫中必須更換或包裝的函數(shù)。例如,Memcheck用自己的版本替換一些字符串和內(nèi)存函數(shù)(strchr,strlen,strcpy,memchr,memcpy,memmove等)。這樣的替換通常僅在共享庫中進(jìn)行,其共享庫的soname匹配預(yù)定義的soname模式(例如?libc.so*在linux上)。默認(rèn)情況下,除了分配函數(shù)(malloc,free,calloc,memalign,realloc,operator new,operator delete等)之外,靜態(tài)鏈接二進(jìn)制或替代庫不進(jìn)行替換。默認(rèn)情況下,這種分配函數(shù)被截取任何共享庫或可執(zhí)行文件,如果它們被導(dǎo)出為全局符號。?這意味著如果找到替換分配庫(如tcmalloc),則默認(rèn)情況下也會攔截其函數(shù)。--soname-synonyms在某些情況下,替換可以指定一個額外的同義詞模式,從而給予更換的靈活性。或防止截取所有公共分配符號。
目前,這種靈活性只允許使用同義詞的malloc相關(guān)功能somalloc。這個同義詞可用于執(zhí)行malloc相關(guān)功能的標(biāo)準(zhǔn)替換的所有工具(例如memcheck,massif,drd,helgrind,exp-dhat,exp-sgcheck)。
-
替代的malloc庫:使用soname?mymalloclib.so(而不是任何其他)替換特定備用庫中的malloc相關(guān)函數(shù),給出選項(xiàng)--soname-synonyms=somalloc=mymalloclib.so。可以使用一個模式來匹配多個庫的聲名。例如,--soname-synonyms=somalloc=*tcmalloc*?將匹配tcmalloc庫(native,debug,profiled,... tcmalloc變體)的所有變體的soname。
注意:可以使用readelf實(shí)用程序檢索elf共享庫的soname。
-
靜態(tài)鏈接庫中的替換是通過使用NONE模式來完成的。例如,如果您鏈??接libtcmalloc.a,并且只想攔截可執(zhí)行文件(和標(biāo)準(zhǔn)庫)本身的malloc相關(guān)函數(shù),而不是任何其他共享庫,則可以給出該選項(xiàng)--soname-synonyms=somalloc=NONE。請注意,NONE模式將匹配主可執(zhí)行文件和任何沒有soname的共享庫。
-
要運(yùn)行用于Linux的“默認(rèn)”Firefox版本,其中JEMalloc鏈接到主可執(zhí)行文件,請使用--soname-synonyms=somalloc=NONE。
-
為了僅攔截默認(rèn)系統(tǒng)庫中的分配符號,但不能在任何其他共享庫或定義public malloc或operator new相關(guān)函數(shù)的可執(zhí)行文件中使用不存在的庫名稱--soname-synonyms=somalloc=nouserintercepts?(如果nouserintercepts可以是任何不存在的庫名稱)。
-
搜索動態(tài)(運(yùn)行時)鏈接器的共享庫被排除在搜索全局公共符號之外,如malloc相關(guān)函數(shù)(由somalloc同義詞標(biāo)識)。
2.6.6。調(diào)試選項(xiàng)
還有一些用于調(diào)試Valgrind本身的選項(xiàng)。你不應(yīng)該在正常的事情中使用它們。如果您希望看到列表,請使用該?--help-debug選項(xiàng)。
如果你想調(diào)試你的程序,而不是調(diào)試Valgrind本身,那么你應(yīng)該使用選項(xiàng)?--vgdb=yes或--vgdb=full。
2.6.7。設(shè)置默認(rèn)選項(xiàng)
請注意,Valgrind還從三個地方讀取選項(xiàng):
文件?~/.valgrindrc
環(huán)境變量?$VALGRIND_OPTS
文件?./.valgrindrc
這些在命令行選項(xiàng)之前以給定的順序進(jìn)行處理。稍后處理的選項(xiàng)將覆蓋之前處理的選項(xiàng);?例如,選項(xiàng)?./.valgrindrc將優(yōu)先于那些?~/.valgrindrc。
請注意,如果./.valgrindrc?文件被標(biāo)記為當(dāng)前用戶可以寫入或不擁有,則該文件將被忽略。這是因?yàn)?./.valgrindrc可能包含潛在有害的選項(xiàng),或者本地攻擊者可以使用該選項(xiàng)來執(zhí)行用戶帳戶下的代碼。
任何放入工具的選項(xiàng)?$VALGRIND_OPTS或?.valgrindrc文件都應(yīng)該加上工具名稱和冒號。例如,如果要讓Memcheck始終進(jìn)行泄漏檢查,可以將以下條目放入~/.valgrindrc:
--memcheck:泄漏檢查= YES如果運(yùn)行Memcheck以外的任何工具,這將被忽略。沒有這個memcheck:?部分,如果選擇其他不了解的工具,這將導(dǎo)致問題?--leak-check=yes。
2.7。支持線程
線程程序得到完全支持。
關(guān)于線程程序的主要內(nèi)容是,您的程序?qū)⑹褂帽緳C(jī)線程庫,但是Valgrind可以串行化執(zhí)行,以便一次只運(yùn)行一個(內(nèi)核)線程。這種方法避免了實(shí)施Valgrind的真正多線程版本的可怕實(shí)現(xiàn)問題,但這意味著即使有多處理器或多核機(jī)器,線程應(yīng)用程序也不會同時使用多個CPU。
Valgrind沒有安排線程本身。它只是確保只有一個線程一次運(yùn)行,使用簡單的鎖定方案。實(shí)際的線程調(diào)度仍然受OS內(nèi)核的控制。這是什么意思,但是,您的程序?qū)⒖吹椒浅2煌恼{(diào)度,當(dāng)運(yùn)行在Valgrind比正常運(yùn)行時。這是因?yàn)閂algrind串行化線程,并且因?yàn)榇a運(yùn)行速度比正常慢。
如果您有某種并發(fā),嚴(yán)重的競爭,鎖定或類似的錯誤,那么調(diào)度的差異可能會導(dǎo)致程序的行為不同。在這種情況下,您可以考慮使用Helgrind和/或DRD工具來跟蹤它們。
在Linux上,Valgrind還支持直接使用?clone系統(tǒng)調(diào)用,?futex等等。?clone支持任何一個共享(一個線程)或者沒有共享(fork-like);?部分分享將失敗。
2.7.1。調(diào)度和多線程性能
只有當(dāng)線程保持上述鎖時,線程才執(zhí)行代碼。執(zhí)行一些指令后,正在運(yùn)行的線程將釋放鎖。準(zhǔn)備運(yùn)行的所有線程將會競爭獲取鎖。
該--fair-sched選項(xiàng)控制用于序列化線程執(zhí)行的鎖定機(jī)制。
默認(rèn)的基于管道的鎖定機(jī)制(--fair-sched=no)可在所有平臺上使用。基于管道的鎖定不能保證線程之間的公平性:剛剛釋放鎖的線程很可能立即重新獲取,即使其他線程已準(zhǔn)備好運(yùn)行。當(dāng)使用基于管道的鎖定時,相同多線程應(yīng)用程序的不同運(yùn)行可能給出非常不同的線程調(diào)度。
在一些平臺上可以使用基于futexes的替代鎖定機(jī)制。如果有的話,它被激活--fair-sched=yes或?--fair-sched=try。基于Futex的鎖定確保線程之間的公平性(循環(huán)調(diào)度):如果多個線程準(zhǔn)備運(yùn)行,則鎖將被提供給首先請求鎖定的線程。請注意,系統(tǒng)調(diào)用中阻塞的線程(例如,阻塞讀取系統(tǒng)調(diào)用)尚未請求鎖定:只有系統(tǒng)調(diào)用完成后,該線程才會請求該鎖。
基于futex的鎖定的公平性為多線程應(yīng)用程序的不同執(zhí)行提供了線程調(diào)度的更好的重現(xiàn)性。使用Helgrind或DRD時,這種更好的再現(xiàn)性特別有用。
Valgrind使用線程序列化意味著一次只能運(yùn)行一個線程。在多處理器/多核系統(tǒng)上,運(yùn)行的線程由OS內(nèi)核調(diào)度程序分配給其中一個CPU。當(dāng)一個線程獲取鎖定時,有時線程將被分配給剛剛釋放鎖的線程的同一個CPU。有時,線程將被分配給另一個CPU。當(dāng)使用基于管道的鎖定時,剛剛獲取鎖的線程通常將被調(diào)度在與剛釋放鎖的線程相同的CPU上。使用基于futex的機(jī)制,剛獲取鎖的線程將更頻繁地在另一個CPU上調(diào)度。
由OS內(nèi)核調(diào)度程序進(jìn)行的Valgrind的線程序列化和CPU分配可以與許多現(xiàn)代CPU上可用的CPU頻率擴(kuò)展進(jìn)行嚴(yán)重的交互。為了降低功耗,如果最近沒有使用CPU /內(nèi)核,則CPU或內(nèi)核的頻率會自動降低。如果操作系統(tǒng)內(nèi)核經(jīng)常將剛剛獲得鎖定的線程分配給另一個CPU /內(nèi)核,那么這個CPU /核心很可能當(dāng)前處于低頻率。這個CPU的頻率會在一段時間后增加。但是,在這段時間內(nèi),(只)運(yùn)行的線程將以低頻運(yùn)行。一旦這個線程運(yùn)行了一段時間,它將釋放鎖。另一個線程將獲取此鎖,并可能會在另一個CPU的時鐘頻率降低的同時進(jìn)行調(diào)度。
基于futex的鎖定會導(dǎo)致線程更頻繁地更改CPU /內(nèi)核。因此,如果CPU頻率縮放被激活,則基于futex的鎖定可能會顯著降低在Valgrind下運(yùn)行的多線程應(yīng)用程序的性能。與在CPU頻率縮放已停用的機(jī)器上運(yùn)行相比,已經(jīng)觀察到高達(dá)50%的性能損失。基于管道的鎖定鎖定方案也與CPU頻率縮放相關(guān),性能損失在10..20%的范圍內(nèi)。
為了避免這種性能下降,您應(yīng)該向內(nèi)核指出所有CPU /內(nèi)核應(yīng)始終以最大時鐘速度運(yùn)行。根據(jù)您的Linux發(fā)行版,可以使用圖形界面或使用諸如cpufreq-selector或?之類的命令行來控制CPU頻率縮放?cpufreq-set。
避免這些問題的另一種方法是告訴操作系統(tǒng)調(diào)度程序使用taskset命令將Valgrind進(jìn)程與特定(固定)CPU綁定?。只要程序的任何線程都有工作,這樣就可以確保所選擇的CPU不會低于其最大頻率設(shè)置。
2.8。處理信號
Valgrind有一個相當(dāng)完整的信號實(shí)現(xiàn)。它應(yīng)該能夠應(yīng)付符合POSIX標(biāo)準(zhǔn)的信號使用。
如果您以聰明的方式使用信號(例如,捕獲SIGSEGV,修改頁面狀態(tài)并重新啟動指令),則可能依賴于精確的異常。在這種情況下,您將需要使用--vex-iropt-register-updates=allregs-at-mem-access?或--vex-iropt-register-updates=allregs-at-each-insn。
如果您的程序由于致命的核心轉(zhuǎn)儲信號而死亡,Valgrind將生成自己的vgcore.NNNNN包含程序狀態(tài)的核心文件()。您可以將此核心文件用于GDB或類似的驗(yàn)證后調(diào)試。(注意:如果您的核心轉(zhuǎn)儲大小限制為0,則不會生成內(nèi)核)。在編寫核心轉(zhuǎn)儲時,不包括所有浮點(diǎn)寄存器信息。
在不太可能的情況下,Valgrind本身崩潰,操作系統(tǒng)將以通常的方式創(chuàng)建一個核心轉(zhuǎn)儲。
2.9。建筑和安裝Valgrind
我們使用標(biāo)準(zhǔn)的Unix?./configure,?make,make install機(jī)制。一旦完成,?make install您可能需要運(yùn)行回歸測試make regtest。
除了通常情況?--prefix=/path/to/install/tree,還有三個選項(xiàng)影響了Valgrind的構(gòu)建方式:
-
--enable-inner
這使得Valgrind成為一些特殊的魔法黑客,可以在標(biāo)準(zhǔn)版本的Valgrind(開發(fā)者稱之為“自主托管”)上運(yùn)行它。通常您不應(yīng)使用此選項(xiàng),因?yàn)楦鞣N安全檢查被禁用。
-
--enable-only64bit
--enable-only32bit
在64位平臺(amd64-linux,ppc64-linux,amd64-darwin)上,默認(rèn)情況下,Valgrind內(nèi)置了32位和64位可執(zhí)行文件的運(yùn)行方式。有時這個聰明才是一個問題,原因有很多。在這種情況下,這兩個選項(xiàng)允許單目標(biāo)構(gòu)建。如果同時發(fā)出這兩個,配置腳本將會抱怨。請注意,它們僅在32位平臺(x86-linux,ppc32-linux,arm-linux,x86-darwin)上被忽略。
該configure腳本測試目前由當(dāng)前指示的X服務(wù)器的版本?$DISPLAY。這是一個已知的錯誤。目的是檢測當(dāng)前X客戶端庫的版本,以便可以為它們選擇正確的抑制,而是測試檢查服務(wù)器版本。這只是錯誤的。
如果您正在構(gòu)建一個二進(jìn)制包Valgrind進(jìn)行發(fā)行,請閱讀README_PACKAGERS?Readme Packagers。它包含一些重要信息。
除此之外,這里沒有什么興奮。如果您有建立問題,請告訴我們。
2.10。如果你有問題
請聯(lián)系我們http://www.valgrind.org/。
請參閱限制為Valgrind的的已知的限制,而對于已知不進(jìn)行這項(xiàng)工作的程序列表。
系統(tǒng)的所有部分大量使用斷言和內(nèi)部自檢。它們被永久啟用,我們沒有計劃禁用它們。如果其中一個休息,請郵寄給我們!
如果您發(fā)現(xiàn)斷言失敗m_mallocfree.c,這可能是因?yàn)槟某绦蜃N堆塊的末尾,或在其開始之前,從而破壞了堆元數(shù)據(jù)。Valgrind希望在這樣做之前就會發(fā)出這樣的消息。
閱讀Valgrind常見問題解答,了解有關(guān)常見問題,崩潰等的更多建議。
2.11。限制
以下列出的限制似乎很長。然而,大多數(shù)程序?qū)嶋H上正常工作。
Valgrind將在受支持的平臺上運(yùn)行程序,但受到以下限制:
-
在Linux上,Valgrind在啟動時使用RLIMIT_DATA rlim_cur確定“brk段”的大小,最小為1 MB,最大為8 MB。每次程序嘗試將brk段擴(kuò)展到啟動時確定的大小時,Valgrind將輸出一條消息。大多數(shù)程序可以正常運(yùn)行這個限制,通常是通過切換到使用mmap來獲得更多的內(nèi)存。如果您的程序真的需要一個大的brk段,則必須更改8 MB的硬編碼限制并重新編譯Valgrind。
-
在x86和amd64上,不支持3DNow!說明。如果翻譯者遇到這種情況,Valgrind將在執(zhí)行指令時產(chǎn)生一個SIGILL。除此之外,在x86和amd64上,基本上所有的指令都支持,包括64位模式下的AVX和AES,以及32位模式下的SSSE3。實(shí)際上,32位模式支持在32位目標(biāo)上在MacOSX 10.6上運(yùn)行程序所需的最小SSE4指令。
-
在ppc32和ppc64上,幾乎支持所有的整數(shù),浮點(diǎn)和Altivec指令。具體來說:PowerPC強(qiáng)制的整數(shù)和FP insns,“通用可選”組(fsqrt,fsqrts,stfiwx),“圖形可選”組(fre,fres,frsqrte,frsqrtes)和Altivec(也稱為作為VMX)SIMD指令集,支持。此外,支持Power ISA 2.05規(guī)范中的說明,如POWER6 CPU中所示。
-
在ARM上,ARM和Thumb模式基本上支持整個ARMv7-A指令集。ThumbEE和Jazelle不受支持。NEON,VFPv3和ARMv6媒體支持相當(dāng)完整。
-
如果您的程序執(zhí)行自己的內(nèi)存管理,而不是使用malloc / new / free / delete,它仍然可以工作,但是Memcheck的錯誤檢查將不會那么有效。如果您使用“客戶端請求”描述程序的內(nèi)存管理方案(請參閱?客戶端請求機(jī)制),Memcheck可以做得更好。然而,使用malloc / new和free / delete仍然是最好的方法。
-
Valgrind的信號模擬并不像現(xiàn)在那樣強(qiáng)大。提供基本的POSIX兼容的sigaction和sigprocmask功能,但可以想象,如果您使用信號做奇怪的事情,事情可能會非常糟糕。解決方法:不要。在任何情況下,執(zhí)行非POSIX信號技巧的程序在本質(zhì)上是不可移植的,所以如果可能的話應(yīng)該避免。
-
機(jī)器指令和系統(tǒng)調(diào)用已經(jīng)按需實(shí)現(xiàn)。所以盡管不太可能,但有可能這樣一個消息可能會導(dǎo)致程序崩潰。如果發(fā)生這種情況,請報告打印出的所有詳細(xì)信息,以便我們嘗試并實(shí)施缺少的功能。
-
在Valgrind的Memcheck工具下運(yùn)行時,程序的內(nèi)存消耗量會大大增加。這是由于幕后維護(hù)的管理信息大量。另一個原因是Valgrind動態(tài)翻譯原始的可執(zhí)行文件。翻譯的測試代碼是原始代碼的12-18倍,因此您可以在運(yùn)行(例如)網(wǎng)絡(luò)瀏覽器時輕松獲得150+ MB的翻譯。
-
Valgrind可以處理動態(tài)生成的代碼。如果您在舊代碼(即相同的內(nèi)存地址)上重新生成代碼,則如果代碼位于堆棧上,Valgrind將會實(shí)現(xiàn)代碼已更改,并正常工作。這是必要的,以處理GCC用于實(shí)現(xiàn)嵌套函數(shù)的蹦床。如果您重新生成堆棧以外的其他地方的代碼,并且運(yùn)行在32位或64位x86 CPU上,則需要使用該--smc-check=all選項(xiàng),而Valgrind的運(yùn)行速度要比正常運(yùn)行的要慢。或者您可以添加客戶端請求,告訴Valgrind,當(dāng)您的程序覆蓋代碼。
在其他平臺(ARM,PowerPC)上,Valgrind觀察并尊重程序不得不發(fā)出的緩存無效提示,以通知新代碼,因此自修改代碼支持應(yīng)該可以自動工作,而不需要--smc-check=all。
-
Valgrind在執(zhí)行相對于IEEE754的x86 / AMD64浮點(diǎn)數(shù)方面有以下限制。
精度:不支持80位算術(shù)。在內(nèi)部,Valgrind代表64位中的所有這樣的“長雙數(shù)”數(shù)字,因此結(jié)果可能會有一些差異。這是否至關(guān)重要還有待觀察。請注意,x86 / amd64 fldt / fstpt指令(讀/寫80位數(shù)字)被正確地模擬,使用/從64位轉(zhuǎn)換,所以如果有人想看到,80位數(shù)字的內(nèi)存映像看起來是正確的。
許多FP回歸測試觀察到的印象是精度差異不顯著。一般來說,如果一個程序依賴于80位精度,那么移植到只能支持64位FP精度的非x86 / amd64平臺上可能會有困難。即使在x86 / amd64上,程序可能得到不同的結(jié)果,這取決于是否編譯為使用SSE2指令(僅64位)或x87指令(80位)。最終的效果是使FP程序的行為就像在具有64位IEEE浮點(diǎn)數(shù)的機(jī)器上運(yùn)行一樣,例如PowerPC。在amd64上,FP算法默認(rèn)在SSE2上完成,所以從FP的角度看,amd64看起來更像是PowerPC而不是x86,與x86相比,顯著的精度差異要小得多。
四舍五入:Valgrind確實(shí)遵循以下轉(zhuǎn)換的4個IEEE強(qiáng)制舍入模式(最接近+無窮大至-infinity,為零):float到整數(shù),整數(shù)浮動,有可能丟失精度;浮點(diǎn)到浮動四舍五入。對于所有其他FP操作,僅支持IEEE默認(rèn)模式(round to nearest)。
FP代碼中的數(shù)字異常:IEEE754定義了可能發(fā)生的五種類型的數(shù)字異常:無效操作(負(fù)數(shù)的sqrt等),除以零,溢出,下溢,不精確(精度損失)。
對于每個例外,IEEE754定義了兩個行動方案:(1)可以調(diào)用用戶定義的異常處理程序,或者(2)定義了一個默認(rèn)動作,“修復(fù)”并允許計算在沒有拋出異常
目前,Valgrind僅支持默認(rèn)的fixup操作。同樣,對異常支持的重要性的反饋將不勝感激。
當(dāng)Valgrind檢測到程序試圖超出任何這些限制(設(shè)置異常處理程序,舍入模式或精度控制)時,它可以打印一個消息,提供發(fā)生這種情況的回溯,并繼續(xù)執(zhí)行。此行為曾經(jīng)是默認(rèn)的,但是消息很煩人,因此默認(rèn)情況下顯示它們已被禁用。用--show-emwarns=yes來看他們。
上述限制精確地定義了IEEE754“默認(rèn)”行為:對所有異常進(jìn)行默認(rèn)修復(fù),從最近到最近的操作和64位精度。
-
相對于IEEE754,Valgrind在執(zhí)行x86 / AMD64 SSE2 FP運(yùn)算時有以下限制。
本質(zhì)上是一樣的:沒有例外,有限的遵守舍入模式。此外,SSE2具有控制位,使得它將非正規(guī)化數(shù)字視為零(DAZ)和相關(guān)動作,將數(shù)值清零(FTZ)。這兩個都導(dǎo)致SSE2算法的精度要低于IEEE要求。Valgrind檢測,忽略并可以警告,嘗試啟用任一模式。
-
相對于IEEE754,Valgrind在執(zhí)行ARM VFPv3運(yùn)算時有以下限制。
本質(zhì)上是一樣的:沒有例外,有限的遵守舍入模式。此外,將VFP單元切換到矢量模式將導(dǎo)致Valgrind中止程序 - 它無法在合理的性能級別模擬VFP的矢量使用。由于VFP指令的非標(biāo)量使用在任何情況下都不推薦使用,這并不重要。
-
相對于IEEE754,Valgrind在執(zhí)行PPC32和PPC64浮點(diǎn)運(yùn)算時有以下限制。
標(biāo)量(非Altivec):Valgrind提供了除了“fre”和“fres”之外的所有浮點(diǎn)指令的比特精確仿真,它們比PowerPC架構(gòu)規(guī)范要求更精確。所有浮點(diǎn)運(yùn)算都觀察當(dāng)前的舍入方式。
但是,每次操作后都不會設(shè)置fpscr [FPRF]。這可以做到,但會產(chǎn)生可衡量的性能開銷,到目前為止還沒有找到它。
在x86 / AMD64上,不支持IEEE754異常:使用默認(rèn)的IEEE定義操作來處理所有浮點(diǎn)異常。Valgrind可以通過寫入浮點(diǎn)狀態(tài)和控制寄存器(fpscr)來檢測,忽略并且可以警告,嘗試取消屏蔽5種IEEE FP異常種類。
矢量(Altivec,VMX):基本上與x86 / AMD64 SSE / SSE2一樣:沒有例外,并且有限地遵循舍入模式。對于Altivec,FP算法在IEEE / Java模式下完成,這比Linux默認(rèn)設(shè)置更準(zhǔn)確。“更準(zhǔn)確”是指正確處理代數(shù),而不是簡單地將其清零。
已知無法使用的程序有:
-
emacs啟動,但馬上得出結(jié)論,它是不記憶和中止。這可能是Memcheck不能提供足夠好的mallinfo功能仿真?。如果您使用標(biāo)準(zhǔn)的malloc / free例程來構(gòu)建Emacs,它們會很正常。
2.12。示例運(yùn)行
這是使用Memcheck運(yùn)行一個小程序的日志。該程序?qū)嶋H上是正確的,報告的錯誤是GNU g ++(快照20010527)中潛在嚴(yán)重的代碼生成錯誤的結(jié)果。
sewardj @ phoenix:?/ newmat10 $?/ Valgrind-6 / valgrind -v ./bogon == 25832 == Valgrind 0.10,x86 RedHat 7.1的內(nèi)存錯誤檢測器。 == 25832 ==版權(quán)所有(C)2000-2001和GNU GPL'd,由朱利安·西瓦德。 == 25832 ==啟動,帶標(biāo)志: == 25832 == --suppressions = / home / sewardj / Valgrind / redhat71.supp == 25832 ==從/lib/ld-linux.so.2讀取syms == 25832 ==從/lib/libc.so.6讀取符號 == 25832 ==從/mnt/pima/jrs/Inst/lib/libgcc_s.so.0讀取符號 == 25832 ==從/lib/libm.so.6讀取syms == 25832 ==從/mnt/pima/jrs/Inst/lib/libstdc++.so.3讀取符號 == 25832 ==從/home/sewardj/Valgrind/valgrind.so讀取符號 == 25832 ==從/ proc / self / exe讀取syms == == 25832 == 25832 ==大小4讀取無效 == 25832 == at 0x8048724:BandMatrix :: ReSize(int,int,int)(bogon.cpp:45) == 25832 == by 0x80487AF:main(bogon.cpp:66) == 25832 ==地址0xBFFFF74C不是stack'd,malloc'd或free'd == == 25832 == 25832 ==錯誤摘要:1個上下文中的1個錯誤(被禁止:0從0) == 25832 == malloc / free:在退出時使用:0個字節(jié),0個塊。 == 25832 == malloc / free:0 allocs,0 frees,0 bytes assigned。 == 25832 ==對于詳細(xì)的泄漏分析,重新運(yùn)行:--leak-check = yes海灣合作委員會在GCC 3.0發(fā)貨前大約一周內(nèi)修復(fù)了這個問題。
2.13。你可能看到的警告信息
其中一些僅在您運(yùn)行在詳細(xì)模式(啟用-v))時出現(xiàn):
-
More than 100 errors detected. Subsequent errors will still be recorded, but in less detail than before.
經(jīng)過100次不同的錯誤顯示,Valgrind對于收集這些錯誤變得更保守。然后,當(dāng)決??定兩個錯誤是否相同時,它只需要前兩個堆棧幀中的程序計數(shù)器進(jìn)行匹配。在此之前,前四個框架中的PC需要匹配。這個黑客具有在第一個100之后減慢新錯誤的出現(xiàn)的效果。可以通過重新編譯Valgrind來更改100個常量。
-
More than 1000 errors detected. I'm not reporting any more. Final error counts may be inaccurate. Go fix your program!
檢測到1000個不同的錯誤后,Valgrind再次忽略。收集更多不同的信息似乎不太可能對任何人都有實(shí)際的幫助,并且避免了Valgrind花費(fèi)越來越多的時間將新的錯誤與日益增長的收藏進(jìn)行比較的危險。如上所述,1000個數(shù)字是編譯時常數(shù)。
-
Warning: client switching stacks?
Valgrind在堆棧指針中發(fā)現(xiàn)了這么大的變化,它猜測客戶端正在切換到不同的堆棧。在這一點(diǎn)上,它使得kludgey猜測新堆棧的基礎(chǔ)在哪里,并相應(yīng)地設(shè)置內(nèi)存權(quán)限。目前,“大變化”被定義為堆棧指針寄存器值的變化大于2000000。如果Valgrind猜測錯誤,您可能會在此之后收到許多虛假的錯誤消息和/或在堆棧跟蹤記錄代碼中發(fā)生崩潰。通過向Valgrind通知使用VALGRIND_STACK_REGISTER客戶機(jī)請求的堆棧邊界可以避免這些問題。
-
Warning: client attempted to close Valgrind's logfile fd <number>
Valgrind不允許客戶端關(guān)閉日志文件,因?yàn)樵诖酥竽肋h(yuǎn)不會看到任何診斷信息。如果看到此消息,可能需要使用該?--log-fd=<number>選項(xiàng)來指定不同的日志文件文件描述符號。
-
Warning: noted but unhandled ioctl <number>
Valgrind觀察到對一系列?ioctl系統(tǒng)調(diào)用的調(diào)用,但沒有修改其內(nèi)存狀態(tài)信息(因?yàn)闆]有人寫過合適的包裝器)。該通話仍然會通過,但是由于內(nèi)存信息的不更新,您可能會在此之后收到虛假錯誤。
-
Warning: set address range perms: large range <number>
診斷消息,主要是為了受益于Valgrind開發(fā)人員,與內(nèi)存權(quán)限有關(guān)。
總結(jié)
以上是生活随笔為你收集整理的使用和了解Valgrind核心的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式——策略模式(C++实现)
- 下一篇: ubuntu 中 iptables 和