คุณตรวจจับ / หลีกเลี่ยงการรั่วไหลของหน่วยความจำในรหัส (ไม่มีการจัดการ) ของคุณได้อย่างไร? [ปิด]


125

ในโค้ด C / C ++ ที่ไม่มีการจัดการแนวทางปฏิบัติที่ดีที่สุดในการตรวจจับการรั่วไหลของหน่วยความจำคืออะไร? และแนวทางการเข้ารหัสเพื่อหลีกเลี่ยง? (ราวกับว่ามันง่ายมาก)

เราเคยใช้วิธีโง่ ๆ ในอดีต: มีการเพิ่มตัวนับสำหรับการเรียกจัดสรรหน่วยความจำทุกครั้งและลดลงในขณะที่ว่าง ในตอนท้ายของโปรแกรมค่าตัวนับควรเป็นศูนย์

ฉันรู้ว่านี่ไม่ใช่วิธีที่ดีและมีการจับไม่กี่ครั้ง (ตัวอย่างเช่นหากคุณกำลังเพิ่มหน่วยความจำที่จัดสรรโดยการเรียก API ของแพลตฟอร์มจำนวนการจัดสรรของคุณจะไม่ตรงกับจำนวนการว่างของคุณแน่นอนจากนั้นเราจะเพิ่มตัวนับเมื่อเรียกการเรียก API ที่จัดสรรหน่วยความจำ)

ฉันคาดหวังว่าประสบการณ์คำแนะนำของคุณและอาจมีการอ้างอิงถึงเครื่องมือที่ทำให้สิ่งนี้ง่ายขึ้น


ในแง่ของการหลีกเลี่ยงการรั่วไหลโพสต์ต่อไปนี้มีคำแนะนำ: http://stackoverflow.com/questions/27492/c-memory-management
tonylo

ฉันถามคำถามนี้ที่นี่: http://stackoverflow.com/questions/25730/what-is-the-best-free-memory-leak-detector-for-a-cc-program-and-its-plug-in- กำลังและมีความสำเร็จกับการรั่วไหลตรวจจับภาพ
Jim Buck

ฉันใช้อันนี้กับสตูดิโอภาพเพื่อตรวจจับการรั่วไหลของ mem codeproject.com/KB/applications/visualleakdetector.aspx
tiboo

1
คุณค้นหา valgrin (สำหรับ linux) หรือ deleaker (สำหรับ windows) ดูเครื่องตรวจจับการรั่วไหลด้วยภาพ ...
John Smith

สำหรับการค้นหาการรั่วไหลของหน่วยความจำตรวจสอบที่นี่: theunixshell.blogspot.com/2013/11/…
วีเจย์

คำตอบ:


78

หากคุณ C / C ++ รหัสเป็นแบบพกพาที่จะระวัง * บางสิ่งที่ดีกว่าValgrind


1
ขณะนี้ Valgrind ทำงานบน OS X แล้วดังนั้น linux จึงไม่ใช่ตัวเลือกเดียวของคุณ
Michael Anderson

1
Valgrind สำหรับ Linux (และ OS X) หากคุณใช้ windose - deleaker - ดีที่สุด!
John Smith

@JordiBunster: ดี! แต่ใช้รันไทม์ ด้วยฐานรหัสขนาดใหญ่(เขียนด้วยตัวอักษร C)คุณจะทดสอบโปรแกรมของคุณเป็นหลักตามที่ได้รับการออกแบบมา ผู้โจมตีสามารถใช้เวลาหลายพันชั่วโมงในการอ่านโค้ดเพื่อค้นหาช่องโหว่ของหน่วยความจำรั่ว ฉันคาดว่าจะมีเครื่องมืออัตโนมัติสำหรับการวิเคราะห์ซอร์สโค้ดที่คล้ายกับที่มีอยู่ใน JavaScript
user2284570

65

หากคุณกำลังใช้ Visual Studio Microsoft มีฟังก์ชันที่มีประโยชน์บางอย่างสำหรับการตรวจจับและแก้ไขข้อบกพร่องของหน่วยความจำที่รั่วไหล

ฉันจะเริ่มต้นด้วยบทความนี้: https://msdn.microsoft.com/en-us/library/x98tx3cf(v=vs.140).aspx

นี่คือสรุปย่อของบทความเหล่านั้น ขั้นแรกรวมส่วนหัวเหล่านี้:

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

