2016-06-09 3 views
1

Das folgende Programm nicht zu einer Assertion Ausfall auslösen:jemalloc nicht Erfassungsspeicherbeschädigung

int main(int argc, char **argv) 
{ 
    int * n = (int *)malloc(100); 
    //malloc_stats_print(nullptr, nullptr, "gablh"); 
    free(n); 
    *n += 1; 
    std::cerr << *n << std::endl; 
    for (int i = 0; i != 10; ++i) { 
    std::cerr << *(n+i) << std::endl; 
    } 
} 

Wenn ich das Programm laufen MALLOC_CONF="quarantine:32,abort:true,stats_print:true" ex_stats_pr

ich:

1515870811 
1515870811 
1515870810 
1515870810 
1515870810 
1515870810 
1515870810 
1515870810 
1515870810 
1515870810 
1515870810 

Gibt es eine Möglichkeit einen Abbruch mit jemalloc auslösen?

+0

Amitabha, Gibt es eine Chance, dass jemalloc irgendwelche Kontrollen durchführt?Ihr Programm wird kostenlos, versucht dann, Speicher zu beschädigen, etwas zu drucken und dann beendet, ohne zusätzliche Aufrufe an jemalloc. Zum Beispiel sollte die Option "Quarantäne" mit "valgrind" verwendet werden, nicht nur bei der normalen Ausführung ("valgrind" kann einige Prüfungen durchführen): http://linux.die.net/man/3/jemalloc "Der isolierte Speicher wird erst freigegeben, wenn er freigegeben wird aus der Quarantäne, ... Diese Funktion ist in Kombination mit Valgrind [2] von besonderem Nutzen, da sie Zugriffe auf unter Quarantäne gestellte Objekte erkennen kann. " – osgx

Antwort

0

Dies ist keine ganz direkte Antwort auf Ihre Frage, aber ...

undefiniertes Verhalten ist nicht definiert. Das Spiel mit freigelassener Erinnerung fällt in dieses Lager. Abhängig von Ihrer Implementierung Ihrer Speicherroutinen haben Sie möglicherweise eine "validate memory" -Funktion, die auf Ihrer freien Speicherliste läuft, um zu sehen, ob es eine Art von Korruption gab, aber selbst das wird nicht alles fangen (nicht vertraut mit jemalloc insbesondere mir selbst). Es könnte sein, dass Ihr oben beschriebener Code die Erinnerung trifft, die niemand interessiert und daher nicht gefangen wird. Heck, Ihre std::cerr Anweisung macht auch undefiniertes Verhalten, so dass Sie nicht einmal seine Werte vertrauen können (Denken Threads und OS greifen und Speicher ändern, etc.)

Dies ist einer der Gründe, dass Sie nicht direkt Zeiger verwenden in C++ wann immer möglich. Intelligente Zeiger und Container, die die Lebensdauer automatisch verwalten, verhindern fast alle diese Arten von Fehlern.

0

Sie erwarten, dass jemalloc einen Schreibvorgang in den freigegebenen Arbeitsspeicher und einige Lesevorgänge des freigegebenen Arbeitsspeichers erkennt.

Aber die jemalloc-Bibliothek verfügt nicht über diese Funktion. Sein Debug-Modus erkennt nur eine begrenzte Anzahl von Fehlern, die zu einer Speicherbeschädigung führen. Zum Beispiel Doppel-Frees.

Dies ist keine willkürliche Einschränkung, da eine Bibliothek wie jemalloc einfach keinen Speicherzugriffsfehler erkennen kann. Das heißt, als Bibliothek kann es malloc()/free() usw. leicht überladen und einen Exit-Handler installieren. Eine Debug-Modus-Implementierung kann somit effektiv einen begrenzten Satz von Überprüfungen implementieren. Und natürlich wählt jede Debug-Modus-Implementierung ihre eigenen Kompromisse. Zum Beispiel entdeckt jemalloc auch keine einfachen Pufferüberläufe während der freien Zeit, obwohl andere Bibliotheken mit Debugging-Fähigkeiten (z. B. Solaris 'libumem) einen leichten Mechanismus implementieren, bei dem die Integrität einiger spezieller nachlaufender Bytes geprüft wird.

Für eine Bibliothek wie jemalloc, um Lese-/Schreibvorgänge in freigegebenen Speicher zu erkennen, müsste es in jeder freigegebenen Region Debugger-Stil-Watches installieren, was ziemlich kompliziert wäre und einen erheblichen Laufzeit-Overhead zur Folge hätte - wenn dies für viele und große Zuweisungen skaliert würde , überhaupt.

Der Punkt ist: jemalloc ist das falsche Tool zum Erkennen von Schreibvorgänge in freigegebenen Speicher (A) und liest von freigegebenen Speicher (B).

Zum Beispiel ist die Address Sanitizer (-fsanitize=address), die mit GCC und Clang kommt, in der Lage zu erkennen (A), aber nicht (B). Und Valgrind() kann sowohl (A) als auch (B) erkennen und meldet diese Probleme als ungültiges Lesen/Schreiben in einen freigegebenen Block. Beide Tools haben sicherlich einen höheren Laufzeitaufwand als ein einfacher Debugging-Modus einer Zuweisungsbibliothek. Und da Valgrinds Ansatz eine CPU emuliert, ist sein Overhead viel höher als der von Address Sanitizer.