日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Memcheck:一个内存错误检测器

發布時間:2025/3/15 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Memcheck:一个内存错误检测器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

4.1。概觀4.2。來自Memcheck的錯誤消息說明
4.2.1。非法讀取/非法寫入錯誤4.2.2。使用未初始化的值4.2.3。在系統調用中使用未初始化或不可尋址的值4.2.4。非法釋放4.2.5。當一個堆塊被釋放不正當的解除分配功能4.2.6。重疊的源和目標塊4.2.7。有趣的參數值4.2.8。內存泄漏檢測
4.3。Memcheck命令行選項4.4。編寫抑制文件4.5。Memcheck檢查機械的詳細信息
4.5.1。有效值(V)位4.5.2。有效地址(A)位4.5.3。把它們放在一起
4.6。Memcheck監視器命令4.7。客戶端請求4.8。內存池:描述和使用自定義分配器4.9。使用Valgrind調試MPI并行程序
4.9.1。建造和安裝包裝紙4.9.2。入門4.9.3。控制包裝庫4.9.4。功能4.9.5。類型4.9.6。寫新的包裝紙4.9.7。使用包裝器時期待什么?

要使用此工具,可以--tool=memcheck?在Valgrind命令行中指定。不過,由于Memcheck是默認工具,所以您不需要。

4.1。概觀

Memcheck是一個內存錯誤檢測器。它可以檢測C和C ++程序中常見的以下問題。

  • 訪問內存您不應該,例如超越和低估堆塊,超出堆棧的頂部,以及在釋放后訪問內存。

  • 使用未定義的值,即尚未初始化的值,或已從其他未定義值導出的值。

  • 不正確的釋放堆內存,比如雙重釋放堆塊,或使用?malloc/?new/?new[]?對?free/?delete/delete[]

  • 重疊src和?dst指針?memcpy以及相關功能。

  • 將一個腥味(大概為負)值傳遞給?size一個內存分配功能的參數。

  • 內存泄漏。

像這樣的問題可能難以通過其他方式找到,經常長時間不被發現,然后導致偶爾的,難以診斷的崩潰。

4.2。來自Memcheck的錯誤消息說明

Memcheck發出一系列錯誤消息。本節將簡要介紹哪些錯誤消息的意思。錯誤檢查機械的精確行為在Memcheck檢查機械的詳細信息中有所描述。

4.2.1。非法讀取/非法寫入錯誤

例如:

大小4讀取無效在0x40F6BBCC :(在/usr/lib/libpng.so.2.1.0.9中)由0x40F6B804 :(在/usr/lib/libpng.so.2.1.0.9中)by 0x40B07FF4:read_png_image(QImageIO *)(kernel / qpngio.cpp:326)by 0x40AC751B:QImageIO :: read()(kernel / qimage.cpp:3621)地址0xBFFFF0E0不是stack'd,malloc'd或free'd

當您的程序在Memcheck認為不應該讀取或寫入內存時,會發生這種情況。在這個例子中,程序做了4個字節的地址處讀0xBFFFF0E0,內系統提供的庫libpng.so.2.1.0.9,將其從其他地方以相同的庫調用某處,從326行調用qpngio.cpp,等等上。

Memcheck嘗試確定非法地址可能涉及什么,因為這通常是有用的。所以,如果它指向一個已經被釋放的內存塊,那么你會被通知這個,而且塊被釋放。同樣,如果它應該是剛剛結束堆塊,這是數組下標中一個一個錯誤的常見結果,你會被告知這個事實,以及塊分配的地方。如果您使用--read-var-info選項Memcheck將運行更慢,但可能會更詳細地描述任何非法地址。

在這個例子中,Memcheck不能識別地址。實際上地址在堆棧上,但是由于某種原因,這不是有效的堆棧地址 - 它不在堆棧指針下面,這是不允許的。在這種特殊情況下,這可能是由GCC產生的無效代碼造成的,這是古代GCC的一個已知bug。

請注意,Memcheck僅告訴您,您的程序即將訪問非法地址的內存。它不能阻止訪問發生。所以,如果您的程序進行通常會導致分段錯誤的訪問,您的程序仍然會遇到相同的命運 - 但??是在此之前您將收到來自Memcheck的消息。在這個特定的例子中,在堆棧上讀取垃圾是非致命的,并且程序保持活著。

4.2.2。使用未初始化的值

例如:

有條件的跳躍或移動取決于未初始化的值在0x402DFA94:_IO_vfprintf(_itoa.h:49)by 0x402E8476:_IO_printf(printf.c:36)通過0x8048472:main(tests / manuel1.c:8)

當程序使用尚未初始化的值(換句話說,未定義)時,將報告未初始化值使用錯誤。這里,未定義的值用于printfC庫機械的?某處。運行以下小程序時報告此錯誤:

int main() {int x;printf(“x =%d \ n”,x); }

重要的是要了解,您的程序可以盡可能多地復制垃圾(未初始化)數據。Memcheck觀察這個并且跟蹤數據,但不會抱怨。只有當您的程序嘗試以可能影響程序外部可見行為的方式使用未初始化的數據時,才會發出投訴。在此示例中,x未初始化。Memcheck觀察到傳遞給的值_IO_printf,然后發送給_IO_vfprintf,但不發表任何評論。但是,?_IO_vfprintf必須檢查它的值,?x所以它可以把它變成相應的ASCII字符串,而在這一點Memcheck抱怨。

未初始化數據的來源往往是:

  • 程序中的局部變量尚未初始化,如上例所示。

  • 在你(或構造函數)之前的堆塊(分配給?malloc,new或類似的函數)的內容寫在那里。

要查看程序中未初始化數據源的信息,請使用該--track-origins=yes選項。這使得Memcheck運行速度更慢,但可以更容易地追蹤未初始化值錯誤的根本原因。

4.2.3。在系統調用中使用未初始化或不可尋址的值

Memcheck檢查系統調用的所有參數:

  • 它會自動檢查所有直接參數,無論它們是初始化的。

  • 此外,如果系統調用需要從程序提供的緩沖區中讀取,Memcheck會檢查整個緩沖區是否可尋址,并將其內容初始化。

  • 此外,如果系統調用需要寫入用戶提供的緩沖區,Memcheck會檢查緩沖區是否可尋址。

系統調用后,Memcheck更新其跟蹤信息,以精確反映系統調用引起的內存狀態變化。

以下是兩個無效參數的系統調用示例:

#include <stdlib.h>#include <unistd.h>int main(void){char * arr = malloc(10);int * arr2 = malloc(sizeof(int));寫(1 / * stdout * /,arr,10);出口(ARR2 [0]);}

你得到這些投訴...

Syscall param write(buf)指向未初始化的字節在0x25A48723:__write_nocancel(在/lib/tls/libc-2.3.3.so)by 0x259AFAD3:__libc_start_main(in /lib/tls/libc-2.3.3.so)由0x8048348 :(在/auto/homes/njn25/grind/head4/a.out中)地址0x25AB8028是大小為10的塊內的0個字節在0x259852B0:malloc(vg_replace_malloc.c:130)由0x80483F1:主(ac:5)Syscall param exit(error_code)包含未初始化的字節在0x25A21B44:__GI__exit(在/lib/tls/libc-2.3.3.so)通過0x8048426:main(ac:8)

因為程序具有(a)從堆塊將未初始化的垃圾寫入標準輸出,并且(b)將未初始化的值傳遞給exit。請注意,第一個錯誤是指由buf(不是?buf本身)指向的內存?,但是第二個錯誤直接指向了exit參數?arr2[0]。

4.2.4。非法釋放

例如:

無效()在0x4004FFDF:free(vg_clientmalloc.c:577)通過0x80484C7:main(tests / doublefree.c:10)地址0x3807F7B4是一個大小為177的空閑塊內的0個字節在0x4004FFDF:free(vg_clientmalloc.c:577)通過0x80484C7:main(tests / doublefree.c:10)

Memcheck使用malloc/?跟蹤程序分配的塊new,所以它可以準確地知道free/ /?的參數?delete是否合法。這里,這個測試程序已經釋放了同一個程序段兩次。與非法讀/寫錯誤一樣,Memcheck嘗試了解地址的釋放。如果在這里,地址是先前被釋放的地址,那么你會被告知 - 同一塊的重復釋放容易發現。如果您嘗試釋放不指向堆塊開始的指針,您還將收到此消息。

4.2.5。當一個堆塊被釋放不正當的解除分配功能

在以下示例中,分配的塊?new[]錯誤地被釋放?free:

free()/ delete / delete []在0x40043249:free(vg_clientfuncs.c:171)by 0x4102BB4E:QGArray ::?QGArray(void)(tools / qgarray.cpp:149)由0x4C261C41:PptDoc ::?PptDoc(void)(include / qmemarray.h:60)通過0x4C261F0E:PptXml ::?PptXml(void)(pptxml.cc:44)地址0x4BB292A8是一個大小為64個alloc'd的塊內的0個字節在0x4004318C:operator new [](unsigned int)(vg_clientfuncs.c:152)by 0x4C21BC15:KLaola :: readSBStream(int)const(klaola.cc:314)by 0x4C21C155:KLaola :: stream(KLaola :: OLENode const *)(klaola.cc:416)通過0x4C21788F:OLEFilter :: convert(QCString const&)(olefilter.cc:272)

在C++它與它是如何分配兼容的方式來釋放內存是很重要的。交易是:

  • 如果與分配?malloc,?calloc,?realloc,?valloc或者?memalign,您必須取消分配free。

  • 如果分配new,你必須解除配置delete。

  • 如果分配new[],你必須解除配置delete[]。

最糟糕的是,在Linux上顯然無論如何混合使用,但同樣的程序可能會在不同的平臺(例如Solaris)上崩潰。所以最好是妥善解決它。根據KDE的人“令人驚奇的是有多少C ++程序員不知道這個”。

要求背后的原因如下。在某些C ++實現中,delete[]必須使用分配的對象,new[]因為在指針實際返回之前,編譯器會將數組的大小和指針成員存儲到數組的內容的析構函數中。?delete不解決這個問題,會混淆,可能會破壞堆。

4.2.6。重疊的源和目標塊

下面的C庫函數從一個存儲器塊復制一些數據到另一個(或類似的東西): ,?memcpy,?strcpy,?strncpy,?。strcat?strncat由他們src和?dst指針指向的塊不允許重疊。POSIX標準具有“如果在重疊的對象之間進行復制,行為未定義”。因此,Memcheck檢查這一點。

例如:

== 27492 == memcpy中的源和目的地重疊(0xbffff294,0xbffff280,21) == 27492 == 0x40026CDC:memcpy(mc_replace_strmem.c:71) == 27492 == by 0x804865A:main(overlap.c:40)

您不希望兩個塊重疊,因為其中一個塊可能被復制部分覆蓋。

你可能會認為,Memcheck在dst小于等于?的情況下被過度迂回地報告src。例如,明顯的實現方式memcpy是從第一個字節到最后一個字節的復制。但是,某些架構的優化指南建議從最后一個字節復制到第一個。而且,復制前的一些實現memcpy為零?dst,因為歸零目的地的高速緩存行可以提高性能。

故事的道德是:如果你想寫真正的便攜式代碼,不要對語言實現做任何假設。

4.2.7。有趣的參數值

所有內存分配函數都會使用一個參數來指定應該分配的內存塊的大小。顯然,請求的大小應該是非負值,通常不會過大。例如,在64位機器上,分配請求的大小超過2 ** 63個字節是非常不起眼的。更可能的是,這樣的值是錯誤大小計算的結果,并且實際上是負值(恰好恰好出現過大,因為位模式被解釋為無符號整數)。這樣的值被稱為“腥值”。所述size的分配如下功能參數被檢查為腥:?malloc,?calloc,?realloc,?memalign,?new,?new []。?__builtin_new,?__builtin_vec_new,calloc

例如:

== 32233 ==函數malloc的參數'size'有一個腥(可能為負)的值:-3 == 32233 ==在0x4C2CFA7:malloc(vg_replace_malloc.c:298) == 32233 == 0x400555:foo(fishy.c:15) == 32233 == 0x400583:main(fishy.c:23)

在早期的Valgrind版本中,這些值被稱為“愚蠢的參數”,并且不包括后跟蹤。

4.2.8。內存泄漏檢測

Memcheck記錄所有響應于malloc/?etc的調用發出的堆塊?new。所以當程序退出時,它知道哪些塊沒有被釋放。

如果--leak-check適當設置,對于每個剩余的塊,Memcheck確定塊是否可以從根集中的指針到達。根組包括(a)所有線程的通用寄存器,以及(b)可訪問的客戶端存儲器中的初始化,對齊,指針大小的數據字,包括堆棧。

有兩種方式可以達到一個塊。第一個是使用“開始指針”,即指向塊開頭的指針。第二個是“內部指針”,即指向塊中間的指針。有幾種方式可以發現內部指針可以發生:

  • 指針本來可能是一個開始指針,并被程序故意地(或不是故意地)移動。特別是,如果您的程序使用帶標記的指針,即如果它使用指針的底部,兩位或三位,由于對齊而通常總是為零,以便存儲額外的信息,則可能會發生這種情況。

  • 這可能是內存中的隨機垃圾值,完全不相關,只是巧合。

  • 它可能是指向C ++的內部char數組的指針?std::string。例如,一些編譯器在std :: string的開頭添加3個字,以便在包含字符數組的內存之前存儲長度,容量和引用計數。他們在這3個字之后返回一個指針,指向char數組。

  • 一些代碼可能會分配一個內存塊,并使用前8個字節來存儲(塊大小-8)作為64位數。?sqlite3MemMalloc做這個。

  • 它可能是一個指向分配給C ++對象(具有析構函數)的數組的指針new[]。在這種情況下,一些編譯器在分配的塊的開始處存儲包含數組長度的“魔術cookie”,并返回一個指向剛剛過去的魔術cookie(即內部指針)的指針。有關詳細信息,請參閱此頁面。

  • 它可能是指向使用多重繼承的C ++對象的內部部分的指針。