จากนั้นคุณต้องเรียกสิ่งนี้เมื่อโปรแกรมของคุณออก:

_CrtDumpMemoryLeaks();

หรือหากโปรแกรมของคุณไม่ออกจากที่เดิมทุกครั้งคุณสามารถเรียกสิ่งนี้เมื่อเริ่มโปรแกรมของคุณ:

_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

ตอนนี้เมื่อโปรแกรมออกจากการจัดสรรทั้งหมดที่ไม่ฟรีจะถูกพิมพ์ในหน้าต่างผลลัพธ์พร้อมกับไฟล์ที่ถูกจัดสรรและการจัดสรรจะเกิดขึ้น

กลยุทธ์นี้ใช้ได้กับโปรแกรมส่วนใหญ่ อย่างไรก็ตามมันกลายเป็นเรื่องยากหรือเป็นไปไม่ได้ในบางกรณี การใช้ไลบรารีของบุคคลที่สามที่ทำการกำหนดค่าเริ่มต้นเมื่อเริ่มต้นระบบอาจทำให้วัตถุอื่น ๆ ปรากฏในการถ่ายโอนข้อมูลหน่วยความจำและทำให้การติดตามการรั่วไหลของคุณทำได้ยาก นอกจากนี้หากชั้นเรียนของคุณมีสมาชิกที่มีชื่อเดียวกันกับรูทีนการจัดสรรหน่วยความจำใด ๆ (เช่น malloc) มาโครการดีบัก CRT จะทำให้เกิดปัญหา

มีเทคนิคอื่น ๆ ที่อธิบายไว้ในลิงก์ MSDN ที่อ้างถึงข้างต้นที่สามารถใช้ได้เช่นกัน


หมายเหตุเกี่ยวกับวิธีนี้: ดูเหมือนว่าจะใช้ได้เฉพาะเมื่อคุณใช้ C บริสุทธิ์กับ malloc และฟรี รายงานโดยละเอียดซึ่งรวมถึงหมายเลขบรรทัดจะไม่ถูกสร้างขึ้นหากคุณใช้ c ++ ใหม่และลบ
Zach

2
@ Zach: จริงๆแล้วคุณสามารถใช้งานได้เช่นกัน (สำหรับโค้ดใด ๆ ที่คุณรวบรวมด้วยตัวเองจริงๆ) - ดูคำตอบที่ยอมรับในsocial.msdn.microsoft.com/forums/en-US/vcgeneral/thread/…
Roman Starkov

สิ่งนี้จะทำงานในโหมดรีลีสด้วยหรือไม่?
JV

1
@ user3152463 ไม่ได้ตามเอกสารจะใช้ได้เฉพาะกับรุ่น debug เท่านั้น: msdn.microsoft.com/en-us/library/e5ewb1h3(v=vs.71).aspx
Dusty Campbell

บรรทัดนี้ไม่ถูกต้อง: #define CRTDBG_MAP_ALLOC ควรเป็น: #define _CRTDBG_MAP_ALLOC
Fallso

37

ใน C ++: ใช้ RAII ชี้สมาร์ทชอบstd::unique_ptr, std::shared_ptr, std::weak_ptrเป็นเพื่อนของคุณ


1
และ std: vector เป็นตัวทดแทนที่ดีเมื่อมีการจัดสรรอาร์เรย์ (บัฟเฟอร์) ในฟังก์ชันเดียวกันกับที่จัดสรร
KJAWolf

4
อย่างน้อย std :: auto_ptr และ boost :: shared_ptr ยังเสี่ยงต่อการรั่วไหล
Jasper Bekkers

5
เฉพาะในกรณีที่คุณใช้ไม่ถูกต้อง แต่ฉันควรยอมรับว่าสำหรับ std :: auto_ptr การใช้อย่างไม่ถูกต้องนั้นค่อนข้างง่าย
Leon Timmermans

2
แม้ว่านี่จะเป็นคำแนะนำที่ดีสำหรับมาตรฐานการเข้ารหัส แต่ก็ไม่ได้ตอบคำถาม แม้แต่การใช้ shared_ptr ก็สามารถนำไปสู่การรั่วไหลที่มีการอ้างอิงแบบวงกลม และคุณสามารถมี "การรั่วไหล" ด้วยกลยุทธ์การแคชแบบไม่ จำกัด ซึ่งใช้ได้แม้กระทั่งกับภาษาที่เก็บขยะ
CashCow

