iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
Software Development

C++ 實務基礎經驗系列 第 21

資源管理 內存洩漏

  • 分享至 

  • xImage
  •  

資源管理 內存洩漏

今天來介紹一下內存洩漏相關的知識,野指針以及如何去發現這類問題的工具valgrind

野指針

野指針Day14 Crashlog中有提到其中一種,對空指針變量進行存取,參考下面例子

int *a = nullptr;
a[1] = 10; // 會導致程式崩潰

若對指針變數使用兩次以上freedelete也會造成野指針

char* str = (char *)malloc (1024);
free(str);
free(str); // 野指針一種

指針操作超出變量作用範圍也會,參考下面例子

Cat *pCat; // Cat 為class
{
    Cat cat2;
    pCat = &cat2; // cat2的生命週期,只存在大括號裡面
}
pCat->Meow(); // pCat變野指針

Valgrind

Valgrind是一款可以用來檢測程式是否有非法使用內存的工具,就是剛剛上面提到的野指針這類的問題,實際上我們用的是valgrind中的其中一個工具memcheck,他裡面還有很多工具,針對緩存、多線程等檢測工具,這邊就暫時不介紹了

安裝

如果是用之前dockerfile啟的環境,valgrind應該是已經安裝好的,因為CentOS devtoolset中就有包含valgrind,這邊真的要安裝也可以參考下面的指令

wget http://sourceware.org/pub/valgrind/valgrind-3.15.0.tar.bz2
tar -jxvf valgrind-3.15.0.tar.bz2
cd valgrind-3.15.0
./configure
make
make install

使用

這邊就先用上次空指針的例子,來用valgrind檢查看看

int main()
{
    int *a = nulltpr;
    a[1] = 10;

    return 0;
}
valgrind --tool=memcheck --leak-check=full ./wild_pointer 
# valgrind 檢測結果,可以看到valgrind幫我們判斷出哪一行非法使用內存
==28157== Memcheck, a memory error detector
==28157== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28157== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==28157== Command: ./wild_pointer
==28157== 
==28157== Invalid write of size 4
==28157==    at 0x400AFC: main (WildPointer.cpp:35)
==28157==  Address 0x4 is not stack'd, malloc'd or (recently) free'd
==28157== 
==28157== 
==28157== Process terminating with default action of signal 11 (SIGSEGV)
==28157==  Access not within mapped region at address 0x4
==28157==    at 0x400AFC: main (WildPointer.cpp:35)
==28157==  If you believe this happened as a result of a stack
==28157==  overflow in your program's main thread (unlikely but
==28157==  possible), you can try to increase the size of the
==28157==  main thread stack using the --main-stacksize= flag.
==28157==  The main thread stack size used in this run was 8388608.
==28157== 
==28157== HEAP SUMMARY:
==28157==     in use at exit: 0 bytes in 0 blocks
==28157==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==28157== 
==28157== All heap blocks were freed -- no leaks are possible
==28157== 
==28157== For counts of detected and suppressed errors, rerun with: -v
==28157== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

重複釋放記憶體

int main()
{
    char* str = (char *)malloc (1024);
    free(str);
    free(str); 

    return 0;
}
valgrind --tool=memcheck --leak-check=full ./wild_pointer 
# valgrind 檢測結果,檢測出哪邊非法,下面的HEAP SUMMARY可以看到申請一次,可以卻釋放兩次
==29416== Memcheck, a memory error detector
==29416== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29416== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==29416== Command: ./wild_pointer
==29416== 
==29416== Invalid free() / delete / delete[] / realloc()
==29416==    at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==29416==    by 0x400B19: main (WildPointer.cpp:38)
==29416==  Address 0x5a24040 is 0 bytes inside a block of size 1,024 free'd
==29416==    at 0x4C2ACBD: free (vg_replace_malloc.c:530)
==29416==    by 0x400B0D: main (WildPointer.cpp:37)
==29416==  Block was alloc'd at
==29416==    at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==29416==    by 0x400AFD: main (WildPointer.cpp:36)
==29416== 
cat  delete
 Meow!
==29416== 
==29416== HEAP SUMMARY:
==29416==     in use at exit: 0 bytes in 0 blocks
==29416==   total heap usage: 1 allocs, 2 frees, 1,024 bytes allocated
==29416== 
==29416== All heap blocks were freed -- no leaks are possible
==29416== 
==29416== For counts of detected and suppressed errors, rerun with: -v
==29416== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

未釋放記憶體

int main(int argc, char const *argv[])
{
    char* str = (char *)malloc (1024);
    return 0;
}
valgrind --tool=memcheck --leak-check=full ./wild_pointer 
# valgrind 檢測結果,檢測出未釋放的部分
==9567== Memcheck, a memory error detector
==9567== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==9567== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==9567== Command: ./wild_pointer
==9567== 
==9567== 
==9567== HEAP SUMMARY:
==9567==     in use at exit: 1,024 bytes in 1 blocks
==9567==   total heap usage: 1 allocs, 0 frees, 1,024 bytes allocated
==9567== 
==9567== 1,024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==9567==    at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==9567==    by 0x400AA5: main (WildPointer.cpp:34)
==9567== 
==9567== LEAK SUMMARY:
==9567==    definitely lost: 1,024 bytes in 1 blocks
==9567==    indirectly lost: 0 bytes in 0 blocks
==9567==      possibly lost: 0 bytes in 0 blocks
==9567==    still reachable: 0 bytes in 0 blocks
==9567==         suppressed: 0 bytes in 0 blocks
==9567== 
==9567== For counts of detected and suppressed errors, rerun with: -v
==9567== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

上一篇
資源管理 右值
下一篇
併發相關 mutex
系列文
C++ 實務基礎經驗25
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言