您可以選擇激活啟發式檢漏過程中使用,以檢測對應的內部指針stdstring,?length64,?newarray?和multipleinheritance案件。如果啟發式檢測到內部指針對應于這種情況,則該塊將被認為是內部指針可達的。換句話說,內部指針將被視為起始指針。

考慮到這一點,考慮下面描述的九種可能的情況。

指針鏈AAA泄漏案BBB泄漏案------------- ------------- ------------- (1)RRR ------------> BBB DR (2)RRR ---> AAA ---> BBB DR IR (3)RRR BBB DL (4)RRR AAA ---> BBB DL IL (5)RRR ------?-----> BBB(y)DR,(n)DL (6)RRR ---> AAA - ? - > BBB DR(y)IR,(n)DL (7)RRR - → - > AAA ---> BBB(y)DR,(n)DL(y)IR,(n)IL (8)RRR-α - > AAA - → - > BBB(y)DR,(n)DL(y,y)IR,(n,y)IL,(_,n) (9)RRR AAA-β-> BBB DL(y)IL,(n)DL指針鏈傳說: - RRR:根集節點或DR塊 - AAA,BBB:堆塊 - --->:一個開始指針 - - ? - >:內部指針泄漏案例傳奇: - DR:直接可達 - IR:間接可達 - DL:直接丟失 - IL:間接丟失 - (y)XY:如果內部指針是真正的指針,則為XY - (n)XY:如果內部指針不是真正的指針,則為XY - (_)XY:在任一種情況下都是XY

每個可能的情況都可以減少到上述九個之一。Memcheck在其輸出中合并了一些這種情況,導致以下四種泄漏。

  • “仍然可達”。這涵蓋上面的1和2(對于BBB塊)的情況。找到一個起始指針或鏈的起始指針。由于塊仍然指向,程序員至少原則上可以在程序退出之前釋放它。“仍然可達”的塊是非常普遍的,可以說是不成問題的。因此,默認情況下,Memcheck不會單獨報告此類塊。

  • “絕對迷失”。這涵蓋上面的案例3(對于BBB塊)。這意味著沒有找到指向塊的指針。該塊被分類為“丟失”,因為程序員不可能在程序退出時釋放它,因為沒有指向它的指針。這可能是程序中某個較早點丟失指針的癥狀。這種情況應由程序員修正。

  • “間接失蹤”。這涵蓋上面的案例4和9(對于BBB塊)。這意味著塊丟失,而不是因為沒有指針,而是因為所有指向它的塊都是丟失的。例如,如果您有一個二叉樹并且根節點丟失,則其所有子節點將被間接丟失。因為如果導致間接泄漏的絕對丟失塊是固定的,那么問題會消失,因此默認情況下Memcheck不會單獨報告這些塊。

  • “可能丟失”。這涵蓋上面的5-8(對于BBB塊)。這意味著已經找到了一個或多個指向塊的指針的鏈,但是指針中的至少一個是內部指針。這可能只是內存中的一個隨機值,恰好指向一個塊,所以你不應該考慮這個確定,除非你知道你有內部指針。

(注:將九種可能的情況映射到四種泄漏方式不一定是報告泄漏的最佳方法;特別是內部指針被不一致地處理,將來可能會改進分類。)

此外,如果塊的存在,則無論其屬于上述四種,都將被報告為“被抑制”。

以下是泄漏匯總示例。

泄漏摘要:絕對丟失:3個塊中的48個字節。間接丟失:32個字節在2個塊。可能丟失:6個塊中的96個字節。仍然可達:64個字節在4個塊。被禁止:0個字節,0個塊。

如果使用啟發式方法來將某些塊視為可達到的,則漏洞摘要將詳細介紹每個啟發式啟發式啟發式可達的“仍可達到的”子集。在下面的例子中,95字節仍然可以達到,87字節(56 + 7 + 8 + 16)被認為是啟發式可達的。

泄漏摘要:絕對丟失:4個字節在1個塊間接丟失:0個字節,0個塊可能丟失:0個塊中的0個字節仍然可達:6個塊中有95個字節其中通過啟發式可達到:stdstring:56個字節,2個塊length64:16個字節,1個塊newarray:1個塊中有7個字節多個繼承:1個塊中8個字節被禁止:0個字節,0個塊

如果--leak-check=full指定,Memcheck將給出每個絕對丟失或可能丟失的塊的詳細信息,包括分配的位置。(實際上,它將具有相同泄漏類型的所有塊的結果和足夠相似的堆棧跟蹤合并到一個“丟失記錄”中,?--leak-resolution允許您控制“足夠相似”的含義。)它不能告訴你什么時候或如何或為什么指向一個泄漏塊的指針丟失了;?你必須為自己工作。一般來說,您應該嘗試確保您的程序在出口時沒有任何明顯的丟失或可能丟失的塊。

例如:

1塊中的8個字節在14的損失記錄中絕對丟失在0x ........:malloc(vg_replace_malloc.c:...)by 0x ........:mk(leak-tree.c:11)by 0x ........:main(leak-tree.c:39)1個塊中的88個(8個直接,80個間接)字節在14的損失記錄13中絕對丟失在0x ........:malloc(vg_replace_malloc.c:...)by 0x ........:mk(leak-tree.c:11)by 0x ........:main(leak-tree.c:25)

第一條消息描述了一個完全丟失的單個8字節塊的簡單情況。第二個例子提到另一個8字節塊已經絕對丟失了;?不同之處在于其他塊中的另外80個字節由于這個丟失塊而間接丟失。損失記錄不以任何顯著的順序呈現,因此損失記錄數字并不具體。損失記錄號可以在Valgrind gdbserver中使用,以列出泄露塊的地址和/或提供有關塊仍然可達的更多細節。

該選項--show-leak-kinds=<set>?控制一組泄漏種類以顯示何時--leak-check=full被指定。

該<set>泄漏種在下列方式之一指定的:

  • 一個或多個逗號分隔的列表?definite indirect possible reachable。

  • all?指定完整集(所有泄漏種類)。

  • none?為空集。

泄漏種類的默認值為?--show-leak-kinds=definite,possible。

還可以顯示可達和間接丟失的塊,除了絕對可能丟失的塊,您可以使用--show-leak-kinds=all。只顯示可達和間接丟失的塊,使用?--show-leak-kinds=indirect,reachable。然后可以顯示可達和間接丟失的塊,如以下兩個示例所示。

4塊中的64字節仍然可以在4的損失記錄中達到在0x ........:malloc(vg_replace_malloc.c:177)by 0x ........:mk(leak-cases.c:52)by 0x ........:main(leak-cases.c:74)2個字節中的32個字節在4的損失記錄1中間接丟失在0x ........:malloc(vg_replace_malloc.c:177)by 0x ........:mk(leak-cases.c:52)by 0x ........:main(leak-cases.c:80)

因為有不同種類的泄漏有不同的嚴重性,一個有趣的問題是:哪些泄漏應該算作真正的“錯誤”,哪些不應該?

這個問題的答案會影響打印ERROR SUMMARY在行中的數字,也影響--error-exitcode選項的效果。首先,如果指定了漏洞,則僅將其視為真實的“錯誤”?--leak-check=full。然后,該選項--errors-for-leak-kinds=<set>控制要作為錯誤考慮的一組泄漏種類。默認值為--errors-for-leak-kinds=definite,possible

4.3。Memcheck命令行選項

--leak-check=<no|summary|yes|full> [default: summary]

啟用時,在客戶端程序完成時搜索內存泄漏。如果設置summary,它說發生了多少泄漏。如果設置為full或者?yes,每個單獨的泄漏將被詳細顯示和/或計數為錯誤,如選項?--show-leak-kinds和?--errors-for-leak-kinds。

--leak-resolution=<low|med|high> [default: high]

在進行泄漏檢查時,確定Memcheck如何將不同的回溯視為相同的目的,以將多個泄漏合并到單個泄漏報告中。設置時low,只有前兩個條目需要匹配。何時med,四個條目必須匹配。何時high,所有條目都需要匹配。

對于硬核泄漏調試,您可能希望?--leak-resolution=high與--num-callers=40這些大數量一起使用?。

請注意,該--leak-resolution設置不會影響Memcheck查找泄漏的能力。它只會改變結果的呈現方式。

--show-leak-kinds=<set> [default: definite,possible]

指定泄漏檢查中顯示的泄漏種類,full?方法如下:

  • 一個或多個逗號分隔的列表?definite indirect possible reachable。

  • all指定完整集(所有泄漏種類)。相當于?--show-leak-kinds=definite,indirect,possible,reachable。

  • none?為空集。

--errors-for-leak-kinds=<set> [default: definite,possible]

指定泄漏種類作為full泄漏搜索中的錯誤?。這?<set>是相同的?--show-leak-kinds

--leak-check-heuristics=<set> [default: all]

指定在泄漏搜索期間使用的泄漏檢查啟發式集合。啟發式控制指向一個塊的內部指針使其被認為是可達到的。啟發式集合以下列方式之一指定:

  • 一個或多個逗號分隔的列表?stdstring length64 newarray multipleinheritance。

  • all激活完整的啟發式集。相當于?--leak-check-heuristics=stdstring,length64,newarray,multipleinheritance。

  • none?為空集。

--show-reachable=<yes|no>?,?--show-possibly-lost=<yes|no>

這些選項提供了一種替代方法來指定泄漏種類來顯示:

  • --show-reachable=no --show-possibly-lost=yes相當于?--show-leak-kinds=definite,possible。

  • --show-reachable=no --show-possibly-lost=no相當于?--show-leak-kinds=definite。

  • --show-reachable=yes相當于?--show-leak-kinds=all。

--undef-value-errors=<yes|no> [default: yes]

控制Memcheck報告是否使用未定義的值錯誤。no如果您不想看到未定義的值錯誤,請將其設置為?。它也有加速Memcheck的副作用。

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

控制Memcheck是否跟蹤未初始化值的來源。默認情況下,它不會,這意味著雖然可以告訴您未初始化的值正在以危險的方式使用,但它不能告訴您未初始化值的來源。這通常使得難以追溯根本問題。

設置時yes,Memcheck記錄所有未初始化值的起始位置。然后,當報告未初始化的值錯誤時,Memcheck將嘗試顯示值的原點。原點可以是以下四個位置之一:堆塊,堆棧分配,客戶端請求或其他其他來源(例如,調用brk)。

對于源自堆塊的未初始化值,Memcheck顯示塊分配的位置。對于來自堆棧分配的未初始化值,Memcheck可以告訴您分配了哪個值,但不超過該值 - 通常它會顯示函數的開始大括號的源位置。所以你應該仔細檢查所有函數的局部變量是否正確初始化。

性能開銷:原始跟蹤價格昂貴。它使Memcheck的速度減半,并將內存使用量提高至少100MB,甚至更多。然而,它可以大大減少確定未初始化價值錯誤的根本原因所需的努力,因此,盡管運行速度更慢,但通常也是程序員的生產力獲勝。

準確度:Memcheck相當準確地跟蹤起始點。為了避免非常大的空間和時間開銷,進行一些近似。盡管可能不大可能,Memcheck會報告錯誤的來源,或者無法識別任何來源。

注意組合?--track-origins=yes?并且--undef-value-errors=no是無意義的。Memcheck啟動時檢查并拒絕此組合。

--partial-loads-ok=<yes|no> [default: yes]

控制Memcheck如何從一些字節可尋址的地址處理32位,64位,128位和256位自然對齊的負載,而其他字節不可尋址。何時yes,這樣的負載不會產生地址錯誤。相反,來自非法地址的加載字節被標記為未初始化,并且以正常方式處理與合法地址相對應的字節。

當no來自部分無效地址的加載處理與完全無效地址的加載相同時:發出非法地址錯誤,并將生成的字節標記為初始化。

請注意,以這種方式行為的代碼違反ISO C / C ++標準,應被視為破壞。如果可能,這些代碼應該是固定的。

--expensive-definedness-checks=<yes|no> [default: no]

控制在檢查值的定義時,Memcheck是否應該使用更精確但更昂貴(耗時)的算法。默認設置不是這樣做,它通常就足夠了。然而,對于高度優化的代碼,valgrind有時可能會錯誤地抱怨。調用valgrind?--expensive-definedness-checks=yes?有助于提高性能成本。已經觀察到25%的運行時間降級,但額外的成本在很大程度上取決于手頭的應用。

--keep-stacktraces=alloc|free|alloc-and-free|alloc-then-free|none [default: alloc-and-free]

控制用于保持malloc'd和/或free'd塊的堆棧跟蹤。

使用alloc-then-free,在分配時間記錄堆棧跟蹤,并與塊相關聯。當塊被釋放時,記錄第二個堆棧跟蹤,這將替換分配堆棧跟蹤。因此,與此塊相關的任何“使用免費”錯誤只能顯示塊被釋放的位置的堆棧跟蹤。

對于alloc-and-free塊,存儲塊的分配和分配堆棧跟蹤。因此,“免費使用”錯誤將同時顯示,這可能會使錯誤更容易診斷。與alloc-then-free此相比,此設置稍微增加了Valgrind的內存使用,因為該塊包含兩個引用而不是一個引用。

有了alloc,只是分配棧跟蹤記錄(并報告)。隨著free,只有釋放堆棧跟蹤記錄(并報告)。這些值稍微減少了Valgrind的內存和CPU使用率。它們可以是有用的,具體取決于您正在搜索的錯誤類型以及需要分析的詳細程度。例如,如果您只對內存泄漏錯誤感興趣,則記錄分配堆棧跟蹤就足夠了。

隨著none,沒有堆棧跟蹤記錄的malloc和free操作。如果您的程序分配了許多塊和/或從許多不同的堆棧跟蹤分配/釋放,這可以顯著降低cpu和/或所需的內存。當然,與堆塊相關的錯誤將不會報告很少的細節。

