Heim  >  Artikel  >  System-Tutorial  >  Ein leistungsstarkes Tool zur Behebung von Speicherproblemen unter Linux

Ein leistungsstarkes Tool zur Behebung von Speicherproblemen unter Linux

王林
王林nach vorne
2024-02-12 22:20:141050Durchsuche

1. Speicherverlust

Speicherleck bedeutet, dass der dynamisch zugewiesene Heap-Speicher im Programm nicht freigegeben wird oder aus irgendeinem Grund nicht freigegeben werden kann, was zu einer Verschwendung von Systemspeicher führt, was schwerwiegende Folgen wie eine Programmverlangsamung oder sogar einen Systemabsturz nach sich ziehen kann.

Ein leistungsstarkes Tool zur Behebung von Speicherproblemen unter Linux

Funktionen

  • Verschleierung Da der Speicherverlust auftritt, weil der Speicherblock nicht freigegeben wird, handelt es sich eher um einen Unterlassungsfehler als um einen Fehlerfehler
  • Kumulative Speicherlecks führen in der Regel nicht direkt zu beobachtbaren Fehlersymptomen, sondern akkumulieren sich allmählich, wodurch die Gesamtleistung des Systems verringert wird und im Extremfall ein Systemabsturz verursacht werden kann. Die intuitivste Frage ist, warum unser Programm normal startet und nach einer Weile abnormal beendet wird.

Speicherlecks bedeuten nicht das physische Verschwinden des Speichers, sondern dass die Anwendung, nachdem sie aufgrund von Nutzungsfehlern ein bestimmtes Speichersegment zugewiesen hat, die Kontrolle über das Speichersegment verliert, bevor es freigegeben wird, was dazu führt, dass der Speicher nicht freigegeben wird . Und verschwendet.

Ursache

Wenn wir während der Programmentwicklung dynamische Speichervariablen verwenden, treten zwangsläufig Probleme bei der Speicherverwaltung auf. Der im Programm dynamisch zugewiesene Speicherplatz muss nach der Ausführung des Programms freigegeben werden. Speicherlecks, die dadurch verursacht werden, dass dynamisch zugewiesener Speicherplatz nicht freigegeben wird, sind die Hauptprobleme bei der Verwendung dynamischer Speichervariablen. Unter normalen Umständen verwenden Entwickler häufig die vom System bereitgestellten grundlegenden Speicherverwaltungsfunktionen wie malloc、realloc、calloc、free usw., um die Zuweisung und Freigabe von dynamischem Speichervariablenspeicherplatz abzuschließen. Bei der Entwicklung von Programmen, die viele dynamische Speichervariablen verwenden und häufig Funktionsaufrufe verwenden, treten jedoch häufig Speicherverwaltungsfehler auf.

2. So beheben Sie Speicherlecks

Während unseres täglichen Entwicklungsprozesses werden wir unweigerlich auf Speicherverluste stoßen. Da ein Speicherverlust aufgetreten ist, müssen wir das Speicherverlustproblem beheben. Ich glaube, dass Sie häufig die folgenden Tools verwenden, um Speicherprobleme zu beheben:

  • memwatch
  • mtrace
  • dmalloc
  • ccmalloc
  • valgrind
  • debug_new

Heute stellt Mu Rong nicht das oben genannte Fehlerbehebungstool vor, sondern ein weiteres Tool zur Fehlerbehebung bei Speicherlecks: AddressSanitizer (ASan). Es unterstützt Linux, OS, Android und andere Plattformen. Es kann nicht nur Speicherlecks erkennen, es ist ein Tool zur Speicherfehlererkennung, das viele häufige Speicherprobleme erkennen kann.

Erkennung häufiger Speicherprobleme:

  • Speicherverlust
  • Grenzüberschreitender Zugang
  • Freier Speicher verwendet

3. AddressSanitizer (ASan)-Tool

Address Sanitizer (ASan) ist ein schnelles Tool zur Speicherfehlererkennung. Es ist sehr schnell und verlangsamt das Programm nur etwa zweimal (viel schneller als Valgrind). Es enthält ein Compiler-Instrumentierungsmodul und eine Laufzeitbibliothek, die malloc()/free()-Alternativen bereitstellt. Ab gcc 4.8 wird AddressSanitizer Teil von gcc. Um ein besseres Erlebnis zu erzielen, ist es natürlich am besten, Version 4.9 und höher zu verwenden, da der AddressSanitizer von gcc 4.8 noch nicht perfekt ist und der größte Nachteil darin besteht, dass keine Symbolinformationen vorhanden sind.

Anwendung:

  • Kompilieren und verknüpfen Sie Ihr Programm mit der Option -fsanitize=address.
  • Kompilieren Sie mit -fno-omit-frame-pointer, um einen verständlicheren Stack-Trace zu erhalten.
  • Optionale Kompilierung der Optimierungsstufe -O1 oder höher
gcc -fsanitize=address -o main -g main.c

Speicherleck

#include 

void Fun()
{
    char *pM = malloc(10);
}

int main(int argc, char *argv[])
{
    Fun();
    return 0;
}

Ausgabe kompilieren

Ein leistungsstarkes Tool zur Behebung von Speicherproblemen unter Linux

Speicher außerhalb der Grenzen

  • Stapelspeicher außerhalb der Grenzen
#include 
#include 

void Fun()
{
    char *pM = malloc(10);
}

int main(int argc, char *argv[])
{
    //Fun();
    int *array = malloc(10*sizeof(int));
    if(array)
    {
            memset(array, 0, 10*sizeof(int));
    }
    int res = array[10];

    free(array);
    return 0;
}