@CashCow: คุณถูกต้อง แม้ว่าฉันจะยังไม่ได้เห็นมันในทางปฏิบัตินั่นอาจเป็นเพราะฉันใช้มันเท่าที่จำเป็น หากต้องการอ้างอิงคำตอบด้านล่าง "ใช้คำแนะนำเมื่อจำเป็นจริงๆเท่านั้น"
Leon Timmermans

28

ในฐานะนักพัฒนา C ++ ต่อไปนี้เป็นแนวทางง่ายๆ:

  1. ใช้พอยน์เตอร์เมื่อจำเป็นจริงๆเท่านั้น
  2. หากคุณต้องการตัวชี้ให้ตรวจสอบอีกครั้งว่าSmartPointerเป็นไปได้หรือไม่
  3. ใช้รูปแบบGRASP Creator

สำหรับการตรวจจับการรั่วไหลของหน่วยความจำโดยส่วนตัวฉันใช้Visual Leak Detector มาโดยตลอดและพบว่ามันมีประโยชน์มาก


2
Visual Leak Detectore ย้ายไปที่เว็บไซต์ใหม่vld.codeplex.com
KindDragon

VLD เป็นเครื่องตรวจจับการรั่วที่ดีจริงๆ - ฉันแนะนำโดยสิ้นเชิงสำหรับทุกคนที่ใช้ VC ++
Javid

1
+1 สำหรับจุด # 1 นี่เป็นสิ่งพื้นฐานอย่างแน่นอน น่าเสียดายที่สำหรับฉันแล้วดูเหมือนว่าไลบรารี "C ++" ที่ใหญ่ที่สุดบางแห่งมักจะละเว้นการจัดสรรสแต็กและ / หรือ RAII เพื่อสนับสนุน Pointers Everywhere โดยมักจะไม่มีเหตุผลที่ชัดเจน ดังนั้นพวกเขาจึงกลายเป็น 'C with Classes' ไม่ใช่ C ++ จริง
underscore_d

16

ฉันใช้ DevStudio มานานหลายปีแล้วและมันทำให้ฉันประหลาดใจเสมอว่ามีโปรแกรมเมอร์กี่คนที่ไม่รู้เกี่ยวกับเครื่องมือวิเคราะห์หน่วยความจำที่มีอยู่ในไลบรารีเวลาทำงานดีบัก ต่อไปนี้เป็นลิงก์บางส่วนสำหรับเริ่มต้นใช้งาน:

การติดตามคำขอการจัดสรรกอง - โดยเฉพาะส่วนในหมายเลขคำขอการจัดสรรเฉพาะ

_CrtSetDbgFlag

_CrtSetBreakAlloc

แน่นอนว่าหากคุณไม่ได้ใช้ DevStudio สิ่งนี้จะไม่เป็นประโยชน์อย่างยิ่ง


10

ฉันประหลาดใจที่ไม่มีใครพูดถึงDebugDiagสำหรับ Windows OS
ใช้งานได้กับรุ่นที่วางจำหน่ายและแม้แต่ที่ไซต์ของลูกค้า
(คุณเพียงแค่ต้องเก็บ PDB เวอร์ชันรีลีสไว้และกำหนดค่า DebugDiag เพื่อใช้เซิร์ฟเวอร์สัญลักษณ์สาธารณะของ Microsoft)


3
ลิงก์ใช้งานไม่ได้อีกต่อไปลองดูเอกสารที่นี่: support.microsoft.com/kb/2580960และดาวน์โหลดที่นี่: microsoft.com/en-us/download/details.aspx?id=26798
JPaget

7

Visual Leak Detector เป็นเครื่องมือที่ดีมากแม้ว่าจะไม่รองรับการเรียกใช้ VC9 runtimes (MSVCR90D.DLL เป็นต้น)


1
เครื่องมือนี้สมบูรณ์แบบจริงๆ! ช่วยให้คุณประหยัดปัญหาในการใช้ _CrtDumpMemoryLeaks (); และเพื่อน ๆ ตามที่อธิบายไว้ใน MSDN รวมเพียงหนึ่งเดียวและเปิดเผยทุกอย่าง! ใช้งานได้แม้ในไลบรารี C เก่า!
m_pGladiator

เวอร์ชันใหม่ (สำหรับ VS2013) อยู่ที่นี่: vld.codeplex.com
Dženan

7

Microsoft VC ++ ในโหมดดีบักจะแสดงหน่วยความจำรั่วแม้ว่าจะไม่แสดงว่าการรั่วไหลของคุณอยู่ที่ใด