請注意,一旦記錄了堆棧跟蹤,Valgrind將堆棧跟蹤保存在內存中,即使它沒有被任何塊引用。一些程序(例如,遞歸算法)可以產生大量堆棧跟蹤。如果Valgrind在這種情況下使用太多內存,可以減少選項所需的內存--keep-stacktraces?和/或使用較小的選項值--num-callers。

--freelist-vol=<number> [default: 20000000]

當客戶端程序使用free(in?C)或?delete?(C++)釋放內存時?,該內存不會立即可用于重新分配。相反,它被標記為不可訪問,并放置在自由塊的隊列中。目的是盡可能延長釋放記憶回流的時間。這增加了Memcheck在被釋放后的某個相當長的一段時間內能夠檢測到塊的無效訪問的機會。

此選項指定隊列中塊的最大總大小(以字節為單位)。默認值為二千萬字節。增加這會增加Memcheck使用的內存總量,但是可能會檢測到無效的釋放塊的使用,否則將無法檢測到。

--freelist-big-blocks=<number> [default: 1000000]

當從可用于重新分配的釋放塊的隊列中制作塊時,Memcheck優先重新循環大小或等于的大小--freelist-big-blocks。這確保了釋放大塊(特別是釋放塊大于?--freelist-vol)不會立即導致自由列表中所有(或許多)小塊的重新流通。換句話說,即使大塊被釋放,這個選項增加了發現“小”塊的懸掛指針的可能性。

設置值為0表示所有塊都按FIFO順序重新循環。

--workaround-gcc296-bugs=<yes|no> [default: no]

啟用時,假設讀取和寫入堆棧指針之外的一些小距離是由于GCC 2.96中的錯誤,并且不會報告它們。“小距離”默認為256字節。請注意,GCC 2.96是一些古老的Linux發行版(RedHat 7.X)上的默認編譯器,因此您可能需要使用此選項。不要使用它,如果你不必要,因為它可以導致真正的錯誤被忽視。一個更好的選擇是使用更新的GCC修復這個錯誤。

在32位PowerPC Linux上使用GCC 3.X或4.X時,還可能需要使用此選項。這是因為GCC生成的代碼偶爾訪問堆棧指針以下,特別是對于浮點數到整數轉換。這違反了32位PowerPC ELF規范,這并不意味著堆棧指針下方的位置可以訪問。

此選項自版本3.12已棄用,可能會從將來的版本中刪除。您應該使用它?--ignore-range-below-sp來指定應忽略的堆棧指針下方的偏移量的精確范圍。一個合適的等價物是--ignore-range-below-sp=1024-1。

--ignore-range-below-sp=<number>-<number>

這是替代不推薦使用的?--workaround-gcc296-bugs選項。指定時,會導致Memcheck不會在堆棧指針下方的指定偏移量下報告訪問錯誤。兩個偏移量必須是正十進制數,并且有些是反直覺的 - 第一個必須更大,以便將非環繞地址范圍意味著忽略。例如,要忽略堆棧指針下方8192字節的4字節訪問,請使用--ignore-range-below-sp=8192-8189。只能指定一個范圍。

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

啟用時,Memcheck使用與分配功能匹配的功能來檢查堆塊是否被釋放。也就是說,它預計free將用于刪除根據所分配的塊malloc,delete供分配的塊new,并delete[]為塊的分配new[]。如果檢測到不匹配,則報告錯誤。這通常很重要,因為在某些環境中,釋放不匹配的功能可能導致崩潰。

但是有一種情況是不能避免這種錯配。那就是當用戶提供?new/?new[]該呼叫malloc和delete/或delete[]該呼叫的實現free時,這些功能是不對稱內聯的。例如,假設delete[]是內聯的,但new[]不是。結果是Memcheck將所有delete[]呼叫視為直接呼叫free,即使程序源不包含不匹配的呼叫。

這會導致很多混亂和不相關的錯誤報告。?--show-mismatched-frees=no禁用這些檢查。盡管如此,通常不建議您禁用它們,因為您可能會錯過實際錯誤。

--ignore-ranges=0xPP-0xQQ[,0xRR-0xSS]

Memcheck的可尋址性檢查將忽略此選項中列出的任何范圍(可以指定多個范圍,以逗號分隔)。

--malloc-fill=<hexnumber>

填補了分配的塊malloc,?new等等,但不calloc與指定的字節。這在嘗試擺脫晦澀的內存損壞問題時很有用。分配的區域仍然被Memcheck視為未定義 - 此選項僅影響其內容。請注意,--malloc-fill當用作客戶端請求VALGRIND_MEMPOOL_ALLOC或VALGRIND_MALLOCLIKE_BLOCK的參數時,不會影響內存塊。

--free-fill=<hexnumber>

填充由釋放的塊free,?delete等等,與指定的字節值。這在嘗試擺脫晦澀的內存損壞問題時很有用。Memcheck仍然將被釋放的區域視為訪問無效 - 此選項僅影響其內容。請注意,--free-fill當用作客戶端請求VALGRIND_MEMPOOL_FREE或VALGRIND_FREELIKE_BLOCK的參數時,不會影響內存塊。

4.4。編寫抑制文件

抑制錯誤中描述了基本抑制格式?。

抑制型(第二行)應具有以下格式:

MEMCHECK:suppression_type

Memcheck抑制類型如下:

  • Value1,?Value2,?Value4,?Value8,?Value16,使用的1,2,4,8或16字節的值時意一個未初始化的值錯誤。

  • Cond(或其舊名稱Value0),意思是使用未初始化的CPU條件代碼。

  • Addr1,?Addr2,?Addr4,?Addr8,?Addr16,分別是1,2,4,8或16字節的存儲器訪問期間意思的地址無效。

  • Jump,意味著跳轉到不可尋址的位置錯誤。

  • Param,意味著無效的系統調用參數錯誤。

  • Free,意思是無效或不匹配的。

  • Overlap,意思是?src/?dst重疊?memcpy或相似的功能。

  • Leak,意味著內存泄漏。

Param?此時,錯誤具有強制性的額外信息行,這是違規系統調用參數的名稱。

Leak?錯誤有一個可選的額外信息行,格式如下:

匹配泄漏種:<設定>

其中<set>指定該抑制條目匹配的泄漏種類。?<set>以與選項相同的方式指定--show-leak-kinds,即以下之一:

  • 一個或多個逗號分隔的列表?definite indirect possible reachable。
  • all?指定完整集(所有泄漏種類)。
  • none?為空集。

如果此可選附加行不存在,則抑制條目將匹配所有泄漏類型。

請注意,使用創建的泄漏抑制?--gen-suppressions將包含此可選額外的行,因此可能會比您預期的更少的泄漏。您可能需要在使用生成的壓縮之前刪除該行。

其他Memcheck錯誤種類沒有額外的行。

如果您給出-v選項,Valgrind將在執行結束時打印所使用的抑制列表。對于泄漏抑制,該輸出給出與抑制相匹配的不同丟失記錄的數量,以及抑制抑制的字節數和塊數。如果運行包含多個泄漏檢查,則在每次新的泄漏檢查之前,字節和塊的數量將重置為零。請注意,不同的丟失記錄的數量不會重置為零。

在下面的示例中,在最后一次泄漏搜索中,7個塊和96個字節已被抑制,名稱為?some_leak_suppression:

--21041-- used_suppression:10 some_other_leak_suppression s.supp:14被抑制:1個塊中的12,400個字節 --21041-- used_suppression:39 some_leak_suppression s.supp:2被抑制:7個塊中的96個字節

對于ValueN和AddrN?錯誤,調用上下文的第一行是發生錯誤的函數的名稱,或者失敗的是.so包含錯誤位置的文件或可執行文件的完整路徑。對于Free錯誤,第一行是函數做的釋放(例如,名字?free,__builtin_vec_delete等等)。為Overlap錯誤,第一行是與重疊參數的函數的名稱(例如?memcpy,strcpy等)。

任何抑制的最后一部分指定需要匹配的調用上下文的其余部分。

4.5。Memcheck檢查機械的詳細信息

如果您想要詳細了解Memcheck正在檢查的內容,請閱讀本部分。

4.5.1。有效值(V)位

考慮到Memcheck實現與真實CPU相同的合成CPU是最簡單的,除了一個關鍵的細節。在實際CPU中處理,存儲和處理的數據的每一位(字面上)在合成CPU中具有相關聯的“有效值”位,其說明伴隨位是否具有合法值。在下面的討論中,該位被稱為V(有效值)位。

因此,系統中的每個字節都有一個8位,它隨處可見。例如,當CPU從存儲器加載一個字大小的項目(4字節)時,它也會從位圖中加載相應的32 V位,該位圖存儲過程'整個地址空間的V位。如果CPU應該將該值的全部或部分內容寫入不同地址的存儲器,則相關的V位將被存儲在V位位圖中。

簡而言之,系統中的每一位都有(概念上)一個關聯的V位,即使在CPU內部也隨處可見。是的,所有CPU的寄存器(整數,浮點,向量和條件寄存器)都有自己的V位向量。為了使這個工作,Memcheck使用大量的壓縮來緊密地表示V位。

復制值不會導致Memcheck檢查或報告錯誤。但是,當以可能影響程序的外部可見行為的方式使用值時,將立即檢查相關的V位。如果其中任何一個表示該值未定義(甚至部分),則會報告錯誤。

這是一個(絕對荒謬的)例子:

int i,j; int [10],b [10]; for(i = 0; i <10; i ++){j = a [i];b [i] = j; }

Memcheck不會對此發出任何抱怨,因為它僅將未初始化的值復制a[]到?b[]并且不會以影響程序行為的方式使用它們。但是,如果循環更改為:

for(i = 0; i <10; i ++){j + = a [i]; } if(j == 77) printf(“hello there \ n”);

那么Memcheck會抱怨說,?if條件取決于未初始化的值。請注意,它不會抱怨j += a[i];,因為在那個時候,未定義不是“可觀察的”。只有當printfMemcheck投訴時,必須做出是否做出您的程序的可觀察的操作的決定。

大多數低級操作(如增加)使Memcheck使用V位作為操作數來計算結果的V位。即使結果部分或全部未定義,也不會抱怨。

對定義的檢查僅發生在三個位置:當使用值來生成存儲器地址時,需要進行控制流決定時,以及檢測到系統調用時,Memcheck根據需要檢查參數的定義。

如果檢查應檢測未定義,則會發出錯誤消息。結果的值隨后被認為是明確的。否則會給出長鏈的錯誤消息。換句話說,一旦Memcheck報告了一個未定義的值錯誤,它會嘗試避免報告從相同的未定義值導出的進一步錯誤。

這聽起來過于復雜。為什么不檢查內存中的所有讀數,并抱怨如果未定義的值被加載到CPU寄存器中?那么這樣做并不好,因為完全合法的C程序通常會在內存中復制未初始化的值,我們不希望無限的抱怨。這是典型的例子。考慮一個這樣的結構:

struct S {int x; char c }; 結構S s1,s2; s1.x = 42; s1.c ='z'; s2 = s1;

要問的問題是:struct S以字節為單位多大?一個int是4個字節和?char一個字節,所以也許struct S占用5個字節?錯誤。我們所知道的所有非玩具編譯器都將struct S整合大量的單詞,在這種情況下為8個字節。不這樣做會強制編譯器生成真正令人震驚的代碼來訪問?struct S某些架構上的數組。

所以s1占用8個字節,但只有5個字節被初始化。對于作業s2 = s1,GCC生成代碼,將所有8個字節批量復制到s2?不考慮其含義。如果Memcheck從內存中簡單地檢查了值,那么每當這樣的結構賦值發生時,它就會變得啰嗦。所以上述更復雜的行為是必要的。這讓GCC復制?s1到s2它喜歡的任何方式,如果未初始化值以后要使用的警告才會發出。

4.5.2。有效地址(A)位

請注意,上一小節描述了如何建立和維護值的有效性,而無需說明程序是否具有訪問任何特定內存位置的權限。我們現在考慮后一個問題。

如上所述,存儲器或CPU中的每一位具有相關聯的有效值(V)位。此外,內存中的所有字節,但不在CPU中,都具有相關的有效地址(A)位。這表示程序是否可以合法讀取或寫入該位置。它不表示在該位置的數據的有效性 - 這是V位的工作 - 只有位置是否可被訪問。

每次程序讀或寫內存時,Memcheck會檢查與地址相關的A位。如果其中任何一個表示無效的地址,則會發出錯誤。請注意,讀寫本身不改變A位,只能查閱它們。

那么A位如何設置/清除?喜歡這個:

  • 當程序啟動時,所有的全局數據區被標記為可訪問。

  • 當程序執行?malloc/?new時,用于準確分配區域的A位,而不是更多的字節被標記為可訪問。釋放該區域后,A位被更改以指示不可訪問。

  • 堆棧指針寄存器(SP)向上或向下移動時,A位置1。規則是從SP棧到底的區域?被標記為可訪問,下面SP是不可訪問的。(如果這聽起來不合邏輯,請記住,幾乎所有的Unix系統(包括GNU / Linux),堆棧都在增長,而不是上升。)SP像這樣的跟蹤?具有一個有用的副作用,即本地功能的一部分堆棧變量等在函數輸入時自動標記可訪問,退出時無法訪問。

  • 進行系統調用時,A位被適當地改變。例如,mmap?神奇地使文件出現在進程的地址空間中,因此如果mmap?成功,必須更新A位。

  • 或者,您的程序可以使用上述客戶端請求機制明確地告訴Memcheck這些更改。

4.5.3。把它們放在一起