Ausgabe ausführen

ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ gcc -fsanitize=address -o main -g main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ls
main  main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ./main
=================================================================
==3234==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400000dff8 at pc 0x000000400854 bp 0x7ffccc9253d0 sp 0x7ffccc9253c0
READ of size 4 at 0x60400000dff8 thread T0
    #0 0x400853 in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:16
    #1 0x7fafc87a883f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
    #2 0x4006f8 in _start (/home/ubuntu/workspace_ex/Linux/ASan/main+0x4006f8)

0x60400000dff8 is located 0 bytes to the right of 40-byte region [0x60400000dfd0,0x60400000dff8)
allocated by thread T0 here:
    #0 0x7fafc8bea602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x4007f7 in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:11
    #2 0x7fafc87a883f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ubuntu/workspace_ex/Linux/ASan/main.c:16 main
Shadow bytes around the buggy address:
  0x0c087fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c087fff9bf0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
  0x0c087fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==3234==ABORTING
  • Globales Gedächtnis außerhalb der Grenzen
#include 
#include 

int g_nArray[10] = {0};

void Fun()
{
    char *pM = malloc(10);
}

int main(int argc, char *argv[])
{
    //Fun();

    /*
    int *array = malloc(10*sizeof(int));
    if(array)
    {
            memset(array, 0, 10*sizeof(int));
    }
    int res = array[10];

    free(array);
    */

    int nIndex = g_nArray[10];
    return 0;
}

Ausgabe ausführen

ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ gcc -fsanitize=address -o main -g main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ls
main  main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ./main 
=================================================================
==4196==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000601128 at pc 0x00000040083e bp 0x7ffc8a332540 sp 0x7ffc8a332530
READ of size 4 at 0x000000601128 thread T0
    #0 0x40083d in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:26
    #1 0x7fda216a583f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
    #2 0x400718 in _start (/home/ubuntu/workspace_ex/Linux/ASan/main+0x400718)

0x000000601128 is located 0 bytes to the right of global variable 'g_nArray' defined in 'main.c:4:5' (0x601100) of size 40
SUMMARY: AddressSanitizer: global-buffer-overflow /home/ubuntu/workspace_ex/Linux/ASan/main.c:26 main
Shadow bytes around the buggy address:
  0x0000800b81d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b81e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b81f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0000800b8220: 00 00 00 00 00[f9]f9 f9 f9 f9 f9 f9 00 00 00 00
  0x0000800b8230: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8250: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8260: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0000800b8270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==4196==ABORTING
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ 

Freien Speicher nutzen

#include 
#include 
#include 

int g_nArray[10] = {0};
int *p;

void Fun()
{
    char *pM = malloc(10);
}

void Fun1()
{
    int nVar = 0;
    p = &nVar;
}

int main(int argc, char *argv[])
{
    //Fun();

    int *array = malloc(10*sizeof(int));
    if(array)
    {
            memset(array, 0, 10*sizeof(int));
    }
    int res = array[10];

    free(array);

    array[0] = 1;

    return 0;
}

Ausgabe ausführen

ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ gcc -fsanitize=address -o main -g main.c
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$ ./main
=================================================================
==4954==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60400000dff8 at pc 0x000000400b68 bp 0x7ffefbe3b170 sp 0x7ffefbe3b160
READ of size 4 at 0x60400000dff8 thread T0
    #0 0x400b67 in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:28
    #1 0x7f1bbb78983f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)
    #2 0x400928 in _start (/home/ubuntu/workspace_ex/Linux/ASan/main+0x400928)

0x60400000dff8 is located 0 bytes to the right of 40-byte region [0x60400000dfd0,0x60400000dff8)
allocated by thread T0 here:
    #0 0x7f1bbbbcb602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
    #1 0x400b0b in main /home/ubuntu/workspace_ex/Linux/ASan/main.c:23
    #2 0x7f1bbb78983f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2083f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/ubuntu/workspace_ex/Linux/ASan/main.c:28 main
Shadow bytes around the buggy address:
  0x0c087fff9ba0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bb0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bc0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9bd0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9be0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x0c087fff9bf0: fa fa fa fa fa fa fa fa fa fa 00 00 00 00 00[fa]
  0x0c087fff9c00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c087fff9c40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==4954==ABORTING
ubuntu@ubuntu:~/workspace_ex/Linux/ASan$

AddressSanitizer能检测的错误类型

错误类型 错误描述
(heap) Use after free 访问堆上已被释放的内存
Heap buffer overflow 堆上缓冲区访问溢出
Stack buffer overflow 栈上缓冲区访问溢出
Global buffer overflow 全局缓冲区访问溢出
Use after return 访问栈上已被释放的内存
Use after scope 栈对象使用超过定义范围
Initialization order bugs 初始化命令错误
Memory leaks 内存泄漏
  • Weitere Informationen finden Sie auf der offiziellen Website

Weitere Informationen finden Sie in der offiziellen Dokumentation von Google: https://github.com/google/sanitizers/wiki/AddressSanitizer

Fazit

ASan ist ein sehr gutes Tool zum Erkennen von Speicherproblemen und ist einfach zu verwenden. Beim Kompilieren müssen Sie nur -fsanitize=address -g auswählen Umgebungsvariable ASAN_OPTIONS zur Erkennung vieler Speicherprobleme. Wenn etwas unklar ist, können Sie die offiziellen Anweisungen zum Austausch und Lernen lesen.

Das obige ist der detaillierte Inhalt vonEin leistungsstarkes Tool zur Behebung von Speicherproblemen unter Linux. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:lxlinux.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen