日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用和了解Valgrind核心

發(fā)布時間:2025/3/15 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用和了解Valgrind核心 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

使用和了解Valgrind核心

目錄

2.1。Valgrind與您的程序一致2.2。入門2.3。評論2.4。報告錯誤2.5。抑制錯誤2.6。核心命令行選項
2.6.1。工具選擇選項2.6.2。基本選項2.6.3。錯誤相關選項2.6.4。malloc相關選項2.6.5。不常見的選項2.6.6。調試選項2.6.7。設置默認選項
2.7。支持線程
2.7.1。調度和多線程性能
2.8。處理信號2.9。建筑和安裝Valgrind2.10。如果你有問題2.11。限制2.12。示例運行2.13。你可能看到的警告信息

本章介紹了Valgrind核心服務,命令行選項和行為。這意味著它是相關的,無論你使用什么特定的工具。這些信息應該足以使您有效地日常使用Valgrind。與Valgrind核心相關的高級主題在Valgrind的核心內容中介紹:高級主題。

術語的一點:本章中大多數(shù)提及“Valgrind”是指Valgrind的核心服務。

2.1。Valgrind與您的程序一致

Valgrind旨在盡可能不侵入。它直接與現(xiàn)有的可執(zhí)行文件一起工作。您不需要重新編譯,重新鏈接或以其他方式修改要檢查的程序。

你這樣調用Valgrind:

valgrind [valgrind-options] your-prog [your-prog-options]

最重要的選項是--tool哪個Valgrind工具運行。例如,如果要ls -l使用內存檢查工具Memcheck?運行命令?,請發(fā)出以下命令:

valgrind --tool = memcheck ls -l

但是,Memcheck是默認值,所以如果要使用它,您可以省略該--tool選項。

無論使用哪種工具,Valgrind在啟動之前都會控制您的程序。調試信息是從可執(zhí)行文件和關聯(lián)的庫中讀取的,以便在適當?shù)臅r候可以根據(jù)源代碼位置來編寫錯誤消息和其他輸出。

然后您的程序在由Valgrind核心提供的合成CPU上運行。當?shù)谝淮螆?zhí)行新代碼時,核心將代碼移動到所選擇的工具。該工具為此添加了自己的測試代碼,并將結果轉回核心,該核心協(xié)調該儀器化代碼的持續(xù)執(zhí)行。

各種工具之間添加的儀器代碼量有很大差異。在比例的一端,Memcheck添加代碼來檢查每個內存訪問和每個計算的值,使其運行速度比本機慢10-50倍。另一方面,Nulgrind最小的工具根本不添加任何工具,只能造成4倍的減速。

Valgrind模擬程序執(zhí)行的每個指令。因此,活動工具不僅會檢查應用程序中的代碼,還可以檢查所有支持動態(tài)鏈接庫(包括C庫,圖形庫等)的配置文件。

如果您使用錯誤檢測工具,Valgrind可能會檢測系統(tǒng)庫中的錯誤,例如您必須使用的GNU C或X11庫。您可能不會對這些錯誤感興趣,因為您可能無法控制該代碼。因此,Valgrind允許您選擇性地抑制錯誤,通過將它們記錄在Valgrind啟動時讀取的抑制文件中。構建機制選擇默認抑制,為您的機器上檢測到的操作系統(tǒng)和庫提供合理的行為。為了使寫入更容易,您可以使用該?--gen-suppressions=yes選項。這告訴Valgrind為每個報告的錯誤打印一個壓縮,然后您可以將其復制到抑制文件中。

不同的錯誤檢查工具報告不同種類的錯誤。因此,抑制機制允許您說明每種抑制適用的工具或工具。

2.2。入門

首先,請考慮重新編譯應用程序和支持啟用調試信息的庫(-g選項)可能是有益的。沒有調試信息,最好的Valgrind工具將能夠做的是猜測一個特定的代碼段所屬的功能,這使得錯誤消息和分析輸出幾乎沒用。隨著-g,您將收到指向相關源代碼行的消息。

另外您可能想要考慮的一個選項是,如果您正在使用C ++,那么-fno-inline。這使得更容易看到函數(shù)調用鏈,這可以幫助減少在大型C ++應用程序上導航時的混亂。例如,使用Memcheck調試OpenOffice.org在使用此選項時會更容易一些。您不需要這樣做,但是這樣做有助于Valgrind產生更準確,更少的混淆錯誤報告。如果您打算使用GNU GDB或其他調試器調試程序,那么您可能已經設置好了。或者,Valgrind選項?--read-inline-info=yes指示Valgrind讀取描述內聯(lián)信息的調試信息。這樣,即使應用程序使用內聯(lián)編譯,函數(shù)調用鏈也將被正確顯示。

如果您打算使用Memcheck:在極少數(shù)情況下,已經觀察到編譯器優(yōu)化(等于-O2?或者等等,有時候-O1)生成的代碼會使Memcheck錯誤地報告未初始化的值錯誤或缺少未初始化的值錯誤。我們已經詳細研究了這一點,不幸的是結果是這樣做會給已經是一個緩慢的工具帶來進一步的顯著的放緩。所以最好的解決方案是關閉優(yōu)化。因為這經常使事情變得難以控制,所以使用合理的妥協(xié)?-O這使您獲得更高優(yōu)化水平的大部分優(yōu)勢,同時保持Memcheck的假陽性或假陰性的機會相對較小。也,-Wall您應該編譯代碼, 因為它可以識別Valgrind在較高優(yōu)化級別可能會錯過的一些或所有問題。(-Wall?一般來說,使用也是一個好主意)所有其他工具(據(jù)我們所知)不受優(yōu)化級別的影響,對于像Cachegrind這樣的分析工具,最好在其正常優(yōu)化級別編譯程序。

Valgrind了解GCC 3.1及更高版本使用的DWARF2 / 3/4格式。用于“stabs”調試格式的讀者(在3.1之前由GCC版本使用)在Valgrind 3.9.0中被禁用。

準備好滾動時,按上述方法運行Valgrind。請注意,您應該在此運行真實的(機器代碼)可執(zhí)行文件。如果您的應用程序是由例如shell或Perl腳本啟動的,那么您需要修改它才能在真正的可執(zhí)行文件上調用Valgrind。直屬Valgrind的運行這些腳本會導致你得到有關錯誤報告?/bin/sh,?/usr/bin/perl或者你使用任何解釋。這可能不是你想要的,可能會令人困惑。你可以通過提供這個選項來強制這個問題?--trace-children=yes,但仍然可能會有混亂。

2.3。評論

Valgrind工具寫一個評論,一串文本,詳細的錯誤報告和其他重大事件。評論中的所有行都具有以下形式:

== 12345 == some-message-from-Valgrind

的12345是進程ID。該方案可以方便地將程序輸出與Valgrind注釋區(qū)分開來,也可以容易地區(qū)分不同流程的注釋,這些流程由于任何原因而被合并在一起。

默認情況下,Valgrind工具只會將重要信息寫入評論,以免發(fā)生帶有次要重要信息的信息。如果您想了解有關正在發(fā)生的更多信息,請重新運行,將-v選項傳遞給Valgrind。第二個?-v給出更多的細節(jié)。