Memcheck的檢查機械可概括如下:

  • 存儲器中的每個字節具有8個關聯的V(有效值)位,表示該字節是否具有定義的值,以及一個A(有效地址)位,表示該程序當前是否具有讀/寫那個地址。如上所述,大量使用壓縮意味著開銷通常在25%左右。

  • 當讀取或寫入存儲器時,可以查詢相關的A位。如果它們指示無效的地址,Memcheck會發出無效的讀取或無效的寫入錯誤。

  • 當內存讀入CPU的寄存器時,相關的V位將從存儲器中讀取并存儲在模擬CPU中。沒有咨詢。

  • 當寄存器寫入存儲器時,該寄存器的V位也被寫回存儲器。

  • 當CPU寄存器中的值用于生成存儲器地址或確定條件轉移的結果時,將檢查這些值的V位,如果其中任何一個未定義,則發出錯誤。

  • 當CPU寄存器中的值用于任何其他目的時,Memcheck計算結果的V位,但不檢查它們。

  • 一旦檢查了CPU中的值的V位,就將它們設置為指示有效性。這樣可以避免長鏈錯誤。

  • 當從內存中加載值時,Memcheck會檢查該位置的A位,并在需要時發出非法地址警告。在這種情況下,加載的V位將被強制指示有效,盡管位置無效。

    這顯然奇怪的選擇減少了向用戶呈現的令人困惑的信息量。它避免了從不可尋址并包含無效值的地方讀取存儲器的不愉快現象,因此,您不僅可以獲得無效地址(讀/寫)錯誤,還可以獲得一個潛在的大量未初始化值錯誤,每次使用該值時都會出現一個錯誤。

    來自地址部分有效且部分無效的多字節加載有一個模糊的邊界情況。有關詳細信息,請參閱選項--partial-loads-ok的詳細信息。

MEMCHECK攔截來電malloc,?calloc,realloc,?valloc,memalign,?free,new,?new[],?delete和?delete[]。你得到的行為是:

  • malloc/?new/?new[]:返回存儲器被標記為可尋址的但不具有有效的值。這意味著你必須寫信才能閱讀它。

  • calloc:返回的內存標記為可尋址和有效,因為calloc將該區域清除為零。

  • realloc:如果新的大小大于舊的,新的部分可尋址但無效,如同?malloc。如果新尺寸較小,則下降部分被標記為不可尋址。你可能只傳給?realloc以前由malloc/?calloc/?發給你的指針?realloc。

  • free/?delete/?delete[]:你只能傳遞給這些函數一個指針,以前由相應的分配函數發給你。否則,Memcheck抱怨。如果指針確實有效,則Memcheck將其指向的整個區域標記為不可尋址,并將該塊置于自由塊隊列中。目的是推遲這個塊的重新分配。在這種情況下,所有嘗試訪問它將會引發無效的地址錯誤,就像您所希望的那樣。

4.6。Memcheck監視器命令

Memcheck工具提供由Valgrind內置的gdbserver?處理的監視器命令(請參閱Valgrind gdbserver的Monitor命令處理)。

  • xb <addr> [<len>]?顯示從<addr>開始的<len>(默認為1)字節的定義(V)位和值。對于每8個字節,輸出兩行。

    第一行顯示8個字節的有效位。使用兩個十六進制數字給出范圍內每個字節的定義。這些十六進制數字對相應字節的每個位的有效性進行編碼,如果定義了該位,則使用0,如果該位未定義則為1。如果一個字節不可尋址,則其有效位被__(雙下劃線)替代。

    第二行顯示低于相應有效位的字節值。用于顯示字節數據的格式與GDB命令'x / <len> xb <addr>'類似。不可尋址字節的值顯示為?(兩個問號)。

    在下面的示例中,string10是一個10個字符的數組,其中偶數字節未定義。在下面的例子中,對應的字節string10[5]是不可尋址的。

    (gdb)p&string10 $ 4 =(char(*)[10])0x804a2f0 (gdb)mo xb 0x804a2f0 10ff 00 ff 00 ff __ ff 00 0x804A2F0:0x3f 0x6e 0x3f 0x65 0x3f 0x ?? 0x3f 0x65ff 00 0x804A2F8:0x3f 0x00 地址0x804A2F0 len 10有1個字節不可尋址 (GDB)

    命令xb不能與寄存器一起使用。要獲取寄存器的有效位,您必須使用該選項啟動Valgrind?--vgdb-shadow-registers=yes。然后可以通過打印相應的“shadow 1”寄存器來獲得寄存器的有效位。在下面的x86示例中,寄存器eax具有未定義的所有位,而寄存器ebx被完全定義。

    (gdb)p / x $ eaxs1 $ 9 = 0xffffffff (gdb)p / x $ ebxs1 $ 10 = 0x0 (GDB)
  • get_vbits <addr> [<len>]?使用與xb命令相同的約定,顯示從<addr>開始的<len>(默認1)字節的定義(V)位?。get_vbits僅顯示V位(按4字節分組)。它不顯示值。如果要將V位與相應的字節值相關聯,則?xb命令將更容易使用,特別是在將未定義的整數部分與其V位值相關聯時,在小端計算機上。

    下面的示例示出的結果get_vibts?對string10在所使用的?xb?命令的解釋。

    (gdb)monitor get_vbits 0x804a2f0 10 ff00ff00 ff__ff00 ff00 地址0x804A2F0 len 10有1個字節不可尋址 (GDB)
  • make_memory [noaccess|undefined|defined|Definedifaddressable] <addr> [<len>]將<addr>中的<len>(默認為1)字節的范圍標記為具有給定狀態。參數?noaccess將范圍標記為不可訪問,所以Memcheck會報告任何訪問錯誤。?undefined或defined將該區域標記為可訪問的,但是Memcheck分別將其中的字節視為具有未定義或定義的值。?Definedifaddressable標記為已定義的范圍內的字節,這些字節已經可以被尋址,但不能改變不可尋址范圍內的字節的狀態。請注意,第一個字母Definedifaddressable?是大寫D以避免混淆defined。

    在下面的例子中,第一個字節?string10被標記為定義:

    (gdb)monitor make_memory定義0x8049e28 1 (gdb)monitor get_vbits 0x8049e28 10 0000ff00 ff00ff00 ff00 (GDB)
  • check_memory [addressable|defined] <addr> [<len>]檢查<addr>中<len>(默認為1)字節的范圍是否具有指定的可訪問性。然后輸出<addr>的描述。在以下示例中,可以使用詳細的描述,因為該選項--read-var-info=yes在Valgrind啟動時給出:

    (gdb)monitor check_memory定義0x8049e28 1 地址0x8049E28 len 1定義 == 14698 ==位置0x8049e28是string10 [0]中的0個字節, == 14698 ==在prog.c中聲明:10,在線程1的幀#0中 (GDB)
  • leak_check [full*|summary] [kinds <set>|reachable|possibleleak*|definiteleak] [heuristics heur1,heur2,...] [increased*|changed|any] [unlimited*|limited <max_loss_records_output>]?執行泄漏檢查。參數*中的參數表示默認值。

    如果[full*|summary]是?summary,則僅提供泄漏搜索的摘要;?否則將生成完整的泄漏報告。完整的泄漏報告提供了每個泄漏的詳細信息:泄漏的塊被分配的堆棧跟蹤,泄露的塊的數量及其總大小。當請求完整的報告時,接下來的兩個參數進一步指定了什么樣的泄漏報告。如果匹配第二個參數和第三個參數,則會顯示一個泄漏的詳細信息。完整的泄漏報告可能會輸出許多泄漏的詳細信息。輸出信息的nr可以使用limited隨后的最大nr個泄漏記錄輸出的參數進行控制。如果達到此最大值,則泄漏搜索將輸出最大字節數的記錄。

    該kinds參數控制了full泄漏搜索顯示哪些塊。可以使用<set>與命令行選項類似的方式指定要顯示的一組泄漏種類--show-leak-kinds。或者,該值definiteleak?相當于kinds definite,該值possibleleak相當于?kinds definite,possible:它還將顯示可能的泄漏塊,只有一個內部指針被找到。該值reachable將顯示所有塊類別(即等效于kinds all)。

    該heuristics參數控制在泄漏搜索期間使用的啟發式。可以使用<set>類似于命令行選項來指定要使用的啟發式集合--leak-check-heuristics。heuristics參數?的默認值為heuristics none。

    該[increased*|changed|any]參數控制對full泄漏搜索顯示哪些更改。該值increased指定僅顯示自上次泄漏檢查以來泄漏字節或塊數增加的塊分配堆棧。該值changed指定應顯示自上次泄漏檢查以來發生任何更改的分配堆棧。該值any指定應顯示所有泄漏條目,而不管任何增加或減少。當指定increased或changed指定時,泄漏報告條目將顯示相對于上一個泄漏報告的增量。

    以下示例顯示leak_check了在memcheck/tests/leak-cases.c回歸測試中使用?monitor命令。第一個命令輸出一個具有增加的泄漏字節的條目。第二個命令與第一個命令相同,但使用GDB和Valgrind gdbserver接受的縮寫形式。它只輸出摘要信息,因為以前的泄漏搜索沒有增加。

    (gdb)monitor leak_check full possibleleak增加 在1(+1)個塊中的== 19520 == 16(+16)個字節可能在12的損失記錄中丟失 == 19520 == at 0x40070B4:malloc(vg_replace_malloc.c:263) == 19520 == by 0x80484D5:mk(leak-cases.c:52) == 19520 == by 0x804855F:f(leak-cases.c:81) == 19520 == by 0x80488E0:main(leak-cases.c:107) == == 19520 == 19520 == LEAK SUMMARY: == 19520 ==絕對丟失:2(+0)個塊中的32(+0)個字節 == 19520 ==間接丟失:1(+0)個塊中的16(+0)個字節 == 19520 ==可能丟失:2(+1)塊中的32(+16)個字節 == 19520 ==仍然可達:6(+1)個塊中的96(+16)個字節 == 19520 == suppress:0(+0)個字節在0(+0)塊 == 19520 ==可以訪問的塊(找到指針的塊)未顯示。 == 19520 ==要查看它們,請將“可達到的任何”參數添加到leak_check == == 19520 (gdb)mo l == 19520 == LEAK SUMMARY: == 19520 ==絕對丟失:2(+0)個塊中的32(+0)個字節 == 19520 ==間接丟失:1(+0)個塊中的16(+0)個字節 == 19520 ==可能丟失:2(+0)個塊中的32(+0)個字節 == 19520 ==仍然可達:6(+0)個塊中的96(+0)個字節 == 19520 == suppress:0(+0)個字節在0(+0)塊 == 19520 ==可以訪問的塊(找到指針的塊)未顯示。 == 19520 ==要查看它們,請將“可達到的任何”參數添加到leak_check == == 19520 (GDB)

    請注意,當使用Valgrind的gdbserver時,無需重新運行--leak-check=full?--show-reachable=yes查看可訪問的塊。您可以通過使用GDB命令monitor leak_check full reachable any(或使用縮寫:)獲得相同的信息,而無需重新運行mo l f r a。

  • block_list <loss_record_nr>|<loss_record_nr_from>..<loss_record_nr_to> [unlimited*|limited <max_blocks>] [heuristics heur1,heur2,...]?顯示屬于<loss_record_nr>(或損失記錄范圍?<loss_record_nr_from>..<loss_record_nr_to>)的塊列表?。可以使用limited參數后跟最大nr個塊來輸出要打印?的塊的nr。如果給出一個或多個啟發式方法,則僅打印通過給定heur1,heur2,...?啟發式之一找到的損失記錄和塊。

    泄漏搜索將丟失記錄中的已分配塊合并:丟失記錄重新分組具有相同狀態的所有塊(例如,絕對丟失)和相同的分配回溯。每個損失記錄在泄漏搜索結果中由損失記錄號識別。該block_list命令顯示損失記錄信息,后面跟隨損失記錄中合并的塊的地址和大小。如果使用啟發式方法找到一個塊,則塊大小后面是啟發式的。

    如果直接丟失的塊導致一些其他塊間接丟失,則block_list命令還將顯示這些間接丟失的塊。根據直接丟失塊和間接丟失塊之間的間接級別,間接丟失的塊將被縮進。每個間接丟失的塊后面都是其損失記錄的引用。

    只要在這種泄漏搜索之后沒有塊被釋放,就可以使用block_list命令對泄漏搜索結果:一旦程序釋放一個塊,在再次使用block_list之前需要新的泄漏搜索。

    在下面的示例中,程序通過丟失指向塊A(樹頂部)的指針來泄漏樹結構。因此,塊A直接丟失,導致塊B到G的間接丟失。第一個block_list命令顯示A(一個絕對丟失的塊,地址為0x4028028,大小為16)的丟失記錄。塊A的間接丟失塊的地址和大小顯示在塊A的下方。第二個命令顯示第一個命令輸出的間接損失記錄之一的細節。

    一個/ \公元前/ \ / \ DEFG (gdb)bt #0 main()在leak-tree.c:69 (gdb)monitor leak_check full any == 19552 == 112(16個直接,96個間接)1個塊中的字節在7的損失記錄中絕對丟失 == 19552 ==在0x40070B4:malloc(vg_replace_malloc.c:263) == 19552 == 0x80484D5:mk(leak-tree.c:28) == 19552 == by 0x80484FC:f(leak-tree.c:41) == 19552 == by 0x8048856:main(leak-tree.c:63) == == 19552 == 19552 == LEAK SUMMARY: == 19552 ==絕對丟失:1個塊中的16個字節 == 19552 ==間接丟失:6個塊中的96個字節 == 19552 ==可能丟失:0個字節,0個塊 == 19552 ==仍然可達:0個字節,0個塊 == 19552 == suppress:0個字節,0個塊 == == 19552 (gdb)monitor block_list 7 == 19552 == 112(16個直接,96個間接)1個塊中的字節在7的損失記錄中絕對丟失 == 19552 ==在0x40070B4:malloc(vg_replace_malloc.c:263) == 19552 == 0x80484D5:mk(leak-tree.c:28) == 19552 == by 0x80484FC:f(leak-tree.c:41) == 19552 == by 0x8048856:main(leak-tree.c:63) == 19552 == 0x4028028 [16] == 19552 == 0x4028068 [16]間接損失記錄1 == 19552 == 0x40280E8 [16]間接損失記錄3 == 19552 == 0x4028128 [16]間接損失記錄4 == 19552 == 0x40280A8 [16]間接損失記錄2 == 19552 == 0x4028168 [16]間接損失記錄5 == 19552 == 0x40281A8 [16]間接損失記錄6 (gdb)mo b 2 == 19552 == 1個塊中的16個字節在7的損失記錄中間接丟失 == 19552 ==在0x40070B4:malloc(vg_replace_malloc.c:263) == 19552 == 0x80484D5:mk(leak-tree.c:28) == 19552 == by 0x8048519:f(leak-tree.c:43) == 19552 == by 0x8048856:main(leak-tree.c:63) == 19552 == 0x40280A8 [16] == 19552 == 0x4028168 [16]間接損失記錄5 == 19552 == 0x40281A8 [16]間接損失記錄6 (GDB)
  • who_points_at <addr> [<len>]?顯示找到指向addr的指針的所有位置。如果len等于1,則該命令僅顯示正好位于addr的位置(即“add指針”到addr)。如果len> 1,指示len第一個字節的“內部指針”也將顯示。

    搜索的位置與泄漏搜索中使用的位置相同。所以,who_points_at可以用來顯示為什么泄漏搜索仍然可以到達一個塊,或者可以搜索懸浮指針到一個被釋放的塊。將描述指向addr的每個位置(或指向內部addr,如果正在搜索內部指針)。

    在下面的示例中,block_list在樹被泄露之前顯示了指向“樹塊A”(參見命令中的示例)的指針。說明詳見--read-var-info=yes?Valgrind啟動時的選項。第二個調用顯示塊G的指針(起始和內部指針)。塊G(0x40281A8)可通過塊C(0x40280a8)和寄存器ECX為tid 1(tid為Valgrind線程ID)到達。通過注冊EBX“內部可達”。

    (gdb)monitor who_points_at 0x4028028 == 20852 ==搜索指向0x4028028的指針 == 20852 == * 0x8049e20分在0x4028028 == 20852 ==位置0x8049e20是全局var“t”內的0個字節 == 20852 ==在leak-tree.c中聲明:35 (gdb)monitor who_points_at 0x40281A8 16 == 20852 ==搜索從0x40281a8指向16個字節的指針 == 20852 == * 0x40280ac指向0x40281a8 == 20852 ==地址0x40280ac是一個大小為16個alloc'd的塊內的4個字節 == 20852 == 0x40070B4:malloc(vg_replace_malloc.c:263) == 20852 == 0x80484D5:mk(leak-tree.c:28) == 20852 == 0x8048519:f(leak-tree.c:43) == 20852 == by 0x8048856:main(leak-tree.c:63) == 20852 == tid 1注冊ECX分數為0x40281a8 == 20852 == tid 1注冊EBX內部點在2個字節內部0x40281a8 (GDB)

    當who_points_at找到一個內部指針時,它會報告這個內部指針被認為是可達到的啟發式的。請注意,這是獨立于該選項的值完成的--leak-check-heuristics。在下面的示例中,丟失記錄6指示可能丟失的塊。who_points_at報告指出內部指針指向該塊,并且該塊可以被認為是可以使用啟發式的multipleinheritance。

    (gdb)monitor block_list 6 == 3748 == 1個塊中的8個字節可能在7的損失記錄6中丟失 == 3748 == at 0x4007D77:operator new(unsigned int)(vg_replace_malloc.c:313) == 3748 == 0x8048954:main(leak_cpp_interior.cpp:43) == 3748 == 0x402A0E0 [8] (gdb)monitor who_points_at 0x402A0E0 8 == 3748 ==搜索指向0x402a0e0的8個字節的指針 == 3748 == * 0xbe8ee078內部點4個字節內部0x402a0e0 == 3748 ==地址0xbe8ee078在線程1的堆棧 == 3748 == block at 0x402a0e0認為可以通過ptr 0x402a0e4使用多重繼承啟發式 (GDB)