หากคุณกำลังใช้ C ++ คุณสามารถหลีกเลี่ยงการใช้ใหม่อย่างชัดเจน: คุณมีvector, string, auto_ptr(pre C ++ 11; แทนที่ด้วยunique_ptrใน C ++ 11), unique_ptr(C ++ 11) และshared_ptr(C ++ 11) ในคลังแสงของคุณ

เมื่อหลีกเลี่ยงไม่ได้ใหม่ให้พยายามซ่อนไว้ในตัวสร้าง (และซ่อนการลบในตัวทำลาย) เช่นเดียวกันกับ API ของบุคคลที่สาม


1
และอย่าลืมกฎ 3 หรือ 5 จากนั้น
Humam Helfawi

4

มีไลบรารี "malloc" ทดแทนมากมายที่จะช่วยให้คุณสามารถเรียกใช้ฟังก์ชันได้ในตอนท้ายและจะบอกคุณเกี่ยวกับหน่วยความจำที่ไม่ได้รีเฟรชทั้งหมดและในหลาย ๆ กรณีใครที่เป็น malloced (หรือใหม่) ในตอนแรก .


4

หากคุณใช้ MS VC ++ ฉันขอแนะนำเครื่องมือฟรีนี้จาก codeproject: leakfinderโดย Jochen Kalmbach

คุณเพียงแค่เพิ่มชั้นเรียนลงในโครงการของคุณแล้วโทร

InitAllocCheck(ACOutput_XML)
DeInitAllocCheck()

ก่อนและหลังรหัสที่คุณต้องการตรวจสอบการรั่วไหล

เมื่อคุณสร้างและเรียกใช้โค้ดแล้ว Jochen จะมีเครื่องมือ GUI ที่เป็นระเบียบซึ่งคุณสามารถโหลดไฟล์. xmlleaks ที่เป็นผลลัพธ์และนำทางผ่าน call stack ที่มีการสร้างการรั่วไหลแต่ละครั้งเพื่อค้นหาบรรทัดของโค้ดที่ละเมิด

PurifyPlus ของ Rational (ปัจจุบันเป็นเจ้าของโดย IBM) PurifyPlus แสดงให้เห็นถึงการรั่วไหลในรูปแบบที่คล้ายกัน แต่ฉันพบว่าเครื่องมือการรั่วไหลใช้งานง่ายกว่าจริง ๆ โดยโบนัสของมันไม่ได้มีราคาหลายพันดอลลาร์!


1
ฉันตรวจสอบการรั่วไหลและมันก็ดูโอเค แต่แค่ FYI มันจะใช้งานไม่ได้เหมือนเดิมสำหรับ x64 เพราะมันมีชุดประกอบแบบอินไลน์
Zach


3

หากคุณกำลังใช้ Visual Studio ก็อาจจะคุ้มค่าดูที่ขอบเขตตรวจสอบ ไม่ฟรี แต่มีประโยชน์อย่างเหลือเชื่อในการค้นหาการรั่วไหลในโค้ดของฉัน มันไม่เพียงแค่ทำหน่วยความจำรั่วเท่านั้น แต่ยังมีการรั่วไหลของทรัพยากร GDI ข้อผิดพลาดในการใช้งาน WinAPI และสิ่งอื่น ๆ มันจะแสดงให้คุณเห็นว่าหน่วยความจำที่รั่วไหลถูกเริ่มต้นที่ไหนทำให้ง่ายต่อการติดตามการรั่วไหล


2

ฉันคิดว่าไม่มีคำตอบง่ายๆสำหรับคำถามนี้ วิธีที่คุณสามารถเข้าถึงโซลูชันนี้ได้ขึ้นอยู่กับความต้องการของคุณ คุณต้องการโซลูชันข้ามแพลตฟอร์มหรือไม่? คุณใช้ new / delete หรือ malloc / free (หรือทั้งสองอย่าง)? คุณกำลังมองหาเพียง "การรั่วไหล" หรือคุณต้องการการป้องกันที่ดีกว่าเช่นการตรวจจับการโอเวอร์รันของบัฟเฟอร์ (หรือการรัน)