您可以將注釋引導到三個不同的地方:

  • 默認值:將其發(fā)送到文件描述符,默認情況下為2(stderr)。所以,如果你給核心沒有選項,它將寫入標準錯誤流的注釋。如果要將其發(fā)送到其他文件描述符,例如9號,您可以指定?--log-fd=9。

    這是最簡單和最常見的安排,但是當Valgrinding整個進程的樹,特別是stdin / stdout / stderr特定的文件描述符可用于自己使用時,可能會導致問題。

  • 一個較少侵入性的選項是將注釋寫入您指定的文件?--log-file=filename。有特殊的格式說明符可用于在日志文件名中使用進程ID或環(huán)境變量名。如果您的程序調用多個進程(特別是MPI程序),這些是有用的/必要的。有關?詳細信息,請參閱基本選項部分。

  • 最簡單的選擇是將評論發(fā)送到網絡套接字。套接字被指定為IP地址和端口號對,如下所示:--log-socket=192.168.0.1:12345如果要將輸出發(fā)送到主機IP 192.168.0.1端口12345(注意:我們不知道12345是否是預先存在的重要性的端口)。您也可以省略端口號:?--log-socket=192.168.0.1在這種情況下,使用默認端口1500。該默認值由VG_CLO_DEFAULT_LOGPORT源中的常量定義?。

    請注意,不幸的是,您必須在此使用IP地址,而不是主機名。

    如果您沒有在另一端收聽東西,寫入網絡套接字是毫無意義的。我們提供一個簡單的監(jiān)聽程序,?valgrind-listener它接受指定端口上的連接,并將發(fā)送到stdout的任何東西復制。大概有人會告訴我們這是一個可怕的安全隱患。人們似乎有可能在充分的時間內寫出更復雜的聽眾。

    valgrind-listener可以接受多達50個Valgrinded進程的同時連接。在每行輸出的前面,打印當前活動連接數(shù)在圓括號中。

    valgrind-listener?接受三個命令行選項:

    -e --exit-at-zero

    當連接的進程的數(shù)量恢復為零時,退出。沒有這個,它將永遠運行,就是直到你發(fā)送Control-C。

    --max-connect=INTEGER

    默認情況下,監(jiān)聽器最多可以連接50個進程。偶爾,這個數(shù)字太小了。使用此選項提供不同的限制。例如?--max-connect=100。

    portnumber

    將其偵聽的端口從默認端口(1500)更改。指定的端口必須在1024到65535之間。同樣的限制適用于由--log-socketValgrind本身指定的端口號?。

    如果Valgrinded進程無法連接到偵聽器,無論什么原因(偵聽器未運行,無效或無法訪問的主機或端口等),Valgrind將切換回寫入stderr的注釋。任何失去與收聽者建立連接的進程也是如此。換句話說,殺死偵聽器不會殺死向其發(fā)送數(shù)據(jù)的進程。

  • 關于評論和工具分析輸出之間的關系,這里是一個重要的一點。評論包含Valgrind核心和所選工具的混合信息。如果工具報告錯誤,它會將其報告給評論。但是,如果該工具進行概要分析,則根據(jù)工具,配置文件數(shù)據(jù)將被寫入某種文件,并且與執(zhí)行的--log-*選項無關?。評論意圖是一個低帶寬,人類可讀的頻道。另一方面,分析數(shù)據(jù)通常是大量的,沒有進一步的處理是沒有意義的,這就是為什么我們選擇這種安排。

    2.4。報告錯誤

    當錯誤檢查工具檢測到程序發(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

    該消息表示該程序對地址0xBFFFF74C執(zhí)行了一個非法的4字節(jié)讀取操作,只要Memcheck可以告訴,它不是有效的堆棧地址,也不對應于任何當前的堆塊或最近釋放的堆塊。讀取是在bogon.cpp同一文件的第66行從第45?行發(fā)出的。對于與識別的(當前的或釋放的)堆塊相關聯(lián)的錯誤,例如讀取釋放的內存,Valgrind不僅報告發(fā)生錯誤的位置,而且在相關聯(lián)的堆塊被分配/釋放的地方。

    Valgrind記得所有錯誤報告。當檢測到錯誤時,將與舊報告進行比較,以查看是否重復。如果是這樣,則會注意到錯誤,但不會發(fā)出進一步的評論。這樣就避免了一大堆重復的錯誤報告。

    如果您想知道每個錯誤發(fā)生多少次,請運行該-v選項。執(zhí)行完成后,所有的報告將隨著它們的發(fā)生次數(shù)一并打印出來并排序。這使得很容易看出哪些錯誤最常發(fā)生。

    在相關操作實際發(fā)生之前報告錯誤。例如,如果您正在使用Memcheck并且您的程序嘗試從地址零讀取,Memcheck會發(fā)出一個消息,這樣會產生一個消息,您的程序可能會因分段錯誤而死亡。

    一般來說,您應該按照報告的順序嘗試修復錯誤。不這樣做可能會令人困惑。例如,當在Memcheck上運行時,將未初始化的值復制到多個存儲器位置并稍后使用它們的程序將生成多個錯誤消息。第一個這樣的錯誤消息可能給出最直接的線索,導致問題的根本原因。

    檢測重復錯誤的過程是相當昂貴的,如果您的程序產生大量錯誤,可能會成為顯著的性能開銷。為了避免嚴重的問題,Valgrind將會在收到1000個不同的錯誤后立即停止收集錯誤,總共有10,000,000個錯誤。在這種情況下,您可以停止您的程序并修復它,因為Valgrind在此之后不會告訴您任何其他有用的東西。請注意,在刪除了抑制誤差之后,1,000 / 10,000,000的限制適用。這些限制在m_errormgr.c必要時定義并可以增加。

    為了避免這種限制,您可以使用該?--error-limit=no選項。那么Valgrind總是會顯示錯誤,不管有多少。仔細使用此選項,因為它可能對性能有不良影響。

    2.5。抑制錯誤

    錯誤檢查工具可以檢測系統(tǒng)庫中的許多問題,例如預裝了操作系統(tǒng)的C庫。你不能輕易地修復這些錯誤,但是您不希望看到這些錯誤(是的,有很多!)所以Valgrind在啟動時讀取一個錯誤列表來抑制。./configure系統(tǒng)構建時腳本創(chuàng)建默認壓縮文件?。

    您可以隨時修改并添加到抑制文件,或者更好地編寫自己的文件。允許多個壓縮文件。如果您的項目的一部分包含您不能或不想修復的錯誤,但您不想不斷提醒他們,這是有用的。

    注:?到目前為止添加鎮(zhèn)壓最簡單的方法是使用--gen-suppressions=yes在描述選項核心命令行選項。這會自動產生抑制。為獲得最佳效果,您可能需要--gen-suppressions=yes手動編輯輸出?,在這種情況下,請閱讀本節(jié)。

    描述要抑制的每個錯誤都是非常具體地描述的,以最大限度地減少抑制指令無意中抑制一些你想要看到的類似錯誤的可能性。抑制機制旨在允許精確而靈活地規(guī)定誤差來抑制。

    如果使用該-v選項,則在執(zhí)行結束時,Valgrind將為每個使用的抑制打印一行,給出其使用次數(shù),其名稱以及定義了抑制的文件名和行號。根據(jù)抑制類型,文件名和行號可選地附加附加信息(例如通過memcheck泄漏抑制抑制的塊數(shù)和字節(jié)數(shù))。以下是運行中使用的禁用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負載抑制模式,$PREFIX/lib/valgrind/default.supp除非?--default-suppressions=no已指定。您可以通過指定--suppressions=/path/to/file.supp一次或多次來要求從其他文件添加抑制?。

    如果您想了解有關抑制的更多信息,請查閱現(xiàn)有的壓縮文件,同時閱讀以下文檔。glibc-2.3.supp源文件中的文件提供了一些很好的例子。

    每個抑制都有以下組件:

    • 第一行:它的名字。這僅僅提供了一個方便的名稱到抑制,由此它在使用鎮(zhèn)壓的打印輸出時,程序完成內容中所指。名字不重要,任何識別字符串都會做。

    • 第二行:抑制的工具的名稱(如果多于一個,以逗號分隔),以及由冒號分隔的抑制本身的名稱(nb:不允許有空格),例如:

      tool_name1,tool_name2:suppression_name

      回想一下,Valgrind是一個模塊化系統(tǒng),其中不同的儀器工具可以在運行時觀察您的程序。由于不同的工具檢測到不同種類的錯誤,因此有必要說明抑制對哪些工具有意義。

      工具在啟動時會抱怨工具不明白對此的任何抑制。工具忽略不針對他們的抑制。因此,將所有工具的禁止放在同一個壓縮文件中是相當實用的。

    • 下一行:少數(shù)抑制類型在第二行之后有額外的信息(例如,Param?對Memcheck?的抑制)

    • 剩余行:這是錯誤的調用上下文 - 導致它的函數(shù)調用鏈。最多可以有24行。

      位置可以是共享對象或函數(shù)的名稱。他們開始?obj:和?fun:分別。要匹配的功能和對象名稱可能會使用通配符?*和??。

      重要說明:?C ++函數(shù)名稱必須被?破壞。如果您手動寫入抑制,請使用該--demangle=no選項在錯誤消息中獲取被破壞的名稱。一個被破壞的C ++名稱的例子是?_ZN9QListView4showEv。這是GNU C ++編譯器在內部使用的形式,以及在壓縮文件中必須使用的形式。等效的被清空的名字,QListView::show()就是你在C ++源代碼級別看到的。

      位置線也可以簡單地“?...”(三個點)。這是一個幀級通配符,匹配零個或多個幀。幀級通配符是有用的,因為它們可以容易地忽略感興趣的幀之間不同數(shù)量的不感興趣的幀。當編寫壓縮時,這通常是重要的,這些抑制是針對編譯器完成的功能內聯(lián)量的變化而進行的。

    • 最后,整個鎮(zhèn)壓必須在花括號之間。每個大括號必須是自己的第一個字符。

    當抑制錯誤與抑制中的所有細節(jié)匹配時,抑制只會抑制錯誤。以下是一個例子:

    {__gconv_transform_ascii_internal / __ mbrtowc / mbtowcMEMCHECK:值4有趣的:__ gconv_transform_ascii_internal有趣的:__ MBR * TOC好玩的:mbtowc }

    這意味著:僅對于Memcheck,當數(shù)據(jù)大小為4時,當該函數(shù)發(fā)生在函數(shù)__gconv_transform_ascii_internal中時,當從名稱匹配的任何函數(shù)調用該函數(shù)時?,禁止使用未初始化的值錯誤,當?__mbr*toc從?mbtowc。在任何其他情況下都不適用。為用戶識別此抑制的字符串是__gconv_transform_ascii_internal/__mbrtowc/mbtowc。

    (有關Memcheck抑制類型的詳細信息,請參閱編寫抑制文件。)

    另一個例子,再次為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從任何位置調用時在同一個庫中的任何地方調用?時的任何大小4未初始化值錯誤libXaw.so.7.0。不符合要求的位置是令人遺憾的,但是關于所有你可以期望的,因為在這個例子的Linux發(fā)行版上發(fā)布的X11庫已經刪除了它們的符號表。

    雖然上述兩個例子并不清楚,但您可以自由地混合obj:和?fun:排除一些壓制。

    最后,這里是一個使用三個框架通配符的例子:

    {一個做作-示例MEMCHECK:泄漏有趣:的malloc...好玩的:DDD...好玩的:CCC...好玩的:主 } 這樣做會抑制Memcheck內存泄漏錯誤,在分配是通過main?調用(盡管任意數(shù)量的中介,包括零)?ccc,通過調用ddd和最終調用?來完成的malloc.。

    2.6。核心命令行選項

    如上所述,Valgrind的核心接受一組共同的選擇。這些工具還可以接受特定于工具的選項,這些選項是為每個工具單獨記錄的。

    在大多數(shù)情況下,Valgrind的默認設置成功地給出了合理的行為。我們按粗略類別分組可用的選項。

    2.6.1。工具選擇選項

    單一最重要的選項。

    --tool=<toolname> [default: memcheck]

    運行Valgrind工具toolname,例如memcheck,cachegrind,callgrind,helgrind,drd,massif,lackey,none,exp-sgcheck,exp-bbv,exp-dhat等

    2.6.2。基本選項

    這些選項適用于所有工具。

    -h --help

    顯示所有選項的幫助,包括核心和所選工具。如果該選項重復,則相當于給予?--help-debug。

    --help-debug

    --help與之一樣,但也列出了通常僅用于Valgrind開發(fā)人員的調試選項。

    --version

    顯示Valgrind內核的版本號。工具可以有自己的版本號。有一個方案來確保只有核心版本是已知的工具才能執(zhí)行的工具。這樣做是為了盡量減少由于工具與核心版本不兼容而產生的奇怪問題的機會。

    -q,?--quiet

    靜默運行,只打印錯誤消息。如果您正在進行回歸測試或有其他自動化測試機器,那么有用。

    -v,?--verbose

    更冗長?提供有關程序各個方面的更多信息,例如:加載的共享對象,使用的禁用,檢測和執(zhí)行引擎的進度以及有關異常行為的警告。重復該選項會增加詳細程度。

    --trace-children=<yes|no> [default: no]

    啟用后,Valgrind將跟蹤通過exec系統(tǒng)調用發(fā)起的子進程。這對于多進程程序是必需的。

    請注意,Valgrind確實會追蹤到一個fork(的孩子)?,因為?fork這樣一個進程的相同拷貝就很難,所以這個選項可能被命名得很糟。然而,大多數(shù)fork電話的孩子?立即打電話exec?。

    --trace-children-skip=patt1,patt2,...

    此選項僅在指定時--trace-children=yes才有效果?。它允許一些孩子被跳過。該選項為Valgrind不應該跟蹤的可執(zhí)行文件的名稱使用逗號分隔的模式列表。這些模式可以包括元字符??和*,它們具有通常的意義。

    這可以用于從Valgrind上運行的進程樹中修剪不感興趣的分支。但是,使用它時應該小心。當Valgrind跳過跟蹤到可執(zhí)行文件時,它不會跳過跟蹤該可執(zhí)行文件,它也跳過跟蹤任何可執(zhí)行文件的子進程。換句話說,該標志不僅僅是引起跟蹤停止在指定的可執(zhí)行文件 - 它跳過跟蹤任何一個指定的可執(zhí)行文件的整個進程子樹。

    --trace-children-skip-by-arg=patt1,patt2,...

    這是一樣的?--trace-children-skip,有一個區(qū)別:關于是否追蹤到子進程的決定是通過檢查子進程的參數(shù)而不是其可執(zhí)行文件的名稱來進行的。

    --child-silent-after-fork=<yes|no> [default: no]

    啟用后,Valgrind不會顯示任何來自fork調用的子進程的調試或記錄輸出。這可以使輸出在處理創(chuàng)建子進程時更不容易混淆(盡管更具誤導性)。它特別有用--trace-children=。如果要求XML輸出(--xml=yes),則強烈建議使用此選項,否則來自子級和父級的XML可能會混淆,這通常會使其無用。

    --vgdb=<no|yes|full> [default: yes]

    當Valgrind的將提供“gdbserver的”功能?--vgdb=yes或--vgdb=full指定的。這允許外部GNU GDB調試器在Valgrind上運行時控制和調試程序。?--vgdb=full引起顯著的性能開銷,但提供更精確的斷點和觀察點。有關詳細說明,請參閱使用Valgrind的gdbserver和GDB調試程序。

    如果嵌入式gdbserver已啟用但目前沒有使用gdb,則vgdb?命令行實用程序可以從shell向Valgrind發(fā)送“監(jiān)視器命令”。Valgrind內核提供一組?Valgrind監(jiān)視器命令。工具可以選擇提供特定于工具的監(jiān)視器命令,這些命令在工具特定的章節(jié)中有所記錄。

    --vgdb-error=<number> [default: 999999999]

    當Valgrind gdbserver啟用--vgdb=yes或時,使用此選項?--vgdb=full。報告錯誤的工具將number在凍結程序并等待您與GDB連接之前等待“?”錯誤報告。因此,值為零將導致在執(zhí)行程序之前啟動gdbserver。這通常用于在執(zhí)行前插入GDB斷點,并且還可以與不報告錯誤的工具(如Massif)一起使用。

    --vgdb-stop-at=<set> [default: none]

    當Valgrind gdbserver啟用--vgdb=yes或時,使用此選項?--vgdb=full。--vgdb-error報告之后,將為每個錯誤調用Valgrind gdbserver?。您還可以詢問為其他事件調用Valgrind gdbserver,以下列方式之一指定:

    • 一個或多個逗號分隔的列表?startup exit valgrindabexit。

      值startup?exit?valgrindabexit分別表示在程序執(zhí)行之前,在程序的最后一個指令之后,在Valgrind異常退出(例如內部錯誤,內存不足,...)中調用gdbserver。

      注意:startup并且?--vgdb-error=0將會在程序執(zhí)行之前調用Valgrind gdbserver。此外?--vgdb-error=0,還將導致您的程序停止所有后續(xù)錯誤。

    • all指定完整集。相當于?--vgdb-stop-at=startup,exit,valgrindabexit。

    • none?為空集。

    --track-fds=<yes|no> [default: no]

    啟用后,Valgrind將通過gdbserver monitor命令在出口或請求時打印出打開的文件描述符列表v.info open_fds。與每個文件描述符一起打印文件打開位置的堆棧回溯以及與文件描述符相關的任何細節(jié),如文件名或套接字詳細信息。

    --time-stamp=<yes|no> [default: no]

    啟用后,每個消息之前都會顯示自啟動以來的已經逝去的時鐘,表示為天,小時,分鐘,秒和毫秒。

    --log-fd=<number> [default: 2, stderr]

    指定Valgrind應將其所有消息發(fā)送到指定的文件描述符。默認值2是標準錯誤通道(stderr)。請注意,這可能會干擾客戶端自己使用stderr,因為Valgrind的輸出將與客戶端發(fā)送給stderr的任何輸出交錯。

    --log-file=<filename>

    指定Valgrind應將其所有郵件發(fā)送到指定的文件。如果文件名為空,則會導致中止。有三種特殊的格式說明符可以在文件名中使用。

    %p被當前進程ID替換。這對于調用多個進程的程序非常有用。警告:如果您使用--trace-children=yes并且您的程序調用多個進程或您的程序fork而不調用exec,并且您不使用此說明符(或%q下面的說明符),則所有這些進程的Valgrind輸出將進入一個文件,可能會混亂并且可能不完整。

    %q{FOO}被替換為環(huán)境變量的內容FOO。如果?{FOO}部件畸形,會導致中止。此說明符很少需要,但在某些情況下(例如運行MPI程序時)非常有用。這個想法是指定一個變量,該變量將為作業(yè)中的每個進程設置不同,例如BPROC_RANK或MPI設置中適用的任何內容。如果未設置命名環(huán)境變量,則會導致中止。請注意,在某些shell中,?角色{和}角色可能需要使用反斜杠進行轉義。

    %%被替換%。

    如果%其后的任何其他字符,則導致中止。

    如果文件名指定相對文件名,則將其放入程序的初始工作目錄中:當程序在fork之后或exec之后執(zhí)行時,這是當前目錄。如果它指定絕對文件名(即以'/'開始),那么它將放在那里。

    --log-socket=<ip-address:port-number>

    指定Valgrind應將其所有消息發(fā)送到指定IP地址的指定端口。可以省略端口,在這種情況下使用端口1500。如果無法連接到指定的套接字,則Valgrind將返回寫入標準錯誤(stderr)的輸出。此選項旨在與valgrind-listener程序一起使用?。有關詳細信息,請參閱?手冊中的注釋。

    2.6.3。錯誤相關選項

    所有可以報告錯誤的工具都使用這些選項,例如Memcheck,而不是Cachegrind。

    --xml=<yes|no> [default: no]

    啟用時,輸出的重要部分(例如工具錯誤消息)將采用XML格式而不是純文本格式。此外,XML輸出將被發(fā)送到與純文本輸出不同的輸出通道。因此,還必須使用的一個?--xml-fd,--xml-file或?--xml-socket到指定的XML將被發(fā)送。

    不太重要的消息將仍然以純文本被打印,但是,因為XML輸出和明文輸出被發(fā)送到不同的輸出信道(純文本輸出的目的地仍然由控制--log-fd,--log-file?和--log-socket)這不應引起問題。

    此選項旨在使消費Valgrind輸出的工具(如GUI前端)變得更簡單。目前這個選項適用于Memcheck,Helgrind,DRD和SGcheck。輸出格式在docs/internals/xml-output-protocol4.txt?Valgrind 3.5.0或更高版本的源代碼樹中的文件?中指定。

    GUI請求XML輸出時,推薦的選項是:--xml=yes啟用XML輸出,?--xml-file將XML輸出發(fā)送到(大概是GUI選擇的)文件,--log-file將純文本輸出發(fā)送到第二個GUI選擇的文件,?--child-silent-after-fork=yes,并將?-q純文本輸出限制為由Valgrind本身創(chuàng)建的關鍵錯誤消息。例如,無法讀取指定的抑制文件將被視為關鍵錯誤消息。這樣,為了成功運行文本輸出文件將為空。但是如果它不是空的,那么它將包含GUI用戶應該注意的重要信息。

    --xml-fd=<number> [default: -1, disabled]

    指定Valgrind應將其XML輸出發(fā)送到指定的文件描述符。它必須與之配合使用?--xml=yes。

    --xml-file=<filename>

    指定Valgrind應將其XML輸出發(fā)送到指定的文件。它必須與之配合使用?--xml=yes。出現(xiàn)在文件名中的任何%p或者?%q序列以與它們完全相同的方式進行擴展--log-file。有關--log-file詳細信息,請參閱說明。

    --xml-socket=<ip-address:port-number>

    指定Valgrind應將指定端口的XML輸出發(fā)送到指定的IP地址。它必須與之配合使用--xml=yes。參數(shù)的形式與使用的形式相同--log-socket。有關--log-socket?詳細信息,請參閱說明。

    --xml-user-comment=<string>

    在XML輸出的開始處嵌入一個額外的用戶注釋字符串。僅在--xml=yes指定時才能工作;?否則忽略。

    --demangle=<yes|no> [default: yes]

    啟用/禁用C ++名稱的自動解碼(解碼)。默認啟用。啟用后,Valgrind將嘗試將編碼的C ++名稱轉換為接近原始文件的東西。demangler處理由g ++版本2.X,3.X和4.X驅動的符號。

    關于解密的一個重要事實是在壓制文件中提到的函數(shù)名稱應該處于它們的格式。在搜索適用的抑制方面,Valgrind不會使功能名稱發(fā)生拆分,因為否則會使壓縮文件內容取決于Valgrind的分離機器的狀態(tài),并且還會減緩抑制匹配。

    --num-callers=<number> [default: 12]

    指定標識程序位置的堆棧跟蹤中顯示的最大條目數(shù)。請注意,僅使用前四個功能位置(當前功能中的位置,以及其三個直接調用者的位置)常見錯誤。所以這并不影響所報錯誤的總數(shù)。

    最大值為500.請注意,較高的設置將使Valgrind運行速度更慢,并占用更多內存,但在使用深嵌套的調用鏈的程序時可能會很有用。

    --unw-stack-scan-thresh=<number> [default: 0]?,?--unw-stack-scan-frames=<number> [default: 5]

    堆棧掃描支持僅在ARM目標上可用。

    這些標志通過堆棧掃描啟用和控制堆棧展開。當正常堆棧展開機制 - 使用Dwarf CFI記錄和幀指針跟隨失敗時,堆棧掃描可能能夠恢復堆棧跟蹤。

    請注意,堆棧掃描是一種不精確的啟發(fā)式機制,可能會產生非常誤導的結果,或者根本沒有。它只能在緊急情況下使用,正常展開失敗,重要的是仍然有堆棧跟蹤。

    堆棧掃描是一種簡單的技術:展開器從堆棧中讀取單詞,并嘗試猜測哪些可能是返回地址,通過檢查它們是否指向ARM或Thumb調用指令。如果是這樣,該詞被添加到回溯。

    當函數(shù)調用返回時,會發(fā)生主要的危險,其返回地址被暴露,并且調用一個新的函數(shù),但新函數(shù)不會覆蓋舊的地址。這樣做的結果是回溯可能包含已經返回的函數(shù)的條目,因此非常混亂。

    此實現(xiàn)的第二個限制是它將僅掃描包含起始堆棧指針的頁面(通常為4KB)。如果堆棧幀較大,則這可能導致軌跡中僅存在少量(甚至不甚甚)。此外,如果您不幸運,并且在其包含頁面的末尾附近有一個初始堆棧指針,掃描可能會錯過所有有趣的幀。

    默認情況下,堆棧掃描被禁用。正常的使用情況是要求堆棧跟蹤否則會很短。所以,啟用它,使用--unw-stack-scan-thresh=number。這要求Valgrind嘗試使用堆棧掃描來“擴展”包含少于number幀的堆棧跟蹤。

    如果堆棧掃描發(fā)生,它將只生成最多指定的幀數(shù)--unw-stack-scan-frames。通常,堆棧掃描會生成這么多垃圾條目,默認情況下該值設置為低值(5)。在任何情況下,堆棧跟蹤大于--num-callers創(chuàng)建指定的值。

    --error-limit=<yes|no> [default: yes]

    啟用后,Valgrind停止報告錯誤,總共有10,000,000個,或者1,000個不同的。這是為了阻止錯誤跟蹤機制在具有許多錯誤的程序中成為巨大的性能開銷。

    --error-exitcode=<number> [default: 0]

    如果Valgrind在運行中報告任何錯誤,則指定返回的替代退出代碼。當設置為默認值(零)時,Valgrind的返回值將始終是正在仿真的進程的返回值。當設置為非零值時,將返回該值,如果Valgrind檢測到任何錯誤。這對于使用Valgrind作為自動化測試套件的一部分非常有用,因為通過檢查返回碼,可以輕松檢測Valgrind報告錯誤的測試用例。

    --error-markers=<begin>,<end> [default: none]

    當錯誤輸出為純文本(即XML未使用)時,?--error-markers指示在每個錯誤之前(之后)輸出包含begin(end)字符串的行。

    這樣的標記線便于搜索包含與程序輸出混合的valgrind錯誤的輸出文件中的錯誤和/或提取錯誤。

    請注意,空標記被接受。因此,只能使用開始(或結束)標記。

    --sigill-diagnostics=<yes|no> [default: yes]

    啟用/禁用打印非法指令診斷。默認情況下啟用,但默認為禁用?--quiet。通過給出此選項,總是可以明確地覆蓋默認值。

    啟用該功能后,在程序發(fā)出SIGILL信號之前,每當遇到Valgrind無法解碼或轉換的指令時,都會打印一條警告消息以及一些診斷信息。通常,非法指令表示程序中的錯誤或缺少對Valgrind特定指令的支持。但有些程序會故意嘗試執(zhí)行可能丟失的指令,并捕獲SIGILL信號以檢測處理器功能。使用此標志可以避免在這種情況下您會得到的診斷輸出。

    --show-below-main=<yes|no> [default: no]

    默認情況下,錯誤的堆棧跟蹤不會顯示下面的任何函數(shù),main因為大多數(shù)時候它不感興趣C庫東西和/或gobbledygook。或者,如果main堆棧跟蹤中不存在堆棧跟蹤,堆棧跟蹤將不會顯示main類似函數(shù)(如glibc)的?任何函數(shù)__libc_start_main。此外,如果?main跟蹤中存在類似函數(shù),則它們被歸一化為(below main)使得輸出更確定。

    如果啟用此選項,將顯示所有堆棧跟蹤條目,并且main類似的函數(shù)將不會被歸一化。

    --fullpath-after=<string> [default: don't show source paths]

    默認情況下,Valgrind僅顯示堆棧跟蹤中的文件名,但不顯示源文件的完整路徑。當在大型項目中使用Valgrind,其中源位于多個不同的目錄中時,這可能是不方便的。?--fullpath-after為這個問題提供了靈活的解決方案。當此選項存在時,將顯示每個源文件的路徑,其中包含以下所有重要的注意事項:如果string在路徑中找到,則將string省略直到和包含的路徑,否則路徑未修改。注意,string不需要作為路徑的前綴。

    例如,考慮一個名為的文件?/home/janedoe/blah/src/foo/bar/xyzzy.c。指定--fullpath-after=/home/janedoe/blah/src/?將導致Valgrind顯示名稱foo/bar/xyzzy.c。

    因為字符串不需要作為前綴,所以?--fullpath-after=src/會產生相同的輸出。當路徑包含任意機器生成的字符時,這很有用。例如,/my/build/dir/C32A1B47/blah/src/foo/xyzzy?可以修剪路徑?以foo/xyzzy?使用?--fullpath-after=/blah/src/。

    如果您只想看到完整的路徑,只需指定一個空字符串:--fullpath-after=。這不是一個特殊情況,只是上述規(guī)則的邏輯后果。

    最后,你可以--fullpath-after?多次使用。任何外觀都會導致Valgrind切換到生成完整路徑并應用上述過濾規(guī)則。每個生成的路徑按照--fullpath-after指定的順序與所有指定的字符串進行比較。要匹配的第一個字符串將導致路徑被截斷,如上所述。如果不匹配,則顯示完整路徑。當源從多個不相關的目錄中抽取時,這有助于切除前綴。

    --extra-debuginfo-path=<path> [default: undefined and unused]

    默認情況下,Valgrind在幾個眾所周知的路徑中搜索調試對象,例如/usr/lib/debug/。

    但是,您可能希望將調試對象放置在任意位置,例如在具有有限本地存儲空間的移動設備上運行Valgrind時的外部存儲。另一個例子可能是您沒有在運行Valgrind的系統(tǒng)上安裝調試對象包的權限的情況。

    在這些情況下,您可以提供絕對路徑作為Valgrind通過指定搜索調試對象的額外最終位置?--extra-debuginfo-path=/path/to/debug/objects。給定的路徑將被添加到搜索對象的絕對路徑名稱。例如,如果Valgrind正在尋找/w/x/y/zz.so?和--extra-debuginfo-path=/a/b/c指定的debuginfo,那么它將在此處查找一個調試對象?/a/b/c/w/x/y/zz.so。

    該標志只能指定一次。如果指定多次,則只會保留最后一個實例。

    --debuginfo-server=ipaddr:port [default: undefined and unused]

    這是在3.9.0版本中引入的一個新的,實驗性的功能。

    在某些情況下,從存儲在不同機器上的對象讀取debuginfo可能很方便。使用此標志,Valgrind將在本地文件系統(tǒng)中找不到debuginfo對象時查詢運行在ipaddr偵聽端口上的debuginfo服務器port。

    debuginfo服務器必須接受端口上的TCP連接port。debuginfo服務器包含在源文件中auxprogs/valgrind-di-server.c。它將僅從它啟動的目錄中提供。?port如果未指定,默認為客戶端和服務器的1500。

    如果Valgrind?/w/x/y/zz.so通過使用debuginfo服務器查找debuginfo,它將剝離路徑名組件,并僅zz.so在服務器上請求。反過來,它將僅在其當前工作目錄中查找匹配的debuginfo對象。

    根據(jù)Valgrind的要求,debuginfo數(shù)據(jù)以小片段(8 KB)傳輸。使用LZO壓縮每個塊以減少傳輸時間。通過單階段802.11g(WiFi)網絡鏈路實現(xiàn)了最佳性能。

    請注意,即使使用debuginfo服務器,也會執(zhí)行使用GNU debuglink CRC方案來匹配主要和調試對象的檢查。要禁用此類檢查,您還需要指定?--allow-mismatched-debuginfo=yes。

    默認情況下,Valgrind構建系統(tǒng)將為valgrind-di-server目標平臺構建,這幾乎肯定不是您想要的。到目前為止,我們一直無法找到如何獲取automake / autoconf來構建它的構建平臺。如果要使用它,則必須使用頂部顯示的命令手動重新編譯它auxprogs/valgrind-di-server.c。

    --allow-mismatched-debuginfo=no|yes [no]

    當從單獨的debuginfo對象讀取debuginfo時,Valgrind將默認使用GNU debuglink機制檢查main和debuginfo對象是否匹配。這樣保證它不會從過期的debuginfo對象中讀取debuginfo,并且還可以確保Valgrind不會因為不匹配而崩潰。

    此檢查可以使用?--allow-mismatched-debuginfo=yes。當debuginfo和主對象沒有以正確的方式拆分時,這可能很有用。盡管如此,使用它時要小心:它禁用所有一致性檢查,并且當主要和debuginfo對象不匹配時,Valgrind被觀察到崩潰。

    --suppressions=<filename> [default: $PREFIX/lib/valgrind/default.supp]

    指定一個額外的文件,從中讀取要抑制的錯誤的描述。您可以使用多達100個額外的壓縮文件。

    --gen-suppressions=<yes|no|all> [default: no]

    設置后yes,Valgrind將在每次顯示錯誤后暫停,并打印行:

    ????----?Print?suppression???---?[Return/N/n/Y/y/C/c]?----

    按Ret或,N Ret或?n Ret導致Valgrind繼續(xù)執(zhí)行而不打印此錯誤的抑制。

    按下Y Ret或?y Ret導致Valgrind寫入此錯誤的抑制。如果您不想再聽到有關該錯誤的信息,可以將其剪切并粘貼到抑制文件中。

    設置時all,Valgrind將會針對每個報告的錯誤打印一個抑制,而不會查詢用戶。

    此選項對于C ++程序特別有用,因為它根據(jù)需要打印出具有破壞名稱的抑制。

    請注意,打印的壓印盡可能具體。您可能希望通過添加通配符到函數(shù)名稱以及使用幀級別的通配符來尋找類似的通配符。通配設備功能強大而靈活,并且經過仔細的編輯,您可能只需少量的壓制即可抑制整個系列的相關錯誤。

    有時兩個不同的錯誤被同樣的抑制所壓制,在這種情況下,Valgrind將會多次輸出抑制,但您只需要在壓縮文件中有一個副本(但是不止一個則不會導致問題)。此外,抑制名稱為?<insert a suppression name here>:該名稱并不重要,它只用于-v打印所有使用的抑制記錄的選項。

    --input-fd=<number> [default: 0, stdin]

    當使用?--gen-suppressions=yes時,Valgrind將停止,以便在發(fā)生每個錯誤時讀取您的鍵盤輸入。默認情況下,它從標準輸入(stdin)讀取,這對于關閉stdin的程序是有問題的。此選項允許您指定從中讀取輸入的備用文件描述符。

    --dsymutil=no|yes [yes]

    此選項僅在Mac OS X上運行Valgrind時才有用。

    Mac OS X使用延遲調試信息(debuginfo)鏈接方案。當包含debuginfo的對象文件鏈接到一個.dylib或可執(zhí)行文件中時,debuginfo不會被復制到最終文件中。相反,必須通過在可執(zhí)行文件上運行dsymutil系統(tǒng)提供的實用程序來手動鏈接debuginfo?.dylib。生成的組合debuginfo放在可執(zhí)行文件旁邊的目錄中,或者.dylib擴展名.dSYM。

    使用--dsymutil=no,Valgrind將檢測?.dSYM目錄丟失或存在的情況,但不符合關聯(lián)的可執(zhí)行文件,或者.dylib很可能是因為它已過期。在這種情況下,Valgrind會打印一個警告消息,但不采取進一步行動。

    隨著--dsymutil=yes,Valgrind的意志,在這樣的情況下,自動運行dsymutil必要使debuginfo軟最新的。對于所有實際的目的,如果您始終使用--dsymutil=yes,則絕對不需要dsymutil手動運行或作為應用程序構建系統(tǒng)的一部分運行,因為Valgrind將根據(jù)需要運行它。

    Valgrind的不會嘗試運行dsymutil在任何可執(zhí)行文件或庫?/usr/,?/bin/,?/sbin/,?/opt/,?/sw/,?/System/,?/Library/或?/Applications/?因為dsymutil總是會在這種情況下失敗。它失敗了,因為這種預安裝的系統(tǒng)組件的debuginfo在任何地方都不可用,也因為它需要這些目錄中的寫入權限。

    使用--dsymutil=yes時要小心,因為它會導致預先存在的.dSYM?目錄被靜默刪除并重新創(chuàng)建。還要注意的?dsymutil是相當慢,有的時候太過分了。

    --max-stackframe=<number> [default: 2000000]

    堆棧幀的最大大小。如果堆棧指針移動超過此值,則Valgrind將假定程序正在切換到另一個堆棧。

    如果您的程序具有大量堆棧分配的數(shù)組,則可能需要使用此選項。Valgrind跟蹤程序的堆棧指針。如果它改變超過閾值,Valgrind假設您的程序正在切換到不同的堆棧,Memcheck的行為與堆棧指針變化小于閾值的行為不同。通常這個啟發(fā)式工作原理很好。但是,如果您的程序在堆棧中分配大型結構,則該啟發(fā)式將被愚弄,并且Memcheck將會報告大量的無效堆棧訪問。此選項允許您將閾值更改為不同的值。

    如果Valgrind的調試輸出指示您這樣做,您應該僅考慮使用此選項。在這種情況下,它會告訴您應該指定的新閾值。

    通常,在堆棧上分配大型結構是一個壞主意,因為您可以輕松地耗盡堆棧空間,特別是在內存有限的系統(tǒng)上,或者希望支持大量線程,每個都有一個小堆棧,并且還因為錯誤由Memcheck執(zhí)行的檢查對堆分配數(shù)據(jù)比對堆棧分配的數(shù)據(jù)更有效。如果您必須使用此選項,您可能希望考慮將代碼重寫為在堆上分配而不是堆棧。

    --main-stacksize=<number> [default: use current 'ulimit' value]

    指定主線程堆棧的大小。

    為了簡化內存管理,Valgrind在啟動時保留主線程堆棧的所有空間。這意味著它需要在啟動時知道所需的堆棧大小。

    默認情況下,Valgrind使用當前的“ulimit”值作為堆棧大小,或16 MB,以較低者為準。在許多情況下,這將提供8到16 MB的堆棧大小,對于大多數(shù)應用程序幾乎不會溢出。

    如果您需要更大的總堆棧大小,請使用--main-stacksize它來指定它。只需將其設置為您所需的高度,因為保留比您需要的更多空間(即,比您需要的數(shù)百兆字節(jié))約束了Valgrind的內存分配器,并可能減少Valgrind可以使用的內存總量。這對32位機器來說真的很重要。

    在Linux上,您可以要求一個大小為2GB的堆棧。如果無法分配堆棧,Valgrind將會停止診斷消息。

    --main-stacksize只影響程序初始線程的堆棧大小。它對線程棧的大小沒有任何影響,因為Valgrind不會分配它們。

    您可能需要同時使用--main-stacksize?和--max-stackframe在一起。重要的是要理解,--main-stacksize設置最大堆棧總數(shù),同時--max-stackframe指定任何一個堆棧幀的最大大小。您將必須--main-stacksize為自己找出價值(通常,如果您的應用程序發(fā)生故障)。但是--max-stackframe,如果需要,Valgrind會告訴你需要的尺寸。

    如在描述中進一步討論的--max-stackframe,對于大堆棧的要求是潛在可移植性問題的跡象。最好建議將所有大數(shù)據(jù)放在堆分配的內存中。

    --max-threads=<number> [default: 500]

    默認情況下,Valgrind最多可處理500個線程。偶爾,這個數(shù)字太小了。使用此選項提供不同的限制。例如?--max-threads=3000。

    2.6.4。malloc相關選項

    對于使用自己的版本?malloc(例如Memcheck,Massif,Helgrind,DRD)的工具,適用以下選項。

    --alignment=<number> [default: 8 or 16, depending on the platform]

    默認情況下Valgrind的的malloc,?realloc等等,返回塊,其起始地址為8字節(jié)對齊或16字節(jié)對齊(數(shù)值取決于平臺和相匹配的平臺默認)。此選項允許您指定不同的對齊方式。提供的值必須大于或等于默認值小于或等于4096,并且必須是2的冪。

    --redzone-size=<number> [default: depends on the tool]

    Valgrind的malloc, realloc,等等,在運行程序分配的每個堆塊之前和之后添加填充塊。這種填充塊稱為redzones。redzone大小的默認值取決于工具。例如,Memcheck在客戶端分配的每個塊之前和之后增加并保護至少16個字節(jié)。這允許它檢測最多16個字節(jié)的塊欠載或超限。

    增加紅色區(qū)域大小可以檢測更大距離的超限,但會增加Valgrind使用的內存量。減少紅區(qū)大小將減少Valgrind所需的內存,同時也降低了檢測超出/欠載的機會,因此不推薦使用。

    2.6.5。不常見的選項

    這些選項適用于所有工具,因為它們會影響Valgrind核心的某些模糊工作。大多數(shù)人不需要使用它們。

    --smc-check=<none|stack|all|all-non-file> [default: all-non-file for x86/amd64/s390x, stack for other archs]

    此選項控制Valgrind對自修改代碼的檢測。如果沒有進行任何檢查,當程序執(zhí)行一些代碼時,用新的代碼覆蓋它,并執(zhí)行新的代碼,Valgrind將繼續(xù)執(zhí)行舊代碼的翻譯。這可能會導致錯誤的行為和/或崩潰。

    對于“現(xiàn)代”架構 - 任何不是x86,amd64或s390x - 的默認設置stack。這是因為正確的程序必須采取明確的行動來重新建立代碼修改后的DI緩存一致性。Valgrind遵守并尊重此類行為,結果是自我修改代碼以零額外成本進行透明處理。

    對于x86,amd64和s390x,程序不需要通知硬件所需的DI一致性同步。因此,默認是all-non-file覆蓋將代碼生成到匿名(非文件備份)mmap'd區(qū)域的正常情況。

    四種可用設置的含義如下。無檢測(none)檢測堆棧上的自修改代碼(由GCC用于實現(xiàn)嵌套函數(shù))(stack),檢測每個地方的自修改代碼all,并檢測除了文件支持的映射之外的其他修改代碼(all-non-file)。

    跑步all會緩慢的下降。運行時none很少加快速度,因為很少的代碼在大多數(shù)程序中動態(tài)生成。該?VALGRIND_DISCARD_TRANSLATIONS客戶端請求是一種替代--smc-check=all?和--smc-check=all-non-file?需要更多的程序員的努力,但允許Valgrind的更快地運行您的程序,告訴它準確翻譯時需要重新制作。

    --smc-check=all-non-file提供了更便宜但更有限的版本--smc-check=all。它會將檢查添加到不是源于文件支持的內存映射的任何翻譯。生成代碼的典型應用程序(例如Web瀏覽器中的JIT)將生成代碼到匿名的mmaped區(qū)域,而瀏覽器的“固定”代碼總是存在于文件支持的映射中。?--smc-check=all-non-file?利用這一觀察,限制檢查可能是JIT生成的代碼的開銷。

    --read-inline-info=<yes|no> [default: see below]

    啟用后,Valgrind將從DWARF3調試信息中讀取有關內聯(lián)函數(shù)調用的信息。這減慢了Valgrind啟動并使其使用更多的內存(通常為每個內聯(lián)代碼段,6個字和空格用于函數(shù)名稱),但它會導致更多描述性的堆棧跟蹤。對于3.10.0版本,默認情況下僅對Linux,Android和Solaris目標以及僅用于Memcheck,Helgrind和DRD的工具啟用此功能。以下是一些堆棧跟蹤的示例?--read-inline-info=no:

    == 15380 ==有條件的跳轉或移動取決于未初始化的值 == 15380 == at 0x80484EA:main(inlinfo.c:6) == == 15380 == 15380 ==有條件跳轉或移動取決于未初始化的值 == 15380 == at 0x8048550:fun_noninline(inlinfo.c:6) == 15380 == by 0x804850E:main(inlinfo.c:34) == == 15380 == 15380 ==有條件跳轉或移動取決于未初始化的值 == 15380 == at 0x8048520:main(inlinfo.c:6)

    以下是與以下相同的錯誤?--read-inline-info=yes:

    == 15377 ==有條件跳轉或移動取決于未初始化的值 == 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 ==有條件跳轉或移動取決于未初始化的值 == 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 ==有條件跳轉或移動取決于未初始化的值 == 15377 == at 0x8048520:fun_d(inlinfo.c:6) == 15377 == by 0x8048520:main(inlinfo.c:35)
    --read-var-info=<yes|no> [default: no]

    啟用后,Valgrind將從DWARF3調試信息中讀取有關變量類型和位置的信息。這顯著減緩了Valgrind的啟動,并使其占用了更多的內存,但是對于可以利用它的工具(Memcheck,Helgrind,DRD),它可能會導致更精確的錯誤消息。例如,以下是Memcheck發(fā)出的一些標準錯誤:

    == 15363 ==客戶端檢查請求期間發(fā)現(xiàn)的未初始化字節(jié) == 15363 == at 0x80484A9:croak(varinfo1.c:28) == 15363 == 0x8048544:main(varinfo1.c:55) == 15363 ==地址0x80497f7是數(shù)據(jù)符號“global_i2”內的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”內的0個字節(jié) == 15370 ==在線程1的第1幀中的varinfo1.c:46聲明
    --vgdb-poll=<number> [default: 5000]

    作為其主循環(huán)的一部分,Valgrind調度程序將輪詢以檢查某些活動(例如外部命令或gdb的某些輸入)是否必須由gdbserver處理。在運行給定數(shù)量的基本塊(或略大于給定數(shù)量的基本塊)之后,將進行此活動輪詢。這個投票相當便宜,所以默認值設置得比較低。如果vgdb無法使用ptrace系統(tǒng)調用中斷Valgrind,如果系統(tǒng)調用中的所有線程(大部分時間)被阻止,您可能會進一步減少此值。

    --vgdb-shadow-registers=no|yes [default: no]

    激活時,gdbserver會將Valgrind影子寄存器公開到GDB。這樣,可以使用GDB檢查或更改Valgrind影子寄存器的值。隱藏影子寄存器僅適用于GDB 7.1或更高版本。

    --vgdb-prefix=<prefix> [default: /tmp/vgdb-pipe]

    要與gdb / vgdb通信,Valgrind gdbserver會創(chuàng)建3個文件(2個命名的FIFO和一個mmap共享內存文件)。prefix選項控制創(chuàng)建這些文件的目錄和前綴。

    --run-libc-freeres=<yes|no> [default: yes]

    此選項僅在Linux上運行Valgrind時才有用。

    libc.so所有程序使用的GNU C庫()可能會為自己的用途分配內存。通常,當程序結束時,它不會釋放內存,因為Linux內核在進程退出時會回收所有進程資源,所以它只會減慢速度。

    glibc作者意識到,當出口檢查完成時,這種行為會導致漏洞檢查器(如Valgrind)錯誤地報告glibc中的泄漏。為了避免這種情況,他們提供了一個__libc_freeres?專門用于使glibc釋放其分配的所有內存的例程。因此,Memcheck嘗試__libc_freeres在退出時運行?。

    不幸的是,在一些很舊的glibc版本中,?__libc_freeres足夠錯誤的引起分段錯誤。這在Red Hat 7.1中尤其明顯。所以這個選項是為了禁止運行而提供的?__libc_freeres。如果您的程序似乎在Valgrind上運行良好,但是在出口處出現(xiàn)segfaults,您可能會發(fā)現(xiàn)?--run-libc-freeres=no修復盡管可能會錯誤地報告空間漏洞?libc.so。

    --run-cxx-freeres=<yes|no> [default: yes]

    此選項僅在運行Linux或Solaris C ++程序上的Valgrind時才有用。

    libstdc++.so由g ++編譯的所有C ++程序使用的GNU標準C ++庫()可能會為自己的用途分配內存。通常,當程序結束時,它不會釋放內存,因為內核在進程退出時會回收所有進程資源,所以它只會減慢速度。

    gcc作者意識到,當在出口處進行泄漏檢查時,此行為會導致漏洞檢查器(如Valgrind)在libstdc ++中錯誤地報告泄漏。為了避免這種情況,他們提供了一個__gnu_cxx::__freeres?專門用于使libstdc ++釋放其已分配的所有內存的例程。因此,Memcheck嘗試__gnu_cxx::__freeres在退出時運行?。

    為了靈活性和不可預見的問題?__gnu_cxx::__freeres,選擇?--run-cxx-freeres=no存在,盡管可能錯誤地報告空間泄漏?libstdc++.so。

    --sim-hints=hint1,hint2,...

    通過Valgrind的其他提示,以非標準或危險的方式稍微修改模擬行為,可能有助于模擬奇怪的功能。默認情況下不啟用任何提示。謹慎使用!目前已知的提示有:

    • lax-ioctls:?對于ioctl處理非常松懈;?唯一的假設是大小是正確的。寫入時不需要初始化完整的緩沖區(qū)。沒有這個,使用一些設備驅動程序與大量的奇怪的ioctl命令變得非常麻煩。

    • fuse-compatible:?對可能在FUSE文件系統(tǒng)中阻塞的某些系統(tǒng)調用啟用特殊處理。在使用一個線程來管理FUSE文件系統(tǒng)的多線程程序上運行Valgrind并且另一個線程訪問該文件系統(tǒng)時,這可能是必需的。

    • enable-outer:?當運行程序本身是Valgrind時,啟用了一些特殊的魔法。

    • no-inner-prefix:?禁止>在外部Valgrind運行的內部Valgrind中,在每個stdout或stderr輸出行前面打印前綴。當在外部/內部設置中運行Valgrind回歸測試時,這是非常有用的。請注意,前綴>將始終打印在內部調試日志記錄行的前面。

    • no-nptl-pthread-stackcache:?這個提示僅在Linux上運行Valgrind時才有用。

      libpthread.sopthread程序使用的GNU glibc pthread庫()維護一個pthread棧緩存。當pthread終止時,用于pthread棧的內存和一些線程本地存儲相關數(shù)據(jù)結構并不總是直接釋放。這個內存被保存在高速緩存中(達到一定的大小),如果啟動了一個新的線程,那么這個內存被重新使用。

      這個緩存導致helgrind工具在這個緩存的內存上報告一些錯誤的正面競爭條件錯誤,因為helgrind不了解內部glibc緩存同步原語。所以,當使用helgrind時,禁用緩存有助于避免錯誤的正面競爭條件,特別是當使用線程本地存儲變量(例如使用?__thread限定符的變量)時。

      當使用memcheck工具時,禁用高速緩存可確保glibc處理__thread變量所使用的內存在線程終止時直接釋放。

      注意:Valgrind使用glibc堆棧緩存實現(xiàn)的一些內部知識以及檢查pthread庫的調試信息來禁用緩存。因此,這種技術有些脆弱,并且可能對所有glibc版本都無效。這已經在各種平臺上通過各種glibc版本(例如2.11,2.16,2.18)成功測試。

    • lax-doors:?(僅限Solaris)對于無法識別的門文件描述符,關于門系統(tǒng)調用處理非常松懈。不需要在寫入時初始化完整的緩沖區(qū)。沒有這一點,使用具有完全專有語義的libdoor(3LIB)功能的程序可能會報告大量的誤報。

    --fair-sched=<no|yes|try> [default: no]

    該--fair-sched選項控制Valgrind使用的鎖定機制來串行線程執(zhí)行。鎖定機制控制線程的安排方式,不同的設置在公平性和性能之間進行不同的權衡。有關Valgrind線程序列化方案及其對性能和線程調度的影響的更多詳細信息,請參閱?計劃和多線程性能。

    • 該值--fair-sched=yes?激活公平的調度程序。簡而言之,如果多個線程準備運行,線程將以輪循方式進行安排。該機制在所有平臺或Linux版本上都不可用。如果不可用,則使用--fair-sched=yes會導致Valgrind終止并出現(xiàn)錯誤。

      如果您在Valgrind上運行交互式多線程程序(例如Web瀏覽器),則可能會發(fā)現(xiàn)此設置會提高整體響應能力。

    • 該值--fair-sched=try?激活公平調度(如果在平臺上可用)。否則會自動回退--fair-sched=no。

    • 該值--fair-sched=no激活一個不能保證線程準備運行的線程之間的公平性,但通常給出最高性能的調度器。

    --kernel-variant=variant1,variant2,...

    處理來自該平臺的默認內核的較小變體的系統(tǒng)調用和ioctl。這對于在黑客內核上運行或者支持非標準ioctl的內核模塊非常有用。謹慎使用。如果你不明白這個選項是什么,那么你幾乎肯定不需要它。目前已知的變體是:

    • bproc:支持sys_brocx86上的?系統(tǒng)調用。這是用于在BProc上運行的,它是標準Linux的一小部分變體,有時用于構建集群。

    • android-no-hw-tls:ARM版Android模擬器的一些版本不提供硬件TLS(線程本地狀態(tài))寄存器,Valgrind在啟動時崩潰。使用此變體選擇TLS的軟件支持。

    • android-gpu-sgx5xx:使用它來支持在Android設備上處理PowerVR SGX 5XX系列GPU的專有ioctl。未選擇此項不會導致穩(wěn)定性問題,但可能會導致Memcheck在程序執(zhí)行GPU特定的ioctl之后報告錯誤的錯誤。

    • android-gpu-adreno3xx:同樣地,使用它來支持在Android設備上處理高通Adreno 3XX系列GPU的專有ioctl。

    --merge-recursive-frames=<number> [default: 0]

    一些遞歸算法,例如平衡二叉樹實現(xiàn),創(chuàng)建許多不同的堆棧跟蹤,每個包含循環(huán)的調用。一個周期被定義為由零個或多個其他程序計數(shù)器值分隔的兩個相同的程序計數(shù)器值。然后,Valgrind可能會使用大量內存來存儲所有這些堆棧跟蹤。考慮到這種堆棧跟蹤包含重復的不感興趣的遞歸調用而不是更有趣的信息,例如已經發(fā)起遞歸調用的函數(shù),這是一個很差的內存使用。

    該選項--merge-recursive-frames=<number>?指示Valgrind檢測并合并大小最多為<number>?幀的遞歸調用循環(huán)。當檢測到這樣的循環(huán)時,Valgrind將堆棧跟蹤中的循環(huán)記錄為唯一的程序計數(shù)器。

    值0(默認值)不會導致遞歸調用合并。值為1將導致簡單遞歸算法(例如,階乘實現(xiàn))的堆棧跟蹤被折疊。通常需要2的值來折疊由遞歸算法(如二叉樹,快速排序等)等產生的堆棧跟蹤。更復雜的遞歸算法可能需要更高的值。

    注意:通過分析程序計數(shù)器值來檢測遞歸調用。通過查看函數(shù)名稱來檢測它們。

    --num-transtab-sectors=<number> [default: 6 for Android platforms, 16 for all others]

    Valgrind以小碎片(基本塊)翻譯和調整程序的機器代碼。翻譯存儲在翻譯高速緩存中,該高速緩存分為多個部分(扇區(qū))。如果緩存已滿,則包含最舊的翻譯的扇區(qū)將被清空并重新使用。如果需要這些舊的翻譯,Valgrind必須重新翻譯和重新設備相應的機器代碼,這是昂貴的。如果程序的“執(zhí)行指令”工作集很大,則通過減少所需的翻譯次數(shù),增加扇區(qū)數(shù)量可以提高性能。部門按需分配。一旦分配,一個部門永遠不會被釋放,并占據(jù)相當大的空間,--avg-transtab-entry-size?取決于工具和值(Memcheck每個扇區(qū)大約40 MB)。使用選項--stats=yes來獲取有關部門使用的內存以及部門分配和回收的準確信息。

    --avg-transtab-entry-size=<number> [default: 0, meaning use tool provided default]

    翻譯基本塊的平均大小。該平均尺寸用于確定扇區(qū)的大小。每個工具提供要使用的默認值。如果此默認值太小,則翻譯扇區(qū)將變得過快。如果此默認值太大,則翻譯部分內存的很大一部分將不被使用。請注意,基本塊平移的平均大小取決于工具,并且可能取決于工具選項。例如,memcheck選項--track-origins=yes?增加了基本塊轉換的大小。使用--avg-transtab-entry-size調整扇區(qū)的大小,既可以獲取內存或避免過多的重譯。

    --aspace-minaddr=<address> [default: depends on the platform]

    為了避免與某些系統(tǒng)庫的潛在沖突,Valgrind不會使用下面的地址空間--aspace-minaddr值,保留它,以防庫中特別要求該區(qū)域內存。所以根據(jù)平臺,Valgrind猜測到一些“悲觀”的價值。在Linux上,默認情況下,Valgrind避免使用第一個64MB,即使這個完整區(qū)域通常沒有沖突。您可以使用該選項--aspace-minaddr使您的內存饑餓應用程序從更多的這種較低的內存中受益。另一方面,如果遇到沖突,增加aspace-minaddr值可能會解決它。沖突通常會在地址空間較低的范圍內出現(xiàn)mmap故障。address提供的頁面必須對齊,并且必須等于或大于0x1000(4KB)。要在平臺上找到默認值,請執(zhí)行以下操作?valgrind -d -d date 2>&1 | grep -i minaddr。已知低于0x10000(64KB)的值會在某些分布上產生問題。

    --valgrind-stacksize=<number> [default: 1MB]

    對于每個線程,Valgrind需要自己的“私有”堆棧。這些堆棧的默認大小在很大程度上是大小尺寸的,因此在大多數(shù)情況下應該是足夠的。如果尺寸太小,Valgrind將會發(fā)生故障。在分裂之前,Valgrind可能在接近極限時發(fā)出警告。

    --valgrind-stacksize如果產生這樣的(不太可能)警告,或者由于分段違規(guī)導致Valgrind死亡,?請使用該選項。在分離大量C ++符號時已經看到這種分段違例。

    如果您的應用程序使用許多線程并需要大量內存,您可以通過使用該選項減小這些Valgrind堆棧的大小來獲得一些內存--valgrind-stacksize。

    --show-emwarns=<yes|no> [default: no]

    啟用后,Valgrind在某些??情況下會發(fā)出關于CPU仿真的警告。這些通常不是有趣的。

    --require-text-symbol=:sonamepatt:fnnamepatt

    當soname匹配的共享對象sonamepatt加載到進程中時,檢查其導出的所有文本符號。如果沒有匹配fnnamepatt,打印錯誤信息并放棄運行。這使得有可能確保運行不會繼續(xù),除非給定的共享對象包含特定的函數(shù)名稱。

    雙方sonamepatt并?fnnamepatt可以用通常的寫入??和*通配符。例如:":*libc.so*:foo?bar"。您可以使用冒號以外的字符分隔兩個模式。第一個字符和分隔符相同只是重要的。例如,上面的例子也可以寫成"Q*libc.so*Qfoo?bar"。?--require-text-symbol允許多個標志,在這種情況下,將檢查加載到進程中的共享對象。

    其目的是支持可靠使用已標記的庫。例如,假設我們有一個GCC的版本,?libgomp.so其中已經標注了注釋以支持Helgrind。將錯誤的,未注釋的加載到應用程序中是太容易和混亂了?libgomp.so。所以這個想法是:例如在標記的庫中添加一個文本符號annotated_for_helgrind_3_6,然后給出標志?--require-text-symbol=:*libgomp*so*:annotated_for_helgrind_3_6?,以便libgomp.so加載時,Valgrind掃描其符號表,如果符號不存在,則運行中止,而不是與未標記的圖書館保持沉默。請注意,您應該將整個標記放在引號中,以阻止擴展*?和?通配符的擴展。

    --soname-synonyms=syn1=pattern1,syn2=pattern2,...

    加載共享庫時,Valgrind會檢查庫中必須更換或包裝的函數(shù)。例如,Memcheck用自己的版本替換一些字符串和內存函數(shù)(strchr,strlen,strcpy,memchr,memcpy,memmove等)。這樣的替換通常僅在共享庫中進行,其共享庫的soname匹配預定義的soname模式(例如?libc.so*在linux上)。默認情況下,除了分配函數(shù)(malloc,free,calloc,memalign,realloc,operator new,operator delete等)之外,靜態(tài)鏈接二進制或替代庫不進行替換。默認情況下,這種分配函數(shù)被截取任何共享庫或可執(zhí)行文件,如果它們被導出為全局符號。?這意味著如果找到替換分配庫(如tcmalloc),則默認情況下也會攔截其函數(shù)。--soname-synonyms在某些情況下,替換可以指定一個額外的同義詞模式,從而給予更換的靈活性。或防止截取所有公共分配符號。

    目前,這種靈活性只允許使用同義詞的malloc相關功能somalloc。這個同義詞可用于執(zhí)行malloc相關功能的標準替換的所有工具(例如memcheck,massif,drd,helgrind,exp-dhat,exp-sgcheck)。

    • 替代的malloc庫:使用soname?mymalloclib.so(而不是任何其他)替換特定備用庫中的malloc相關函數(shù),給出選項--soname-synonyms=somalloc=mymalloclib.so。可以使用一個模式來匹配多個庫的聲名。例如,--soname-synonyms=somalloc=*tcmalloc*?將匹配tcmalloc庫(native,debug,profiled,... tcmalloc變體)的所有變體的soname。

      注意:可以使用readelf實用程序檢索elf共享庫的soname。

    • 靜態(tài)鏈接庫中的替換是通過使用NONE模式來完成的。例如,如果您鏈??接libtcmalloc.a,并且只想攔截可執(zhí)行文件(和標準庫)本身的malloc相關函數(shù),而不是任何其他共享庫,則可以給出該選項--soname-synonyms=somalloc=NONE。請注意,NONE模式將匹配主可執(zhí)行文件和任何沒有soname的共享庫。

    • 要運行用于Linux的“默認”Firefox版本,其中JEMalloc鏈接到主可執(zhí)行文件,請使用--soname-synonyms=somalloc=NONE。

    • 為了僅攔截默認系統(tǒng)庫中的分配符號,但不能在任何其他共享庫或定義public malloc或operator new相關函數(shù)的可執(zhí)行文件中使用不存在的庫名稱--soname-synonyms=somalloc=nouserintercepts?(如果nouserintercepts可以是任何不存在的庫名稱)。

    • 搜索動態(tài)(運行時)鏈接器的共享庫被排除在搜索全局公共符號之外,如malloc相關函數(shù)(由somalloc同義詞標識)。

    2.6.6。調試選項

    還有一些用于調試Valgrind本身的選項。你不應該在正常的事情中使用它們。如果您希望看到列表,請使用該?--help-debug選項。

    如果你想調試你的程序,而不是調試Valgrind本身,那么你應該使用選項?--vgdb=yes或--vgdb=full。

    2.6.7。設置默認選項

    請注意,Valgrind還從三個地方讀取選項:

  • 文件?~/.valgrindrc

  • 環(huán)境變量?$VALGRIND_OPTS

  • 文件?./.valgrindrc

  • 這些在命令行選項之前以給定的順序進行處理。稍后處理的選項將覆蓋之前處理的選項;?例如,選項?./.valgrindrc將優(yōu)先于那些?~/.valgrindrc。

    請注意,如果./.valgrindrc?文件被標記為當前用戶可以寫入或不擁有,則該文件將被忽略。這是因為?./.valgrindrc可能包含潛在有害的選項,或者本地攻擊者可以使用該選項來執(zhí)行用戶帳戶下的代碼。

    任何放入工具的選項?$VALGRIND_OPTS或?.valgrindrc文件都應該加上工具名稱和冒號。例如,如果要讓Memcheck始終進行泄漏檢查,可以將以下條目放入~/.valgrindrc:

    --memcheck:泄漏檢查= YES

    如果運行Memcheck以外的任何工具,這將被忽略。沒有這個memcheck:?部分,如果選擇其他不了解的工具,這將導致問題?--leak-check=yes。

    2.7。支持線程

    線程程序得到完全支持。

    關于線程程序的主要內容是,您的程序將使用本機線程庫,但是Valgrind可以串行化執(zhí)行,以便一次只運行一個(內核)線程。這種方法避免了實施Valgrind的真正多線程版本的可怕實現(xiàn)問題,但這意味著即使有多處理器或多核機器,線程應用程序也不會同時使用多個CPU。

    Valgrind沒有安排線程本身。它只是確保只有一個線程一次運行,使用簡單的鎖定方案。實際的線程調度仍然受OS內核的控制。這是什么意思,但是,您的程序將看到非常不同的調度,當運行在Valgrind比正常運行時。這是因為Valgrind串行化線程,并且因為代碼運行速度比正常慢。

    如果您有某種并發(fā),嚴重的競爭,鎖定或類似的錯誤,那么調度的差異可能會導致程序的行為不同。在這種情況下,您可以考慮使用Helgrind和/或DRD工具來跟蹤它們。

    在Linux上,Valgrind還支持直接使用?clone系統(tǒng)調用,?futex等等。?clone支持任何一個共享(一個線程)或者沒有共享(fork-like);?部分分享將失敗。

    2.7.1。調度和多線程性能

    只有當線程保持上述鎖時,線程才執(zhí)行代碼。執(zhí)行一些指令后,正在運行的線程將釋放鎖。準備運行的所有線程將會競爭獲取鎖。

    該--fair-sched選項控制用于序列化線程執(zhí)行的鎖定機制。

    默認的基于管道的鎖定機制(--fair-sched=no)可在所有平臺上使用。基于管道的鎖定不能保證線程之間的公平性:剛剛釋放鎖的線程很可能立即重新獲取,即使其他線程已準備好運行。當使用基于管道的鎖定時,相同多線程應用程序的不同運行可能給出非常不同的線程調度。

    在一些平臺上可以使用基于futexes的替代鎖定機制。如果有的話,它被激活--fair-sched=yes或?--fair-sched=try。基于Futex的鎖定確保線程之間的公平性(循環(huán)調度):如果多個線程準備運行,則鎖將被提供給首先請求鎖定的線程。請注意,系統(tǒng)調用中阻塞的線程(例如,阻塞讀取系統(tǒng)調用)尚未請求鎖定:只有系統(tǒng)調用完成后,該線程才會請求該鎖。

    基于futex的鎖定的公平性為多線程應用程序的不同執(zhí)行提供了線程調度的更好的重現(xiàn)性。使用Helgrind或DRD時,這種更好的再現(xiàn)性特別有用。

    Valgrind使用線程序列化意味著一次只能運行一個線程。在多處理器/多核系統(tǒng)上,運行的線程由OS內核調度程序分配給其中一個CPU。當一個線程獲取鎖定時,有時線程將被分配給剛剛釋放鎖的線程的同一個CPU。有時,線程將被分配給另一個CPU。當使用基于管道的鎖定時,剛剛獲取鎖的線程通常將被調度在與剛釋放鎖的線程相同的CPU上。使用基于futex的機制,剛獲取鎖的線程將更頻繁地在另一個CPU上調度。

    由OS內核調度程序進行的Valgrind的線程序列化和CPU分配可以與許多現(xiàn)代CPU上可用的CPU頻率擴展進行嚴重的交互。為了降低功耗,如果最近沒有使用CPU /內核,則CPU或內核的頻率會自動降低。如果操作系統(tǒng)內核經常將剛剛獲得鎖定的線程分配給另一個CPU /內核,那么這個CPU /核心很可能當前處于低頻率。這個CPU的頻率會在一段時間后增加。但是,在這段時間內,(只)運行的線程將以低頻運行。一旦這個線程運行了一段時間,它將釋放鎖。另一個線程將獲取此鎖,并可能會在另一個CPU的時鐘頻率降低的同時進行調度。

    基于futex的鎖定會導致線程更頻繁地更改CPU /內核。因此,如果CPU頻率縮放被激活,則基于futex的鎖定可能會顯著降低在Valgrind下運行的多線程應用程序的性能。與在CPU頻率縮放已停用的機器上運行相比,已經觀察到高達50%的性能損失。基于管道的鎖定鎖定方案也與CPU頻率縮放相關,性能損失在10..20%的范圍內。

    為了避免這種性能下降,您應該向內核指出所有CPU /內核應始終以最大時鐘速度運行。根據(jù)您的Linux發(fā)行版,可以使用圖形界面或使用諸如cpufreq-selector或?之類的命令行來控制CPU頻率縮放?cpufreq-set。

    避免這些問題的另一種方法是告訴操作系統(tǒng)調度程序使用taskset命令將Valgrind進程與特定(固定)CPU綁定?。只要程序的任何線程都有工作,這樣就可以確保所選擇的CPU不會低于其最大頻率設置。

    2.8。處理信號

    Valgrind有一個相當完整的信號實現(xiàn)。它應該能夠應付符合POSIX標準的信號使用。

    如果您以聰明的方式使用信號(例如,捕獲SIGSEGV,修改頁面狀態(tài)并重新啟動指令),則可能依賴于精確的異常。在這種情況下,您將需要使用--vex-iropt-register-updates=allregs-at-mem-access?或--vex-iropt-register-updates=allregs-at-each-insn。

    如果您的程序由于致命的核心轉儲信號而死亡,Valgrind將生成自己的vgcore.NNNNN包含程序狀態(tài)的核心文件()。您可以將此核心文件用于GDB或類似的驗證后調試。(注意:如果您的核心轉儲大小限制為0,則不會生成內核)。在編寫核心轉儲時,不包括所有浮點寄存器信息。

    在不太可能的情況下,Valgrind本身崩潰,操作系統(tǒng)將以通常的方式創(chuàng)建一個核心轉儲。

    2.9。建筑和安裝Valgrind

    我們使用標準的Unix?./configure,?make,make install機制。一旦完成,?make install您可能需要運行回歸測試make regtest。

    除了通常情況?--prefix=/path/to/install/tree,還有三個選項影響了Valgrind的構建方式:

    • --enable-inner

      這使得Valgrind成為一些特殊的魔法黑客,可以在標準版本的Valgrind(開發(fā)者稱之為“自主托管”)上運行它。通常您不應使用此選項,因為各種安全檢查被禁用。

    • --enable-only64bit

      --enable-only32bit

      在64位平臺(amd64-linux,ppc64-linux,amd64-darwin)上,默認情況下,Valgrind內置了32位和64位可執(zhí)行文件的運行方式。有時這個聰明才是一個問題,原因有很多。在這種情況下,這兩個選項允許單目標構建。如果同時發(fā)出這兩個,配置腳本將會抱怨。請注意,它們僅在32位平臺(x86-linux,ppc32-linux,arm-linux,x86-darwin)上被忽略。

    該configure腳本測試目前由當前指示的X服務器的版本?$DISPLAY。這是一個已知的錯誤。目的是檢測當前X客戶端庫的版本,以便可以為它們選擇正確的抑制,而是測試檢查服務器版本。這只是錯誤的。

    如果您正在構建一個二進制包Valgrind進行發(fā)行,請閱讀README_PACKAGERS?Readme Packagers。它包含一些重要信息。

    除此之外,這里沒有什么興奮。如果您有建立問題,請告訴我們。

    2.10。如果你有問題

    請聯(lián)系我們http://www.valgrind.org/。

    請參閱限制為Valgrind的的已知的限制,而對于已知不進行這項工作的程序列表。

    系統(tǒng)的所有部分大量使用斷言和內部自檢。它們被永久啟用,我們沒有計劃禁用它們。如果其中一個休息,請郵寄給我們!

    如果您發(fā)現(xiàn)斷言失敗m_mallocfree.c,這可能是因為您的程序注銷堆塊的末尾,或在其開始之前,從而破壞了堆元數(shù)據(jù)。Valgrind希望在這樣做之前就會發(fā)出這樣的消息。

    閱讀Valgrind常見問題解答,了解有關常見問題,崩潰等的更多建議。

    2.11。限制

    以下列出的限制似乎很長。然而,大多數(shù)程序實際上正常工作。

    Valgrind將在受支持的平臺上運行程序,但受到以下限制:

    • 在Linux上,Valgrind在啟動時使用RLIMIT_DATA rlim_cur確定“brk段”的大小,最小為1 MB,最大為8 MB。每次程序嘗試將brk段擴展到啟動時確定的大小時,Valgrind將輸出一條消息。大多數(shù)程序可以正常運行這個限制,通常是通過切換到使用mmap來獲得更多的內存。如果您的程序真的需要一個大的brk段,則必須更改8 MB的硬編碼限制并重新編譯Valgrind。

    • 在x86和amd64上,不支持3DNow!說明。如果翻譯者遇到這種情況,Valgrind將在執(zhí)行指令時產生一個SIGILL。除此之外,在x86和amd64上,基本上所有的指令都支持,包括64位模式下的AVX和AES,以及32位模式下的SSSE3。實際上,32位模式支持在32位目標上在MacOSX 10.6上運行程序所需的最小SSE4指令。

    • 在ppc32和ppc64上,幾乎支持所有的整數(shù),浮點和Altivec指令。具體來說:PowerPC強制的整數(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媒體支持相當完整。

    • 如果您的程序執(zhí)行自己的內存管理,而不是使用malloc / new / free / delete,它仍然可以工作,但是Memcheck的錯誤檢查將不會那么有效。如果您使用“客戶端請求”描述程序的內存管理方案(請參閱?客戶端請求機制),Memcheck可以做得更好。然而,使用malloc / new和free / delete仍然是最好的方法。

    • Valgrind的信號模擬并不像現(xiàn)在那樣強大。提供基本的POSIX兼容的sigaction和sigprocmask功能,但可以想象,如果您使用信號做奇怪的事情,事情可能會非常糟糕。解決方法:不要。在任何情況下,執(zhí)行非POSIX信號技巧的程序在本質上是不可移植的,所以如果可能的話應該避免。

    • 機器指令和系統(tǒng)調用已經按需實現(xiàn)。所以盡管不太可能,但有可能這樣一個消息可能會導致程序崩潰。如果發(fā)生這種情況,請報告打印出的所有詳細信息,以便我們嘗試并實施缺少的功能。

    • 在Valgrind的Memcheck工具下運行時,程序的內存消耗量會大大增加。這是由于幕后維護的管理信息大量。另一個原因是Valgrind動態(tài)翻譯原始的可執(zhí)行文件。翻譯的測試代碼是原始代碼的12-18倍,因此您可以在運行(例如)網絡瀏覽器時輕松獲得150+ MB的翻譯。

    • Valgrind可以處理動態(tài)生成的代碼。如果您在舊代碼(即相同的內存地址)上重新生成代碼,則如果代碼位于堆棧上,Valgrind將會實現(xiàn)代碼已更改,并正常工作。這是必要的,以處理GCC用于實現(xiàn)嵌套函數(shù)的蹦床。如果您重新生成堆棧以外的其他地方的代碼,并且運行在32位或64位x86 CPU上,則需要使用該--smc-check=all選項,而Valgrind的運行速度要比正常運行的要慢。或者您可以添加客戶端請求,告訴Valgrind,當您的程序覆蓋代碼。

      在其他平臺(ARM,PowerPC)上,Valgrind觀察并尊重程序不得不發(fā)出的緩存無效提示,以通知新代碼,因此自修改代碼支持應該可以自動工作,而不需要--smc-check=all。

    • Valgrind在執(zhí)行相對于IEEE754的x86 / AMD64浮點數(shù)方面有以下限制。

      精度:不支持80位算術。在內部,Valgrind代表64位中的所有這樣的“長雙數(shù)”數(shù)字,因此結果可能會有一些差異。這是否至關重要還有待觀察。請注意,x86 / amd64 fldt / fstpt指令(讀/寫80位數(shù)字)被正確地模擬,使用/從64位轉換,所以如果有人想看到,80位數(shù)字的內存映像看起來是正確的。

      許多FP回歸測試觀察到的印象是精度差異不顯著。一般來說,如果一個程序依賴于80位精度,那么移植到只能支持64位FP精度的非x86 / amd64平臺上可能會有困難。即使在x86 / amd64上,程序可能得到不同的結果,這取決于是否編譯為使用SSE2指令(僅64位)或x87指令(80位)。最終的效果是使FP程序的行為就像在具有64位IEEE浮點數(shù)的機器上運行一樣,例如PowerPC。在amd64上,FP算法默認在SSE2上完成,所以從FP的角度看,amd64看起來更像是PowerPC而不是x86,與x86相比,顯著的精度差異要小得多。

      四舍五入:Valgrind確實遵循以下轉換的4個IEEE強制舍入模式(最接近+無窮大至-infinity,為零):float到整數(shù),整數(shù)浮動,有可能丟失精度;浮點到浮動四舍五入。對于所有其他FP操作,僅支持IEEE默認模式(round to nearest)。

      FP代碼中的數(shù)字異常:IEEE754定義了可能發(fā)生的五種類型的數(shù)字異常:無效操作(負數(shù)的sqrt等),除以零,溢出,下溢,不精確(精度損失)。

      對于每個例外,IEEE754定義了兩個行動方案:(1)可以調用用戶定義的異常處理程序,或者(2)定義了一個默認動作,“修復”并允許計算在沒有拋出異常

      目前,Valgrind僅支持默認的fixup操作。同樣,對異常支持的重要性的反饋將不勝感激。

      當Valgrind檢測到程序試圖超出任何這些限制(設置異常處理程序,舍入模式或精度控制)時,它可以打印一個消息,提供發(fā)生這種情況的回溯,并繼續(xù)執(zhí)行。此行為曾經是默認的,但是消息很煩人,因此默認情況下顯示它們已被禁用。用--show-emwarns=yes來看他們。

      上述限制精確地定義了IEEE754“默認”行為:對所有異常進行默認修復,從最近到最近的操作和64位精度。

    • 相對于IEEE754,Valgrind在執(zhí)行x86 / AMD64 SSE2 FP運算時有以下限制。

      本質上是一樣的:沒有例外,有限的遵守舍入模式。此外,SSE2具有控制位,使得它將非正規(guī)化數(shù)字視為零(DAZ)和相關動作,將數(shù)值清零(FTZ)。這兩個都導致SSE2算法的精度要低于IEEE要求。Valgrind檢測,忽略并可以警告,嘗試啟用任一模式。

    • 相對于IEEE754,Valgrind在執(zhí)行ARM VFPv3運算時有以下限制。

      本質上是一樣的:沒有例外,有限的遵守舍入模式。此外,將VFP單元切換到矢量模式將導致Valgrind中止程序 - 它無法在合理的性能級別模擬VFP的矢量使用。由于VFP指令的非標量使用在任何情況下都不推薦使用,這并不重要。

    • 相對于IEEE754,Valgrind在執(zhí)行PPC32和PPC64浮點運算時有以下限制。

      標量(非Altivec):Valgrind提供了除了“fre”和“fres”之外的所有浮點指令的比特精確仿真,它們比PowerPC架構規(guī)范要求更精確。所有浮點運算都觀察當前的舍入方式。

      但是,每次操作后都不會設置fpscr [FPRF]。這可以做到,但會產生可衡量的性能開銷,到目前為止還沒有找到它。

      在x86 / AMD64上,不支持IEEE754異常:使用默認的IEEE定義操作來處理所有浮點異常。Valgrind可以通過寫入浮點狀態(tài)和控制寄存器(fpscr)來檢測,忽略并且可以警告,嘗試取消屏蔽5種IEEE FP異常種類。

      矢量(Altivec,VMX):基本上與x86 / AMD64 SSE / SSE2一樣:沒有例外,并且有限地遵循舍入模式。對于Altivec,FP算法在IEEE / Java模式下完成,這比Linux默認設置更準確。“更準確”是指正確處理代數(shù),而不是簡單地將其清零。

    已知無法使用的程序有:

    • emacs啟動,但馬上得出結論,它是不記憶和中止。這可能是Memcheck不能提供足夠好的mallinfo功能仿真?。如果您使用標準的malloc / free例程來構建Emacs,它們會很正常。

    2.12。示例運行

    這是使用Memcheck運行一個小程序的日志。該程序實際上是正確的,報告的錯誤是GNU g ++(快照20010527)中潛在嚴重的代碼生成錯誤的結果。

    sewardj @ phoenix:?/ newmat10 $?/ Valgrind-6 / valgrind -v ./bogon == 25832 == Valgrind 0.10,x86 RedHat 7.1的內存錯誤檢測器。 == 25832 ==版權所有(C)2000-2001和GNU GPL'd,由朱利安·西瓦德。 == 25832 ==啟動,帶標志: == 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 ==對于詳細的泄漏分析,重新運行:--leak-check = yes

    海灣合作委員會在GCC 3.0發(fā)貨前大約一周內修復了這個問題。

    2.13。你可能看到的警告信息

    其中一些僅在您運行在詳細模式(啟用-v))時出現(xiàn):

    • More than 100 errors detected. Subsequent errors will still be recorded, but in less detail than before.

      經過100次不同的錯誤顯示,Valgrind對于收集這些錯誤變得更保守。然后,當決??定兩個錯誤是否相同時,它只需要前兩個堆棧幀中的程序計數(shù)器進行匹配。在此之前,前四個框架中的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再次忽略。收集更多不同的信息似乎不太可能對任何人都有實際的幫助,并且避免了Valgrind花費越來越多的時間將新的錯誤與日益增長的收藏進行比較的危險。如上所述,1000個數(shù)字是編譯時常數(shù)。

    • Warning: client switching stacks?

      Valgrind在堆棧指針中發(fā)現(xiàn)了這么大的變化,它猜測客戶端正在切換到不同的堆棧。在這一點上,它使得kludgey猜測新堆棧的基礎在哪里,并相應地設置內存權限。目前,“大變化”被定義為堆棧指針寄存器值的變化大于2000000。如果Valgrind猜測錯誤,您可能會在此之后收到許多虛假的錯誤消息和/或在堆棧跟蹤記錄代碼中發(fā)生崩潰。通過向Valgrind通知使用VALGRIND_STACK_REGISTER客戶機請求的堆棧邊界可以避免這些問題。

    • Warning: client attempted to close Valgrind's logfile fd <number>

      Valgrind不允許客戶端關閉日志文件,因為在此之后您永遠不會看到任何診斷信息。如果看到此消息,可能需要使用該?--log-fd=<number>選項來指定不同的日志文件文件描述符號。

    • Warning: noted but unhandled ioctl <number>

      Valgrind觀察到對一系列?ioctl系統(tǒng)調用的調用,但沒有修改其內存狀態(tài)信息(因為沒有人寫過合適的包裝器)。該通話仍然會通過,但是由于內存信息的不更新,您可能會在此之后收到虛假錯誤。

    • Warning: set address range perms: large range <number>

      診斷消息,主要是為了受益于Valgrind開發(fā)人員,與內存權限有關。

    總結

    以上是生活随笔為你收集整理的使用和了解Valgrind核心的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。