มาบ่นเรื่อง Memory Leak ที่หายากสุดๆ ครับ
ก่อนอื่นเลย ผมเขียนโปรแกรม C++ และมีกฏว่า ระหว่าง test normal operation และ Graceful Exit ห้ามมี Memory Leak ขึ้นใน Output เด็ดขาด
ซึ่งมันก็ทำงานได้ดี แต่อยู่ๆ ก็เจอปัญหานี้
Detected Memory Leaks
{126241} normal block at 0x04279DC0, 8 bytes long.
Data: < l > 88 D8 6C 03 00 00 00 00
{126240} normal block at 0x0427A028, 8 bytes long.
Data: <l l > 6C D8 6C 03 00 00 00 00
จริงๆ มีเยอะกว่านี้ แต่ตัดมา ยกตัวอย่างเฉยๆ
ผมก็อุทาน เชี่ยอะไรวะ ใล่หาทั้งโปรแกรม ทั้งทำ CRT_DBG_ALLOC ส่วนอื่นๆ ขึ้น source line หมด แต่บรรทัดนี้กลับแปลก ไม่ขึ้น source line เลย แถมเลข block number / allocation number ดันเปลี่ยนไปเรื่อยๆ ทำให้ BreakAlloc เป็นไปไม่ได้
เลยใช้วิธี scope แคบลงมาเรื่อยๆ จนรู้ว่ามันมี function หนึ่งถ้ากดให้มันทำงาน จะ leak แน่นอน เลยโฟกัสแค่จุดนั้น และดึง code มาเทสในส่วน Test Form
ผลคือไม่มี Memory leak…..
Me: เชี่ยอะไรอีกวะเนี่ย สรุปใล่หาเพิ่มอีกราวๆ 7 ชั่วโมงแต่ก็ยังไม่เจออะไร
แต่พอทดสอบไปเรื่อยๆ เลยเจอ pattern leak ว่ามันมาจาก struct เพราะตอนสร้าง leak test ทุกแบบ pattern มันตรงกับตัวแปรประเภท struct พอดี และจำนวนจะเท่ากับ struct member ด้วย
เลยใล่ๆ นับ struct ทั้งโปรแกรม เลยเจอ candidate ที่น่าจะ leak อยู่สองตัว
เลยเพิ่ม member เข้าไปใน struct ด้วย concept ที่ว่า ถ้าจำนวน Block Leak เพิ่ม เช่น struct A เพิ่ม member ไป 1 ตัว / struct B เพิ่ม member ไปสองตัว
ถ้าจำนวน leak block ใหนเพิ่ม 1 หรือ 2 นั่นแหละผู้ร้าย!!
หลังจากเพิ่ม struct member ไป ผลคือ
{126241} normal block at 0x04279DC0, 8 bytes long.
Data: < l > 88 D8 6C 03 00 00 00 00
{126240} normal block at 0x0427A028, 8 bytes long.
Data: <l l > 6C D8 6C 03 00 00 00 00
{126239} normal block at 0x0427A0D0, 8 bytes long.
Data: <P l > 50 D8 6C 03 00 00 00 00
{126238} normal block at 0x0427A178, 8 bytes long.
Data: <4 l > 34 D8 6C 03 00 00 00 00
ชัดแล้ว struct B แน่นอน เพื่อความชัวร์เลยเพิ่ม member ไปอีก 1 ตัว > leak เพิ่มมาอีก 1 block จริงๆ
เลยไปใล่ๆ หาว่า struct นี้ใช้ตรงจุดใหนบ้าง พบว่ามันใช้งานอยู่จุดเดียว และ code เขียนแบบนี้
MyData tmpData;
ZeroMemory(&tmpData, sizeof(tmpData));
ชัดละ นี่แหละตัวการ เลยลบ ZeroMemory ออก > Leak ทั้งหมดที่เจอหายหมดทันที!
เกิดอะไรขึ้น
เดิมที struct MyData เขียนไว้แบบนี้
{
wchar_t data1[256];
wchar_t data2[256];
}
{
std::wstring data1;
std::wstring data2;
}