หากคุณกำลังทำงานในฝั่ง windows ไลบรารีรันไทม์การดีบัก MS จะมีฟังก์ชันการตรวจจับการดีบักพื้นฐานบางอย่างและตามที่ได้ระบุไว้แล้วมีตัวห่อหลายตัวที่สามารถรวมอยู่ในซอร์สของคุณเพื่อช่วยในการตรวจจับการรั่วไหล การค้นหาแพ็กเกจที่สามารถทำงานร่วมกับทั้ง new / delete และ malloc / free จะช่วยให้คุณมีความยืดหยุ่นมากขึ้น

ฉันไม่รู้เกี่ยวกับด้านยูนิกซ์มากพอที่จะให้ความช่วยเหลือได้แม้ว่าคนอื่น ๆ จะมี

แต่นอกเหนือจากการตรวจจับการรั่วไหลแล้วยังมีแนวคิดในการตรวจจับความเสียหายของหน่วยความจำผ่านการโอเวอร์รันบัฟเฟอร์ (หรือการรัน) ฉันคิดว่าฟังก์ชันการดีบักประเภทนี้ยากกว่าการตรวจจับการรั่วไหลธรรมดา ระบบประเภทนี้ยังซับซ้อนยิ่งขึ้นหากคุณกำลังทำงานกับอ็อบเจ็กต์ C ++ เนื่องจากคลาส polymorhpic สามารถลบได้หลายวิธีทำให้เกิดความยุ่งยากในการกำหนดตัวชี้ฐานที่แท้จริงที่จะถูกลบ ฉันรู้ว่าไม่มีระบบ "ฟรี" ที่ดีที่ให้การป้องกันที่เหมาะสมสำหรับการใช้งานมากเกินไป เราได้เขียนระบบ (ข้ามแพลตฟอร์ม) และพบว่ามันค่อนข้างท้าทาย


2

ฉันต้องการนำเสนอสิ่งที่ฉันเคยใช้ในอดีต: เครื่องตรวจสอบการรั่วไหลขั้นพื้นฐานซึ่งเป็นระดับต้นทางและค่อนข้างอัตโนมัติ ฉันให้สิ่งนี้ไปด้วยเหตุผลสามประการ:

  1. คุณอาจพบว่ามันมีประโยชน์.

  2. แม้ว่าจะดูธรรมดาไปหน่อย แต่ฉันก็ไม่ปล่อยให้สิ่งนั้นทำให้ฉันขุ่นเคือง

  3. แม้ว่าจะผูกติดกับตะขอ win32 แต่ก็น่าจะบรรเทาได้ง่าย

มีสิ่งที่คุณต้องระวังเมื่อใช้: อย่าทำอะไรที่ต้องพึ่งพา newรหัสที่อยู่ข้างใต้ระวังคำเตือนเกี่ยวกับกรณีที่อาจพลาดที่ด้านบนของ leakcheck.cpp โปรดทราบว่าหากคุณเลี้ยว เปิด (และแก้ไขปัญหาเกี่ยวกับ) รหัสที่ถ่ายโอนภาพคุณอาจสร้างไฟล์ขนาดใหญ่

การออกแบบนี้มีขึ้นเพื่อให้คุณสามารถเปิดและปิดตัวตรวจสอบได้โดยไม่ต้องคอมไพล์ทุกอย่างที่มีส่วนหัวซ้ำ รวมการตรวจสอบการรั่วไหลที่คุณต้องการติดตามการตรวจสอบและสร้างใหม่เพียงครั้งเดียว หลังจากนั้นให้คอมไพล์ leakcheck.cpp โดยมีหรือไม่มี LEAKCHECK # define'd จากนั้นเชื่อมโยงใหม่เพื่อเปิดและปิด การรวม unleakcheck.h จะปิดการใช้งานภายในไฟล์ มีมาโครสองตัว: CLEARALLOCINFO () จะหลีกเลี่ยงการรายงานไฟล์และบรรทัดเดียวกันอย่างไม่เหมาะสมเมื่อคุณสำรวจการจัดสรรโค้ดที่ไม่มีการรั่วไหล ALLOCFENCE () เพียงแค่วางบรรทัดในรายงานที่สร้างขึ้นโดยไม่ต้องทำการจัดสรรใด ๆ

อีกครั้งโปรดทราบว่าฉันไม่ได้ใช้สิ่งนี้มาระยะหนึ่งแล้วและคุณอาจต้องทำงานกับมันสักหน่อย ฉันวางมันลงเพื่อแสดงความคิด หากปรากฎว่ามีความสนใจเพียงพอฉันยินดีที่จะทำตัวอย่างอัปเดตโค้ดในกระบวนการและแทนที่เนื้อหาของ URL ต่อไปนี้ด้วยสิ่งที่ดีกว่าซึ่งรวมถึงรายการที่มีสีไวยากรณ์ที่เหมาะสม