4.7。客戶端請求

下面定義了以下客戶端請求?memcheck.h。看到memcheck.h他們的參數的確切細節。

  • VALGRIND_MAKE_MEM_NOACCESS,?VALGRIND_MAKE_MEM_UNDEFINED和?VALGRIND_MAKE_MEM_DEFINED。這些標記地址范圍完全不可訪問,可訪問但包含未定義的數據,并且可訪問和包含定義的數據。在Valgrind運行時返回-1,否則返回0。

  • VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE。這就像VALGRIND_MAKE_MEM_DEFINED只是影響那些已經可尋址的字節。

  • VALGRIND_CHECK_MEM_IS_ADDRESSABLE并且?VALGRIND_CHECK_MEM_IS_DEFINED:立即檢查給定的地址范圍是否具有相關屬性,如果沒有,請打印錯誤消息。此外,為了方便客戶,如果相關屬性成立,則返回零;?否則,返回的值是屬性不為真的第一個字節的地址。在Valgrind不運行時始終返回0。

  • VALGRIND_CHECK_VALUE_IS_DEFINED:一個快速簡便的方法來查明Valgrind是否認為一個特定的值(左值,準確)是可尋址和定義的。打印錯誤信息,如果沒有。它沒有返回值。

  • VALGRIND_DO_LEAK_CHECK:現在做一個完整的內存泄漏檢查(像--leak-check=full)。這對于逐步檢查程序執行中任意位置之間的泄漏是非常有用的。它沒有返回值。

  • VALGRIND_DO_ADDED_LEAK_CHECK:與?VALGRIND_DO_LEAK_CHECK以前的泄漏搜索相同?但僅顯示泄漏字節增加或塊數泄漏的條目。它沒有返回值。

  • VALGRIND_DO_CHANGED_LEAK_CHECK:與VALGRIND_DO_LEAK_CHECK以前的泄漏搜索相同?但僅顯示泄露字節增加或減少的條目或泄漏的塊數。它沒有返回值。

  • VALGRIND_DO_QUICK_LEAK_CHECK:喜歡?VALGRIND_DO_LEAK_CHECK,除了它只產生泄漏匯總(如--leak-check=summary)。它沒有返回值。

  • VALGRIND_COUNT_LEAKS:填寫四個參數,其中先前泄漏檢查發現的內存字節數(即直接泄漏和間接泄漏的總和),可疑,可達到并被抑制。這在調用VALGRIND_DO_LEAK_CHECK或?之后的測試線索代碼中很有用VALGRIND_DO_QUICK_LEAK_CHECK。

  • VALGRIND_COUNT_LEAK_BLOCKS:?VALGRIND_COUNT_LEAKS除了它返回塊數而不是每個類別中的字節數除外。

  • VALGRIND_GET_VBITS并且?VALGRIND_SET_VBITS:允許您獲取并設置地址范圍的V(有效性)位。你應該只設置你所擁有的V位?VALGRIND_GET_VBITS。只有那些真正了解他們在做什么的人才會。

  • VALGRIND_CREATE_BLOCK和?VALGRIND_DISCARD。?VALGRIND_CREATE_BLOCK?取一個地址,一個字節和一個字符串。然后指定的地址范圍與該字符串相關聯。當Memcheck報告對該范圍內的地址的無效訪問時,它將根據該塊而不是根據其知道的任何其他塊來描述它。請注意,這個宏的使用實際上并不會以任何方式改變內存的狀態 - 它只是給出范圍的名稱。

    在某些時候,您可能希望Memcheck停止報告錯誤VALGRIND_CREATE_BLOCK。為了實現這一點,VALGRIND_CREATE_BLOCK返回一個“塊句柄”,它是一個C?int值。您可以將此塊句柄傳遞給VALGRIND_DISCARD。在這樣做之后,Valgrind將不再將指定范圍內的尋址錯誤與塊相關聯。傳遞無效手柄?VALGRIND_DISCARD是無害的。

4.8。內存池:描述和使用自定義分配器

有些程序通常使用自定義內存分配器,出于性能原因。留給自己,Memcheck無法理解自定義分配方案的行為,并且它了解標準分配器,因此可能會錯過您的程序中的錯誤和泄漏。本節描述的是一種給予Memcheck足夠的自定義分配器的描述的方法,它可以使至少有一些感覺發生了什么。

有許多不同種類的自定義分配器,所以Memcheck嘗試使用松散的抽象模型來推理它們。描述自定義分配系統時,我們使用以下術語:

  • 自定義分配涉及一組獨立的“內存池”。

  • Memcheck對內存池的概念由一個“錨地址”和一組與錨地址相關聯的非重疊“塊”組成。

  • 通常,池的錨地址是保存“標題”結構的地址。

  • 典型地,該池的塊被從通過該系統獲得的連續的“超級塊”拉伸?malloc或?mmap。

請記住,上面的最后兩點表示“通常”:Valgrind mempool客戶端請求API對于mempool的確切結構有意識地模糊。沒有具體提及標題或超級塊。然而,以下圖片可能有助于闡明API中術語的意圖:

“池子”(錨地址)|v+ -------- + --- +| 標題| o |+ -------- + - | - +|v超級塊+ ------ + --- + -------------- + --- + ------------------ +| | RZB | 分配| rzB | |+ ------ + --- + -------------- + --- + ------------------ +^ ^| |“addr”“addr”+“size”

注意,報頭和超級塊可以是連續的或不連續的,并且可能存在與單個報頭相關聯的多個超級塊;?這種變化對于Memcheck是不透明的。API只要求您的分配方案可以顯示“pool”,“addr”和“size”的合理值。

通常,在發出與mempools相關的客戶端請求之前,客戶端程序將為其mempool分配這樣的頭和超級塊,并使用VALGRIND_MAKE_MEM_NOACCESS客戶端請求標記超級塊NOACCESS?。

在處理mempools時,目標是保持一個特定的不變條件:Memcheck相信池的超級塊(包括redzones)的未分配部分是NOACCESS。為了維護這個不變量,客戶端程序必須確保超級塊在那個狀態下開始;?Memcheck不能這樣做,因為Memcheck從來沒有明確地了解一個池的超級塊,只有池中已分配的塊。