คุณสามารถค้นหาได้ที่นี่: http://www.cse.ucsd.edu/~tkammeye/leakcheck.html


2

สำหรับ Linux: ลองใช้Google Perftools

มีเครื่องมือมากมายที่ให้การจัดสรร / การนับฟรีที่คล้ายกันข้อดีของ Goolge Perftools:

  • ค่อนข้างเร็ว (เมื่อเทียบกับ valgrind: เร็วมาก)
  • มาพร้อมกับการแสดงผลแบบกราฟิกที่สวยงาม
  • มีความสามารถที่เป็นประโยชน์อื่น ๆ : cpu-profiling, memory-usage profiling ...

ย้ายไปที่: github.com/gperftools/gperftools
Michael

2

การป้องกันการรั่วไหลที่ดีที่สุดคือโครงสร้างโปรแกรมที่ลดการใช้ malloc ให้น้อยที่สุด สิ่งนี้ไม่เพียง แต่จะดีจากมุมมองของการเขียนโปรแกรมเท่านั้น แต่ยังช่วยเพิ่มประสิทธิภาพและความสามารถในการบำรุงรักษาอีกด้วย ฉันไม่ได้พูดถึงการใช้สิ่งอื่นแทน malloc แต่ในแง่ของการใช้อ็อบเจกต์ซ้ำและการรักษาแท็บที่ชัดเจนมากบนวัตถุทั้งหมดที่ส่งผ่านไปมาแทนที่จะจัดสรรโดยเจตนาเหมือนอย่างที่คนทั่วไปคุ้นเคยในภาษากับคนเก็บขยะ เช่น Java

ตัวอย่างเช่นโปรแกรมที่ฉันทำงานมีวัตถุเฟรมจำนวนมากที่แสดงข้อมูลรูปภาพ วัตถุแต่ละเฟรมมีข้อมูลย่อยซึ่งตัวทำลายของเฟรมปลดปล่อยออกมา โปรแกรมจะเก็บรายการของเฟรมทั้งหมดที่ถูกจัดสรรและเมื่อต้องการเฟรมใหม่ให้ตรวจสอบรายการของเฟรมที่ไม่ได้ใช้เพื่อดูว่าสามารถใช้เฟรมที่มีอยู่ซ้ำได้หรือไม่แทนที่จะจัดสรรเฟรมใหม่ เมื่อปิดเครื่องมันจะวนซ้ำผ่านรายการเพื่อปลดปล่อยทุกอย่าง


2

ฉันอยากจะแนะนำให้ใช้Memory Validatorจากการตรวจสอบซอฟต์แวร์ เครื่องมือนี้พิสูจน์แล้วว่าเป็นตัวช่วยล้ำค่าที่ช่วยฉันในการติดตามการรั่วไหลของหน่วยความจำและเพื่อปรับปรุงการจัดการหน่วยความจำของแอปพลิเคชันที่ฉันกำลังทำงานอยู่

เครื่องมือที่สมบูรณ์และรวดเร็ว


Memory Validator ยังมีชื่อไฟล์และหมายเลขบรรทัดสำหรับ C # ที่เรียกใช้รหัสดั้งเดิมของคุณ เวอร์ชัน x64 เป็นรุ่นเบต้า
Stephen Kellett

2

คุณกำลังนับการจัดสรรและการปลดปล่อยโดยการสอดแทรกฟังก์ชัน syscall ของคุณเองซึ่งบันทึกการโทรแล้วส่งการโทรไปยังฟังก์ชันจริงหรือไม่?

นี่เป็นวิธีเดียวที่คุณสามารถติดตามการโทรที่มาจากรหัสที่คุณไม่ได้เขียน

ดูที่หน้าคนสำหรับ ld.so. หรือ ld.so.1 ในบางระบบ

ทำ Google LD_PRELOAD ด้วยและคุณจะพบบทความที่น่าสนใจอธิบายเทคนิคนี้ได้ที่ www.itworld.com


1

อย่างน้อยสำหรับ MS VC ++ ไลบรารี C Runtime มีฟังก์ชันหลายอย่างที่ฉันเคยพบว่ามีประโยชน์ในอดีต ตรวจสอบวิธีใช้ MSDN สำหรับ_Crt*ฟังก์ชัน