一旦池的頭和超級塊被建立并被正確標記,有許多客戶端請求程序可以用來通知Memcheck關于對mempool的狀態的改變:

  • VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed):該請求將地址pool注冊為內存池的錨地址。它還提供了一個大小rzB,指定從池分配的塊周圍放置的redzones?的大小?。最后,它提供了一個?is_zeroed參數,指定在分配時池的塊是否為零(更精確地:定義)。

    完成此請求后,不會與池相關聯。該請求簡單地告訴Memcheck池存在,以便后續調用可以將其稱為池。

  • VALGRIND_CREATE_MEMPOOL_EXT(pool, rzB, is_zeroed, flags):創建具有一些標志的內存池(可以一起OR-ed)指定擴展行為。當標志為零時,行為是相同的?VALGRIND_CREATE_MEMPOOL。

    • 該標志VALGRIND_MEMPOOL_METAPOOL?指定與使用的池相關聯的內存塊VALGRIND_MEMPOOL_ALLOC將被應用程序用作超級塊以使用MALLOC_LIKE塊VALGRIND_MALLOCLIKE_BLOCK。換句話說,元池是一個“2級”池:第一級是由...描述的塊VALGRIND_MEMPOOL_ALLOC。使用第二級塊進行描述VALGRIND_MALLOCLIKE_BLOCK。請注意,池和第二級塊之間的關聯是隱式的:第二級塊將位于第一級塊內。有必要VALGRIND_MEMPOOL_METAPOOL對這樣的2級池使用標志,否則valgrind將檢測到重疊的內存塊,并將中止執行(例如

    • VALGRIND_MEMPOOL_AUTO_FREE。這樣的元池也可以使用標志來標記為“自動免費”池,該標志VALGRIND_MEMPOOL_AUTO_FREE必須與...一起使用VALGRIND_MEMPOOL_METAPOOL。對于“自動免費”池,VALGRIND_MEMPOOL_FREE?將自動釋放第一個級別塊中包含的第二級別塊VALGRIND_MEMPOOL_FREE。換句話說,調用VALGRIND_MEMPOOL_FREE將對VALGRIND_FREELIKE_BLOCK包含在第一級塊中的所有第二級塊產生隱式調用。注意:使用VALGRIND_MEMPOOL_AUTO_FREE沒有VALGRIND_MEMPOOL_METAPOOL標志的標志?是一個錯誤。

  • VALGRIND_DESTROY_MEMPOOL(pool):此請求告訴Memcheck池已被拆除。Memcheck然后刪除與池相關聯的所有塊的記錄,以及其存儲池的記錄。在破壞其記憶的記錄的同時,Memcheck將池中任何活塊的redzones重置為NOACCESS。

  • VALGRIND_MEMPOOL_ALLOC(pool, addr, size):此請求通知Memcheck?size已經分配了一個字節塊addr,并將該組合與指定的塊相關聯?pool。如果池是用非零rzB紅色區域創建的?,Memcheck會將rzB塊之前和之后的字節標記?為NOACCESS。如果使用is_zeroed參數集創建池,Memcheck會將該塊標記為DEFINED,否則Memcheck會將該塊標記為UNDEFINED。

  • VALGRIND_MEMPOOL_FREE(pool, addr):此請求通知Memcheck,該塊addr?不應被視為已分配。Memcheck將標記與NOACCESS相關聯的塊addr,并刪除其塊的存在記錄。

  • VALGRIND_MEMPOOL_TRIM(pool, addr, size):此請求修剪與之相關聯的塊pool。該請求僅對與之相關的塊進行操作?pool。修剪正式定義為:

    • 整個范圍內的所有塊?addr..(addr+size-1)都被保留。

    • 完全超出范圍的所有塊?addr..(addr+size-1)都被丟棄,就像?VALGRIND_MEMPOOL_FREE被稱為它們一樣。

    • 所有其他塊必須與范圍相交?addr..(addr+size-1);?十字路口以外的區域被標記為“非空”,就像它們已被獨立釋放一樣?VALGRIND_MEMPOOL_FREE。

    這是一個很少見的請求,但可以在實現常規LIFO分配器中常見的無大規模操作的類型中有用。

  • VALGRIND_MOVE_MEMPOOL(poolA, poolB):此請求通知Memcheck以前錨定在地址的池poolA已移動到錨地址?poolB。這是一個罕見的請求,通常只有當您realloc的回憶標題時才需要。

    此請求不會更改內存狀態位。

  • VALGRIND_MEMPOOL_CHANGE(pool, addrA, addrB, size):該請求通知MEMCHECK先前在地址分配的組塊addrA內的?pool已被移動和/或調整大小,應加以改變,以覆蓋該區域addrB..(addrB+size-1)。這是一個罕見的請求,通常只有realloc在超級塊或希望擴展塊而不改變其內存狀態位時才需要?。

    此請求不會更改內存狀態位。

  • VALGRIND_MEMPOOL_EXISTS(pool):該請求通知呼叫者Memcheck是否正在錨定地址處追蹤回憶pool。當與該地址相關聯的mempool時,它評估為1,否則為0。這是一個罕見的請求,僅在客戶端代碼可能丟失了一組活動mempools的情況下才有用。

4.9。使用Valgrind調試MPI并行程序

Memcheck支持使用MPI消息傳遞標準的分布式內存應用程序的調試。該支持包括用于該PMPI_*接口的包裝函數庫?。當加入到應用程序的地址空間中,無論是直接鏈接或通過?LD_PRELOAD,該包裝攔截來電PMPI_Send,?PMPI_Recv等他們再使用客戶端的請求,通知所造成的功能被包裝內存狀態變化MEMCHECK。這減少了Memcheck通常為MPI應用報告的誤報數量。

包裝器還利用機會仔細檢查作為參數傳遞給MPI函數的緩沖區的大小和定義,從而檢測錯誤,例如將未定義的數據傳遞到?PMPI_Send或將數據接收到太小的緩沖區中。

與大多數其他Valgrind不同,包裝庫受BSD風格許可,因此您可以將其鏈接到任何您喜歡的代碼庫。查看mpi/libmpiwrap.c?許可證詳細信息的頂部。

4.9.1。建造和安裝包裝紙

如果可能,將自動構建包裝庫。Valgrind的配置腳本將尋找適合?mpicc于構建它。這必須與mpicc您用來構建您要調試的MPI應用程序相同。默認情況下,Valgrind嘗試?mpicc,但您可以使用configure-time選項指定一個不同的?--with-mpicc。目前,封裝器只能使用mpicc基于GNU GCC或Intel C ++編譯器的s來構建?。

檢查配置腳本是否打印如下所示的行:

檢查可用的MPI2兼容mpicc和mpi.h ...是的,mpicc

如果說... no,您的?mpicc編譯和鏈接測試MPI2程序失敗。

如果配置測試成功,繼續與通常的方式?make和make install。最后的安裝樹應該包含?libmpiwrap-<platform>.so。

匯編測試MPI程序(例如,MPI hello-world),并嘗試:

LD_PRELOAD = $ prefix / lib / valgrind / libmpiwrap- <platform> .so \mpirun [args] $ prefix / bin / valgrind ./hello

你應該看到類似于以下內容

valgrind MPI包裝紙31901:適用于pid 31901 valgrind MPI包裝器31901:嘗試MPIWRAP_DEBUG =幫助可能的選項

對于組中的每個過程重復。如果沒有看到這些,有一種構建/安裝問題。

要包裝的MPI函數被假定為具有soname匹配的ELF共享對象?libmpi.so*。至少對于Open MPI和Quadrics MPI來說,這是正確的,如果需要,可以輕松更改。

4.9.2。入門

像往常一樣編譯MPI應用程序,注意使用與mpicc您的Valgrind構建配置相同的鏈接。

使用以下基本方案在Valgrind上運行您的應用程序:

MPIWRAP_DEBUG = [wrapper-args] \LD_PRELOAD = $ prefix / lib / valgrind / libmpiwrap- <platform> .so \mpirun [mpirun-args] \$ prefix / bin / valgrind [valgrind-args] \[應用程序] [app-args]

作為一種替代?LD_PRELOADING?libmpiwrap-<platform>.so,你可以簡單地把它如果需要鏈接到您的應用程序。這不應該以任何方式打擾您的應用程序的本機行為。

4.9.3。控制包裝庫

環境變量?MPIWRAP_DEBUG在啟動時被查閱。默認行為是打印起始橫幅

valgrind MPI包裝器16386:適用于pid 16386 valgrind MPI包裝器16386:嘗試MPIWRAP_DEBUG =幫助可能的選項

然后比較安靜。

您可以在其中列出逗號分隔的選項?MPIWRAP_DEBUG。這些是

  • verbose:顯示所有包裝的條目/出口。還顯示額外的調試信息,如優秀的狀態?MPI_Request期從半拉造成MPI_Irecv秒。

  • quiet:相反verbose,當打包機想要報告檢測到的編程錯誤,或者在包裝器發生災難性故障的情況下,只打印任何東西。

  • warn:默認情況下,缺少適當的包裝器的功能沒有評論,只是默默地忽略。這將導致每個使用的展開功能打印一個警告,每個功能最多可以有三個警告。

  • strict:如果使用缺少包裝器的功能,則打印錯誤消息并中止程序。

如果要使用Valgrind的XML輸出工具(--xml=yes),您應該傳入?quiet,?MPIWRAP_DEBUG以便從包裝器中除去任何無關的打印。

4.9.4。功能

所有MPI2功能除外?MPI_Wtick,?MPI_Wtime并?MPI_Pcontrol有包裝。前兩個沒有包裝,因為它們返回一個?double,Valgrind的函數包裝機制無法處理(但是可以很容易地擴展)。?MPI_Pcontrol不可包裹,因為它具有可變特性:?int MPI_Pcontrol(const int level, ...)

大多數函數都使用一個默認的包裝器來打包,除非是根據MPIWRAP_DEBUG上面列出的設置調用,否則它不會執行任何命令,也不會中止它。以下功能具有“真實”,有用的包裝器:

PMPI_Send PMPI_Bsend PMPI_Ssend PMPI_RsendPMPI_Recv PMPI_Get_countPMPI_Isend PMPI_Ibsend PMPI_Issend PMPI_IrsendPMPI_Irecv PMPI_Wait PMPI_Waitall PMPI_Test PMPI_TestallPMPI_Iprobe PMPI_ProbePMPI_CancelPMPI_SendrecvPMPI_Type_commit PMPI_Type_freePMPI_Pack PMPI_UnpackPMPI_Bcast PMPI_Gather PMPI_Scatter PMPI_Alltoall PMPI_Reduce PMPI_Allreduce PMPI_Op_createPMPI_Comm_create PMPI_Comm_dup PMPI_Comm_free PMPI_Comm_rank PMPI_Comm_sizePMPI_Error_string PMPI_Init PMPI_Initialized PMPI_Finalize

PMPI_Address列出的?幾個功能?HAS_NO_WRAPPER。他們根本沒有包裝,因為沒有什么值得檢查,給出一個無操作的包裝器會降低性能沒有任何理由。

請注意,包裝庫本身本身可以產生大量對MPI實現的調用,特別是在步行復雜類型時。所謂的最常用的功能是?PMPI_Extent,?PMPI_Type_get_envelope,?PMPI_Type_get_contents,和?PMPI_Type_free。

4.9.5。類型

支持MPI-1.1結構化類型,并正確運行。目前支持的組合是?MPI_COMBINER_NAMED,?MPI_COMBINER_CONTIGUOUS,?MPI_COMBINER_VECTOR,?MPI_COMBINER_HVECTOR?MPI_COMBINER_INDEXED,?MPI_COMBINER_HINDEXED和?MPI_COMBINER_STRUCT。這應該涵蓋所有MPI-1.1類型。該機制(功能?walk_type)應易于擴展以覆蓋MPI2組合器。

MPI定義了一些命名結構化類型(MPI_FLOAT_INT,?MPI_DOUBLE_INT,?MPI_LONG_INT,?MPI_2INT,?MPI_SHORT_INT,?MPI_LONG_DOUBLE_INT),其是對一些基本類型和C的int。不幸的是,MPI規范使得不可能查看這些類型并查看字段在哪里。因此,這些包裝器假設類型被布置為struct { float val; int loc; }(for?MPI_FLOAT_INT)等,并且相應地進行操作。至少對于Open MPI 1.0.2和Quadrics MPI來說,這似乎是正確的。

如果strict是指定的選項MPIWRAP_DEBUG,如果遇到未處理類型,應用程序將中止。否則,應用程序將打印一條警告消息并繼續。

做了一些努力來在單次通過中標記/檢查對應于數組數組的存儲器范圍。這對于性能很重要,因為Valgrind要求標記/檢查任何范圍,無論多么小,承載相當大的恒定成本。這種優化被施加到原始類型的陣列(double,?float,?int,?long,long long,short,?char,和long double上平臺其中sizeof(long double) == 8)。對于所有其他類型的數組,包裝器單獨處理每個元素,因此可能會有非常大的性能成本。

4.9.6。寫新的包裝紙

在大多數情況下,包裝很簡單。唯一重要的復雜性是出現在非阻塞接收。

問題是MPI_Irecv?聲明recv緩沖區并立即返回,為事務提供一個handle(MPI_Request)。稍后用戶將必須輪詢完成?MPI_Wait等等,并且當事務成功完成時,包裝器必須繪制recv緩沖區。但是recv緩沖區細節沒有呈現給?MPI_Wait- 只有句柄是。因此,庫保持一個影子表,它將未完成的MPI_Requests與相應的緩沖區地址/計數/類型相關聯。操作完成后,將搜索表格中相關聯的地址/計數/類型信息,并相應地標記內存。

訪問表受到(POSIX pthreads)鎖的保護,以使庫線程安全。

該表被分配?malloc并且從不?freed,所以它將顯示在泄漏檢查中。

寫新的包裝器應該是相當容易的。源文件是?mpi/libmpiwrap.c。如果可能,找到一個與要包裝的行為類似行為的函數的現有包裝,并將其用作起點。包裝器按照與MPI 1.1規范相同的順序進行組織,以輔助導航。添加包裝器時,請記住在文件底部的長列表中注釋掉默認包裝器的定義(不要刪除它,只是將其注釋掉)。

4.9.7。使用包裝器時期待什么?

包裝器應該減少Memcheck在MPI應用程序上的錯誤錯誤率。因為封裝是在MPI接口完成的,所以接口下面的MPI實現中仍然可能會有大量的錯誤報告。你能做的最好的就是試圖壓制他們。

您還可以發現輸入端(緩沖區長度/定義)檢查在您的MPI使用中發現錯誤,例如傳遞太短的緩沖區?MPI_Recv。

未包裝的功能可能會增加錯誤率。一種可能的方法是與運行?MPI_DEBUG含有?warn。這將顯示您缺少正確的包裝器但仍然使用的功能。然后你可以為他們寫封裝。

PMPI_Reduce當使用自定義(用戶定義的)縮減功能時,一個已知的潛在的錯誤錯誤源?就是功能系列。在縮減操作中,每個節點都意圖將數據發送到使用指定的縮減功能的“中心點”,將數據項合并成單個項目。因此,通常,數據在節點之間傳遞并饋送到縮減功能,但是包裝庫不能將傳輸的數據標記為初始化之前被遞送到縮減功能,因為所有這些都發生在“內部”?PMPI_Reduce。因此,您的縮減功能可能會顯示誤報。

總結

以上是生活随笔為你收集整理的Memcheck:一个内存错误检测器的全部內容,希望文章能夠幫你解決所遇到的問題。

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

六月色婷婷| 久久免费在线视频 | 久在线 | 久久9视频 | 色综合天天综合在线视频 | a黄色片 | 日韩视频一区二区三区在线播放免费观看 | 久章草在线| 亚洲精品乱码久久久久久按摩 | 97成人资源站 | 精品久久精品久久 | 丁香五月亚洲综合在线 | 日日干夜夜干 | 免费在线观看毛片网站 | 亚洲欧美日韩在线一区二区 | 中文字幕激情 | 色香天天 | 日韩一级电影网站 | 欧美在线视频a | 日韩高清免费电影 | 亚洲国产美女久久久久 | 久久国产精品99久久人人澡 | 最近中文字幕高清字幕在线视频 | 午夜视频播放 | 欧美激情va永久在线播放 | 国内精品在线观看视频 | 在线观看中文字幕视频 | 久久免费电影网 | www.夜色321.com | 99精品欧美一区二区三区黑人哦 | 国产精品99久久久久久宅男 | 夜夜高潮夜夜爽国产伦精品 | 天堂在线v | 国产丝袜网站 | 欧美成人黄色片 | 欧美最新大片在线看 | 欧美性护士 | 成人黄色资源 | 久久黄色成人 | 国产伦精品一区二区三区… | 成人小视频在线免费观看 | 在线午夜电影神马影院 | 久久久精品国产一区二区三区 | 欧美 亚洲 另类 激情 另类 | 免费福利在线视频 | 精品在线播放视频 | 伊人久在线 | 91尤物国产尤物福利在线播放 | 成人性生交大片免费观看网站 | 免费在线看v | 精品一二三四在线 | 亚洲在线视频网站 | 色婷婷天天干 | 欧美一区影院 | 日韩在线观看视频网站 | 六月婷婷色| 国产精品久久久久久爽爽爽 | 一级理论片在线观看 | 国产精品免费久久久久久久久久中文 | av大全在线看 | 久久激情五月激情 | 一区二区欧美激情 | 久久国产精品99久久人人澡 | 亚洲精品视频在线 | 男女全黄一级一级高潮免费看 | 91视频免费看网站 | 久久久精品免费看 | 国产专区精品 | 国产免费观看高清完整版 | 欧美午夜剧场 | 亚洲成免费| 福利片免费看 | 成人免费亚洲 | 最新91在线视频 | 九九热视频在线 | www.一区二区三区 | 伊人午夜视频 | 久久九九免费 | 曰韩精品 | 欧美日韩在线免费观看视频 | 精品国产伦一区二区三区观看体验 | 欧美亚洲国产一卡 | 精品毛片一区二区免费看 | 亚洲国产69| 成人免费大片黄在线播放 | 丁香 婷婷 激情 | 久久av网址 | 一区二区不卡视频在线观看 | 国产五十路毛片 | 日韩欧美一区二区在线播放 | 五月激情电影 | 午夜三级福利 | 国产精品国产毛片 | 国产精品视频一二三 | 成人久久久久久久久久 | 在线亚洲小视频 | 日韩精品一区二区三区中文字幕 | 国产情侣一区 | 国产精品欧美日韩在线观看 | 国产美女网站在线观看 | 日韩欧美成 | 久久综合九色九九 | 日本中文字幕一二区观 | 成人毛片在线观看视频 | 狠狠五月天 | 久久综合九色综合97婷婷女人 | 亚洲精品小区久久久久久 | 五月婷婷久久综合 | 亚洲综合在线五月 | 开心色婷婷 | 视频在线91| 免费高清在线观看成人 | 日韩精品一区不卡 | 精品福利在线 | 久久99在线观看 | 就要色综合 | 五月天色中色 | 亚洲精品在线观看的 | 久久免费片 | 亚洲国产精品资源 | 右手影院亚洲欧美 | 婷婷六月激情 | 日韩特黄一级欧美毛片特黄 | 日本精品一二区 | 欧美一区免费在线观看 | 免费的黄色的网站 | 国产精品成人av久久 | 国产精品麻豆视频 | 国产伦精品一区二区三区在线 | 亚洲精品久久久久中文字幕二区 | 久久在草| 欧美激情在线看 | 精品国产免费久久 | 久久精品99久久久久久2456 | 国产视频九色蝌蚪 | 国产 字幕 制服 中文 在线 | 99免费看片 | 久久综合导航 | 久99视频| 久久久久久久久久久久电影 | 国产精品18久久久久vr手机版特色 | 国产成a人亚洲精v品在线观看 | 国产色影院 | 97国产 | 日本精品久久久一区二区三区 | 久久精品中文字幕一区二区三区 | 亚洲欧美国产精品18p | 亚洲一区视频在线播放 | 中文在线www | 丁香五月亚洲综合在线 | 91av色 | 97人人超碰在线 | 最新av网址在线 | 亚洲欧美婷婷六月色综合 | 成人av在线网 | 亚洲欧美日本一区二区三区 | 久草干| 高清免费av在线 | 国产日产精品一区二区三区四区 | av丝袜美腿 | 久久人人精 | 最新国产精品拍自在线播放 | 久久综合影音 | 91久久精品一区二区三区 | 91网在线观看 | 国产一区网址 | 国产一级黄色片免费看 | 色婷婷狠狠五月综合天色拍 | 久久免费视频在线 | 99国产精品视频免费观看一公开 | av高清不卡| 亚洲日本色 | 精品国产一区二区三区久久久 | 亚洲午夜久久久久久久久电影网 | 天堂在线一区二区 | 久久免费精品视频 | 99在线视频观看 | 日韩精品一区二区三区中文字幕 | 青青河边草免费视频 | 欧美 日韩精品 | 黄色片软件网站 | 国产成人高清 | 91人人爽人人爽人人精88v | 久久免费美女视频 | 99精品区| 91漂亮少妇露脸在线播放 | 超碰在线中文字幕 | 国产精品入口麻豆www | 美女视频黄在线观看 | 国产精品自产拍在线观看桃花 | 在线不卡中文字幕播放 | 黄色一区三区 | 日韩精品视频在线观看免费 | 成年在线观看 | 热久久精品在线 | 国产九九九精品视频 | 欧美日韩一区二区三区在线观看视频 | 欧美日韩亚洲第一 | 欧美大片第1页 | 另类五月激情 | 中文字幕在线看 | 最新色站 | 国产黄色电影 | 99久久精品无码一区二区毛片 | 久久婷婷网 | www.色爱| av九九 | 色香天天 | 亚洲精品理论 | 天天激情天天干 | 欧美日韩1区 | 国产色视频 | 中文字幕精品久久 | 在线精品视频免费观看 | 国产91丝袜在线播放动漫 | 在线影院 国内精品 | 国产精品毛片网 | 国模一区二区三区四区 | 国产一级在线观看视频 | 亚洲激情在线观看 | 久久久观看 | 伊人五月天 | 国产精品二区在线观看 | 亚洲国产中文字幕在线观看 | 日日色综合 | 天天综合日 | 69xx视频 | 91.dizhi永久地址最新 | 九九热视频在线 | 国产高清无线码2021 | 国产免费亚洲高清 | 免费久久久久久 | 99色资源 | 五月婷婷丁香在线观看 | 国产69精品久久久久99 | 成人av免费在线看 | 51久久成人国产精品麻豆 | 日韩中文在线电影 | 不卡的一区二区三区 | 久久国产欧美日韩 | 在线看片91 | 最近中文字幕在线中文高清版 | 正在播放国产91 | 中文字幕丝袜一区二区 | 在线观看资源 | 免费在线成人av电影 | 亚洲天堂网视频 | 午夜久久福利 | 欧美一级艳片视频免费观看 | 天天操夜夜操 | 六月丁香激情综合色啪小说 | 丁香花在线观看视频在线 | 国产精品热视频 | 国产一区二区日本 | 99精品毛片| 激情综合网色播五月 | 不卡的av在线 | 午夜精品一区二区三区视频免费看 | 欧美小视频在线 | 黄色国产精品 | 超碰97人人射妻 | 色就是色综合 | 精品国产网址 | a级成人毛片 | 91丨九色丨国产女 | 日韩中文字幕免费视频 | 69久久99精品久久久久婷婷 | 亚洲国产一区在线观看 | 久久99久久99精品免视看婷婷 | av看片网址 | 亚洲色图27p | 久久久久女教师免费一区 | 日韩成人免费观看 | 精品在线亚洲视频 | 在线观看黄色av | 久久久久综合视频 | 在线观看完整版免费 | 日韩丝袜在线观看 | 久草在线免费新视频 | 日韩欧美在线一区二区 | 久草网在线 | 日韩久久午夜一级啪啪 | 成年人免费在线播放 | 国产视频观看 | 日韩偷拍精品 | 婷婷精品视频 | 成人一区二区三区中文字幕 | 黄p在线播放 | 国产91在 | 999国产在线 | 亚洲精品h | 999久久久免费精品国产 | 一区二区伦理电影 | 一区二区视频欧美 | 91人人人 | 黄色性av | 久久国产精品一二三区 | 在线看一区 | 日韩v在线91成人自拍 | 国产成人在线精品 | 日韩欧美视频免费观看 | 玖操 | 人人爱在线视频 | 久久精品视频在线免费观看 | 毛片一二区 | 中文字幕久久亚洲 | 国产精品国产三级国产不产一地 | 欧美了一区在线观看 | 黄色一级在线免费观看 | 精品国产一区二区三区久久影院 | 国产精品久久久久永久免费看 | 在线影视 一区 二区 三区 | 高清av影院| 亚洲最新合集 | av片子在线观看 | 久久短视频 | 夜夜操天天操 | 天天操天天谢 | 成人久久毛片 | 色综合天天狠天天透天天伊人 | 伊人五月天综合 | 久久av影院| 黄网站色视频 | 欧美91精品 | 免费黄色a网站 | 96视频在线 | 亚洲成人精品在线观看 | 欧美日韩有码 | 91 中文字幕 | 国模精品在线 | 国产黄色精品网站 | 国产精品视频 | 久久久久国产一区二区三区四区 | 免费观看高清 | 操操日日 | 国语麻豆 | 国产麻豆剧果冻传媒视频播放量 | 亚洲视频在线免费观看 | 亚洲另类视频在线 | 亚洲精品在线视频观看 | 国产精品一区二区三区久久久 | 久久久久国产精品免费 | 美女福利视频 | 欧美福利精品 | 手机看片国产 | 日韩免费三区 | 国产黄在线免费观看 | 国产成人免费观看久久久 | 午夜国产一区二区三区四区 | 天天操 夜夜操 | 色婷婷激婷婷情综天天 | 成人黄色大片在线观看 | 美女视频a美女大全免费下载蜜臀 | 97人人看 | 成人久久免费 | 激情视频免费在线 | 在线视频观看亚洲 | 亚洲精品乱码白浆高清久久久久久 | 手机av在线网站 | 国产毛片久久久 | 国产精品白浆视频 | 国产一级二级三级在线观看 | 欧美日韩一区二区在线观看 | 国产中文字幕三区 | 国产一区二区在线免费 | 91av99| 九九热re| 偷拍精品一区二区三区 | 国产最新网站 | 日韩精品久久久久久中文字幕8 | 人人澡人人模 | 日日操天天操夜夜操 | 激情网站网址 | 天天色婷婷 | 久久久久久久久免费视频 | 色欲综合视频天天天 | 免费在线色视频 | 视频在线99| 深爱激情婷婷网 | 婷婷色影院 | 在线视频 亚洲 | 成人av在线直播 | 天天干天天操天天搞 | 欧美一二三四在线 | 色妞色视频一区二区三区四区 | 成人小视频在线免费观看 | 日日干 天天干 | 超碰人人在线 | www.夜夜骑.com | www黄com | 日本一区二区高清不卡 | 日日干日日色 | 怡红院av久久久久久久 | 天天鲁一鲁摸一摸爽一爽 | 国产精品一区二区三区观看 | 国产成人福利在线观看 | 国产91精品看黄网站 | 久久视频99| 亚洲精品国产精品乱码不99热 | 亚洲美女在线国产 | av午夜电影 | 亚洲成av人片一区二区梦乃 | 久久精品久久精品 | 久久精品电影网 | 女人18精品一区二区三区 | 韩国精品一区二区三区六区色诱 | 欧美一区二区三区四区夜夜大片 | 欧美一二三区播放 | 中文字幕在线影院 | 日韩有码第一页 | 中文字幕在线观看视频一区 | 久久久久福利视频 | 成年人在线观看免费视频 | 91精品国产高清 | 91在线操 | 国产黄色观看 | 久久久久久国产精品999 | 欧美日韩三区二区 | 国产精品色婷婷视频 | 中文字幕一区二区三区乱码不卡 | 国产精久久久久久妇女av | 精品亚洲免费 | 久久精品日韩 | 99亚洲精品在线 | 久久九精品| 国产一区免费 | 国产又粗又硬又长又爽的视频 | 精品国产一区二区三区噜噜噜 | 黄色精品免费 | 精品国产一区二区三区日日嗨 | 久久精品国产亚洲精品2020 | www.成人sex | 99久久久国产免费 | 91精品啪在线观看国产 | 免费在线观看午夜视频 | 久久夜色精品国产欧美乱 | 国产一区二区在线播放 | 欧美成人精品欧美一级乱黄 | 天天干 天天摸 天天操 | 日韩黄色av网站 | 成人一级视频在线观看 | 成年人黄色免费网站 | 成年人黄色免费看 | 国产精品对白一区二区三区 | 亚洲国产成人久久综合 | av一区在线 | 国产麻豆精品久久 | 免费黄色在线网址 | 国产高清网站 | 日韩毛片在线免费观看 | 午夜精品福利一区二区 | 久久久久久久久久久精 | 91精品国产电影 | 国产免费叼嘿网站免费 | 综合色综合 | 在线免费观看国产 | 国产不卡视频在线播放 | 亚洲精品高清一区二区三区四区 | 日韩在线网 | 六月色 | 激情网五月 | 国产精品福利在线观看 | 黄色一级在线观看 | 亚洲精品国产精品乱码在线观看 | 黄色一级免费电影 | 日日干美女 | 97视频免费观看 | 久av在线| 日韩欧美视频在线免费观看 | 九九免费观看视频 | av综合站 | 91视频在线播放视频 | 一区三区在线欧 | 精品久久久久久国产 | 欧美日韩精品在线播放 | 四虎国产精品永久在线国在线 | 国产精品亚洲片夜色在线 | 99久久9 | 日本精品视频在线观看 | 男女拍拍免费视频 | 欧美一区二区三区在线播放 | 99中文在线| 91精品日韩 | 色com | 丁香电影小说免费视频观看 | 欧美天天综合网 | av电影中文字幕 | 麻豆视频入口 | 97视频网址 | 久久艹综合 | 色婷婷激婷婷情综天天 | 亚洲精品乱码久久久久久蜜桃不爽 | 久久精品成人 | 欧美视频国产视频 | 色视频网页| 欧美va天堂va视频va在线 | 久久久久综合精品福利啪啪 | 久久久久免费精品 | 久久一二区 | 噜噜色官网| 一区二区三区在线看 | 9999精品 | 久久99视频免费观看 | 91成人免费在线视频 | 久久视频精品在线 | 欧美另类重口 | 日本黄色一级电影 | 久久国产影视 | 久久国产系列 | 亚洲欧美日韩一区二区三区在线观看 | 久草在线视频新 | 久久久久久久久久久电影 | 91成人区| 四虎影视av| 国产小视频免费在线网址 | 久久久国产影视 | 91桃色在线观看视频 | 亚洲国产高清在线观看视频 | 99精品一级欧美片免费播放 | 国产护士hd高朝护士1 | 狠狠狠操 | 午夜在线国产 | 亚洲精品视频免费 | 高清不卡毛片 | 午夜私人影院 | 激情开心色 | 黄色特一级 | www.天天草 | 91视视频在线直接观看在线看网页在线看 | 黄色免费视频在线观看 | 在线v片免费观看视频 | 亚洲国产网站 | 色91av| 亚洲成人精品在线 | 久久久九色精品国产一区二区三区 | 亚洲91中文字幕无线码三区 | 最近中文字幕免费观看 | 成人av在线直播 | 一区二区三区在线免费 | 久久久资源 | 国产精品美女久久久久久2018 | 天天爱综合 | 天堂激情网 | 亚洲视屏在线播放 | av网站手机在线观看 | 亚洲精品1区2区3区 超碰成人网 | 亚洲综合精品视频 | 久久精品视频观看 | 免费看的黄色小视频 | 中文字幕有码在线观看 | 色吧av色av | 日韩网 | 国产免费视频一区二区裸体 | 国内成人精品2018免费看 | 国色综合| 欧美激情第十页 | 中国一级片在线 | 成人av在线影院 | 中文字幕在线视频精品 | 精品一区二区三区久久 | 激情网色 | 午夜精品999 | 韩国av在线| 国产成人精品久久久久 | 欧美一区二区三区在线视频观看 | 精品国产激情 | 国产裸体视频网站 | 美女国产精品 | 九色91福利 | 美女黄频在线观看 | 日韩av成人免费看 | 色欧美成人精品a∨在线观看 | 中文字幕免费观看 | h动漫中文字幕 | 天天色天天干天天 | 五月天婷婷在线观看视频 | 色综合久久久 | 区一区二在线 | 日韩欧美一区二区三区在线观看 | 国产精品一区二区三区99 | 国产免费一区二区三区最新6 | 国产亚洲精品久久久久久大师 | 国产一区视频免费在线观看 | 亚洲区另类春色综合小说校园片 | 国产精品久久久久久久久久久免费 | 在线观看免费成人 | 丁香五月网久久综合 | 久久久亚洲国产精品麻豆综合天堂 | 天天干夜夜想 | 在线观看日韩国产 | 国产又粗又硬又长又爽的视频 | 国产精品久久久久永久免费观看 | 国产精品久久久久久久久久不蜜月 | 中文字幕在线播放av | 视频在线精品 | 国产精品久久久久久久毛片 | 99热这里只有精品久久 | 人成在线免费视频 | 国产精品a久久 | 大荫蒂欧美视频另类xxxx | 久久日本视频 | 亚洲视频电影在线 | 国产96精品 | 婷婷中文在线 | 欧美大片www | 一区二区不卡高清 | 97超碰人人澡 | 中文字幕 91 | 97国产小视频 | 麻豆视频在线免费观看 | 国产精品高潮在线观看 | 国产美女在线精品免费观看 | 91漂亮少妇露脸在线播放 | 在线91视频 | 五月婷在线观看 | 久久y | 久久婷婷色综合 | 成人免费在线观看电影 | 友田真希x88av | 99精品观看| 人人射人人插 | 国产成年免费视频 | 天天射天天操天天色 | 免费av在线播放 | 欧美成人黄色 | 国产成人av在线影院 | 久久99精品久久只有精品 | 另类五月激情 | 久久 一区 | 国产在线视频在线观看 | 久久午夜色播影院免费高清 | 精品国产欧美 | 国产一级精品在线观看 | 91在线国产观看 | 粉嫩一二三区 | 97超碰免费在线 | 97av色| 日韩精品一区二区三区不卡 | 九九激情视频 | 日韩欧美精品在线 | 婷婷午夜 | 免费精品在线 | 日韩在线观看视频网站 | 日韩在线观看免费 | 日韩精品你懂的 | 日韩激情影院 | 国产成人99久久亚洲综合精品 | 91高清视频 | 色99之美女主播在线视频 | 久久精品一区 | 91色吧| 97av在线| 国产在线观看黄 | 日韩激情中文字幕 | 日韩av在线免费播放 | av一级二级 | 欧美日韩国产欧美 | 人人澡澡人人 | 国产精品久久久久久99 | av黄色免费网站 | 日韩精品中文字幕一区二区 | 91一区二区在线 | 国产一区二区在线精品 | 一区二区三区免费在线 | 91看片黄色 | 欧美午夜精品久久久久久孕妇 | 最近高清中文字幕 | 天天操天天操 | 西西人体4444www高清视频 | 中文字幕在线日本 | 97看片网| 色偷偷中文字幕 | 中文字幕在线一二 | 色婷婷综合久久久久 | 久久狠狠婷婷 | 亚洲视频免费视频 | 97色狠狠| 久久国产品| 91九色蝌蚪视频网站 | 亚州免费视频 | av韩国在线 | 亚洲精品婷婷 | 国产精品美女久久久 | 又黄又刺激的网站 | 99热亚洲精品 | 一区二区三区免费看 | 久久精品男人的天堂 | 91视频国产免费 | 日韩三区在线观看 | 人人爽久久久噜噜噜电影 | 2000xxx影视 | 天天在线视频色 | 黄色软件在线观看 | 中文字幕日本在线观看 | www.大网伊人 | 天天射网 | 国产视频欧美视频 | 亚洲精品免费播放 | 久久久久久久久久久久亚洲 | 婷婷在线视频 | 免费精品视频在线 | 国产午夜精品av一区二区 | www.色com | 国产精品第2页 | 欧美大片大全 | 亚洲国产理论片 | 天天色草 | 久久久精品欧美一区二区免费 | 精品国产乱码久久 | 69中文字幕 | 99这里只有精品99 | 日日添夜夜添 | 国产99自拍 | 久久五月婷婷丁香 | 娇妻呻吟一区二区三区 | 国产一区麻豆 | 97成人免费 | 久久久久久久久久福利 | 成人免费在线视频 | 久久久久久美女 | 中文字幕精品一区二区三区电影 | 最近中文字幕完整视频高清1 | 欧美天天综合网 | 久久不射电影网 | 国产在线国偷精品产拍免费yy | 在线99视频| 91av视频免费在线观看 | 天天摸天天舔 | 夜夜躁日日躁狠狠久久88av | 国产精品一区二区免费视频 | 国产精品色婷婷视频 | 91高清在线看| 欧美视频日韩视频 | 丁香激情综合久久伊人久久 | 一区二区三区在线影院 | 久久久国产一区二区三区 | 久久美女视频 | 国产精品手机视频 | 日韩电影黄色 | 亚洲精品高清视频在线观看 | 亚洲专区视频在线观看 | 超碰国产在线观看 | 国产精品综合av一区二区国产馆 | 91精品视频免费观看 | 婷婷天天色 | 顶级欧美色妇4khd | 亚洲高清视频在线观看免费 | 麻豆视频国产在线观看 | 欧美成人理伦片 | a电影在线观看 | 精品一二三四五区 | 不卡国产视频 | 国产成人精品亚洲a | 免费看片成年人 | 婷婷激情在线观看 | 国产手机免费视频 | 国产精品一区二区在线看 | 日韩在线色视频 | 国产又粗又硬又爽的视频 | 国产一级视频在线免费观看 | 婷婷亚洲五月 | 亚洲欧美日韩一区二区三区在线观看 | 91成人在线视频观看 | 国产精品伦一区二区三区视频 | 毛片激情永久免费 | 成人永久免费 | 色五月激情五月 | 欧美乱淫视频 | 亚洲激情在线观看 | 成年人在线免费看片 | 国产成人久久精品亚洲 | 久久久久久久久久久成人 | 人人澡超碰碰97碰碰碰软件 | 在线不卡视频 | 五月婷在线 | 久久伊99综合婷婷久久伊 | 96亚洲精品久久久蜜桃 | 久久精品一区二区三区四区 | 精品国产激情 | 又粗又长又大又爽又黄少妇毛片 | 五月天婷婷综合 | 欧洲视频一区 | 五月婷婷在线视频观看 | 日韩免费看 | 亚州国产视频 | 日韩亚洲国产中文字幕 | 色偷偷88欧美精品久久久 | 国产97免费 | 久久福利电影 | 999成人精品| 999久久国产| 亚洲精品高清一区二区三区四区 | 一区二区三区精品在线视频 | 日韩精品91偷拍在线观看 | 日日天天av| 手机在线免费av | 欧美日韩一级久久久久久免费看 | 视频一区在线播放 | 成 人 黄 色视频免费播放 | 欧美人体xx| 最近2019年日本中文免费字幕 | 色婷婷狠狠操 | 天天爱天天射 | 国产精品手机在线 | 色婷婷亚洲精品 | 黄网站免费大全入口 | 国产精品女 | 波多野结衣在线视频免费观看 | 久久久午夜精品福利内容 | 草莓视频在线观看免费观看 | 特黄一级毛片 | 丁香婷婷久久久综合精品国产 | 视频二区| 中文字幕韩在线第一页 | 久久激情视频免费观看 | 福利精品在线 | 日韩在线视频免费观看 | 国产成人精品一区二区 | 免费黄色在线播放 | 99999精品视频 | av在线播放不卡 | 97视频在线看| 成人黄色小说网 | 成人在线观看影院 | 免费观看9x视频网站在线观看 | 狠狠的干狠狠的操 | jizzjizzjizz亚洲 | 91视频成人免费 | 手机在线黄色网址 | 69精品视频 | 国产色拍拍拍拍在线精品 | 免费视频xnxx com | 国产人在线成免费视频 | 色激情五月 | 欧美一区二区三区在线播放 | 日本久久成人中文字幕电影 | 亚洲视频久久久 | av资源在线看 | 国产精品久久久久9999 | 国产 精品 资源 | 欧美老女人xx | 日韩午夜小视频 | 免费成人在线观看视频 | 免费视频91 | 天干啦夜天干天干在线线 | 亚洲精品欧美成人 | 国产专区在线看 | 天天摸夜夜添 | av看片在线观看 | 天天操欧美 | 国产精品婷婷 | 六月丁香在线观看 | 免费av高清 | 大胆欧美gogo免费视频一二区 | 国产又粗又硬又爽视频 | 国产亚洲成人网 | 亚洲国产播放 | 黄a网| 久久久久久久国产精品视频 | 国产在线91精品 | 国产精品一区二区你懂的 | 亚洲午夜久久久久久久久电影网 | 午夜久久精品 | 国内精品久久久久久久97牛牛 | 久久久久久免费 | 91欧美在线 | 亚洲精品午夜久久久久久久久久久 | 久久影院精品 | 丝袜足交在线 | 波多野结衣在线播放一区 | 久久激五月天综合精品 | 亚洲不卡在线 | 天天天天综合 | 日本精品午夜 | 97电影院网| 首页av在线| 久久天天躁夜夜躁狠狠躁2022 | 国产精品日韩精品 | 欧美大jb| 成人观看视频 | 国产精品久久久久永久免费看 | 精品国产一区二区三区噜噜噜 | 91视频免费观看 | 欧美怡红院 | 亚洲麻豆精品 | 亚洲成av人片在线观看www | 99精品国产免费久久 | 激情综合网五月 | 91在线看 | 91日韩精品一区 | 国产精品久久久久久一二三四五 | 五月天久久综合网 | 综合天天色 | 一级性视频 | 中文字幕欧美日韩va免费视频 | 又黄又爽又刺激的视频 | 五月天色站 | 在线观看视频国产 | 人人玩人人添人人 | 狠狠久久伊人 | 欧美日韩国产色综合一二三四 | 亚州性色 | 亚洲黄色软件 | 久草在线视频国产 | 日韩久久在线 | 国产免费观看视频 | 亚洲欧洲一级 | 天天干天天操天天操 | 在线观看韩国av | 日韩视频1| 国产精品入口传媒 | 中文字幕2021 | 国产精品久久久久婷婷 | 成人免费在线播放视频 | 91看片在线看片 | 91精品久久久久久综合乱菊 | 一本一本久久a久久精品牛牛影视 | www.日日日.com | 一区二区三区电影 | 久久精品一二区 | 欧美一级特黄aaaaaa大片在线观看 | 91精品视频在线看 | 最新国产福利 | 国产一区成人在线 | 亚洲欧美一区二区三区孕妇写真 | 深爱激情五月综合 | 91视频在线国产 | 国产在线久久久 | 国产高清视频在线免费观看 | 国产麻豆精品久久 | 色播激情五月 | 91在线看| 成人在线观看影院 | 成人在线免费视频 | 国产成人免费av电影 | 91精品久久久久 | 天天色影院| 99视频偷窥在线精品国自产拍 | 亚洲精品国产精品国自产观看浪潮 | 天天爽人人爽夜夜爽 | 久久伊人色综合 | 欧美成人久久 | 99精品美女| 精品综合久久久 | 欧美日韩一区三区 | 日日摸日日 | 国产精品小视频网站 | 久久97精品| 男女激情麻豆 | 看片一区二区三区 | 日本激情动作片免费看 | 狠狠躁日日躁夜夜躁av | 精品在线免费视频 | 免费手机黄色网址 | 国产手机在线 | 国产91亚洲精品 | 超碰在线人人草 | 日本99干网 | 久久免费视频一区 | 精品成人国产 | 久久综合久久伊人 | av免费观看网站 | 亚洲毛片视频 | 亚洲黄色在线观看 | 国产精品初高中精品久久 | 国产精品永久久久久久久www | 国产综合小视频 | 亚洲精品国产精品国自产观看 | 久草青青在线观看 | 欧美黄在线 | av三级av | 中文字幕在线视频一区二区 | 亚洲精品理论 | 国产无遮挡又黄又爽馒头漫画 | 日日夜夜国产 | 亚洲日日射 | 欧美一级欧美一级 | 中文字幕黄色 | www.久久久久| 超碰人人99 | 国产护士hd高朝护士1 | 五月婷婷激情综合 | www.久草.com | 日日干夜夜草 | 欧美成年人在线视频 | 日韩专区在线观看 | 亚洲人人网 | 九九久久影视 | 中文字幕丝袜一区二区 | 亚洲国产精品人久久电影 | 在线激情影院一区 | 国产精品大尺度 | 免费亚洲视频在线观看 | 成人av亚洲 | 99看视频在线观看 | 欧美成人va| 欧洲视频一区 | 久久精品系列 |