1

mmgr ของ Paul Nettleเป็นเครื่องมือโปรดของฉันมานาน คุณรวม mmgr.h ในไฟล์ต้นฉบับกำหนด TEST_MEMORY และส่งไฟล์ข้อความที่เต็มไปด้วยปัญหาหน่วยความจำที่เกิดขึ้นระหว่างการรันแอปของคุณ


1

แนวทางการเข้ารหัสทั่วไป:

  • ควรยกเลิกการจัดสรรทรัพยากรที่ "เลเยอร์" (ฟังก์ชัน / คลาส / ไลบรารี) เดียวกันกับที่ที่มีการจัดสรร
  • หากเป็นไปไม่ได้ให้ลองใช้การยกเลิกการจัดสรรอัตโนมัติ (เพิ่มตัวชี้ที่ใช้ร่วมกัน ... )

1

เครื่องมือดีบั๊กหน่วยความจำมีค่าเท่ากับน้ำหนักทองคำ แต่ในช่วงหลายปีที่ผ่านมาฉันพบว่าสามารถใช้แนวคิดง่ายๆสองข้อเพื่อป้องกันการรั่วไหลของหน่วยความจำ / ทรัพยากรส่วนใหญ่จากการเข้ารหัสตั้งแต่แรก

  1. เขียนรหัสรุ่นทันทีหลังจากเขียนรหัสการได้มาสำหรับทรัพยากรที่คุณต้องการจัดสรร ด้วยวิธีนี้ทำให้ "ลืม" ได้ยากขึ้นและในบางแง่ก็เป็นการบังคับให้เราต้องนึกถึงวงจรชีวิตของทรัพยากรที่ถูกใช้อย่างจริงจังแทนที่จะเป็นการทิ้ง

  2. ใช้ผลตอบแทนเท่าที่จะทำได้ สิ่งที่จัดสรรควรปล่อยให้เป็นอิสระในที่เดียวถ้าเป็นไปได้ เส้นทางที่มีเงื่อนไขระหว่างการได้มาของทรัพยากรและการเผยแพร่ควรได้รับการออกแบบให้เรียบง่ายและชัดเจนที่สุด


1

ที่ด้านบนสุดของรายการนี้ (ตอนที่ฉันอ่าน) คือ valgrind Valgrind นั้นยอดเยี่ยมมากหากคุณสามารถทำซ้ำรอยรั่วในระบบทดสอบได้ ฉันใช้มันด้วยความสำเร็จ

จะเกิดอะไรขึ้นถ้าคุณเพิ่งสังเกตเห็นว่าระบบการผลิตรั่วไหลในขณะนี้และคุณไม่รู้ว่าจะทำซ้ำในการทดสอบได้อย่างไร? มีการบันทึกหลักฐานบางอย่างเกี่ยวกับความผิดปกติในสถานะของระบบการผลิตนั้นและอาจเพียงพอที่จะให้ข้อมูลเชิงลึกว่าปัญหาอยู่ที่ใดเพื่อให้คุณสามารถทำซ้ำได้

นั่นคือจุดที่การสุ่มตัวอย่าง Monte Carlo เข้ามาในภาพ อ่านบทความในบล็อกของ Raymond Chen "วิธีการระบุหน่วยความจำรั่วของคนยากจน" จากนั้นตรวจสอบการใช้งานของฉัน (สมมติว่า Linux ทดสอบเฉพาะบน x86 และ x86-64)

http://github.com/tialaramex/leakdice/tree/master


1

การทำงานบนระบบปฏิบัติการของโทรศัพท์เคลื่อนที่ Motorola เราได้จี้คลังการจัดสรรหน่วยความจำเพื่อสังเกตการจัดสรรหน่วยความจำทั้งหมด ช่วยให้พบปัญหามากมายเกี่ยวกับการจัดสรรหน่วยความจำ เนื่องจากการป้องกันดีกว่าแล้วจึงทำให้หายได้ฉันจึงขอแนะนำให้ใช้เครื่องมือวิเคราะห์แบบคงที่เช่นKlockworkหรือPC-Lint


เฝือกเป็นการเปลี่ยนผ้าสำลีที่ใหม่กว่า
Mark Kegel

@ user14788: ผลิตภัณฑ์ PC-Lint ของ Gimpel ทันสมัยกว่า Unix รุ่นเก่าlintมาก มีการตรวจสอบหลายอย่างเฉพาะสำหรับ C ++ ซึ่ง afaik ไม่เข้าเฝือก ดูลิงค์ในคำตอบ (ซึ่งฉันเปลี่ยนชื่อจาก Lint เป็น PC-Lint)
แดน

0

Valgrind เป็นตัวเลือกที่ดีสำหรับ Linux ภายใต้ MacOS X คุณสามารถเปิดใช้งานไลบรารี MallocDebug ซึ่งมีหลายตัวเลือกสำหรับการแก้ปัญหาการจัดสรรหน่วยความจำ (ดู manpage malloc ส่วน "สิ่งแวดล้อม" มีรายละเอียดที่เกี่ยวข้อง) OS X SDK ยังมีเครื่องมือที่เรียกว่า MallocDebug (โดยปกติจะติดตั้งใน / Developer / Applications / Performance Tools /) ที่สามารถช่วยคุณตรวจสอบการใช้งานและการรั่วไหล


0

การตรวจสอบ:

แก้ไขข้อบกพร่อง CRT

ควรหลีกเลี่ยง:

พอยน์เตอร์อัจฉริยะ boehm GC


0

การเปลี่ยน malloc, calloc และ reallloc ที่ดีคือ rmdebug ซึ่งค่อนข้างใช้งานง่าย มันเร็วกว่ามากในการ valgrind ดังนั้นคุณสามารถทดสอบโค้ดของคุณได้อย่างครอบคลุม แน่นอนว่ามันมีข้อเสียอยู่บ้างเมื่อคุณพบการรั่วไหลคุณอาจยังต้องใช้ valgrind เพื่อค้นหาตำแหน่งที่รั่วไหลและคุณสามารถทดสอบได้เฉพาะ mallocs ที่คุณทำโดยตรงเท่านั้น หาก lib รั่วเพราะคุณใช้ผิด rmdebug จะไม่พบ

http://www.hexco.de/rmdebug/


0

ตัวสร้างโปรไฟล์หน่วยความจำส่วนใหญ่ทำให้แอปพลิเคชัน Windows ที่ซับซ้อนขนาดใหญ่ของฉันช้าลงจนถึงจุดที่ผลลัพธ์ไม่มีประโยชน์ มีเครื่องมือหนึ่งที่ใช้ได้ดีในการค้นหาการรั่วไหลในแอปพลิเคชันของฉัน: UMDH - http://msdn.microsoft.com/en-us/library/ff560206%28VS.85%29.aspx


ฉันไม่เห็นว่าทำไมการชะลอตัวทำให้ผลลัพธ์ไร้ประโยชน์ แน่นอนว่าหน่วยความจำที่รั่วไหลจะรั่วไหลไม่ว่าโปรแกรมจะทำงานด้วยความเร็วเท่าใดก็ตาม ประเด็นของเครื่องมือเหล่านี้คือการหารอยรั่วแล้วปัญหาอยู่ที่ไหน? มันทำงานช้ามากจนคุณไม่สามารถทำให้มันครอบคลุมเส้นทางรหัสทั้งหมดเพื่อสร้างโปรไฟล์ได้หรือไม่?
underscore_d

-1

Mtraceดูเหมือนจะเป็นมาตรฐานในตัวสำหรับ linux ขั้นตอนมีดังนี้

  1. ตั้งค่าตัวแปรสภาพแวดล้อม MALLOC_TRACE ใน bash
    MALLOC_TRACE = / tmp / mtrace.dat
    ส่งออก MALLOC_TRACE;
  2. เพิ่ม#include <mcheck.h>ที่ด้านบนของไฟล์ต้นฉบับหลักของคุณ
  3. เพิ่มmtrace (); ที่จุดเริ่มต้นของ main และmuntrace ();ที่ด้านล่าง (ก่อนคำสั่ง return)
  4. คอมไพล์โปรแกรมของคุณด้วยสวิตช์ -g สำหรับข้อมูลการดีบัก
  5. รันโปรแกรมของคุณ
  6. แสดงข้อมูลการรั่วไหลด้วย
    mtrace your_prog_exe_name /tmp/mtrace.dat
    (ฉันต้องติดตั้งสคริปต์ mtrace perl ก่อนในระบบ fedora ของฉันด้วยyum install glibc_utils   )

mtrace ไม่มีประโยชน์อย่างยิ่งสำหรับ C ++
Erin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.