malloc
-
ich hab ein kleines programm das sehr oft malloc aufruft.
deswegen habe ich mir zwei eigene mallocs definiert.eines heißt malloc_release das nur überprüft ob malloc null zurückgegeben hat und eines heißt malloc_debug das überprüft ob malloc null zurückgegeben hat und einen counter um 1 hochzählt. (ein entsprechendes pendant gibt es auch für die funktion free die den counter um 1 verringert).
im programm möchte ich gerne umstellen können ob ich jetzt die debug oder die release version haben will. per präprozessordirektive
#define DEBUGGING
und jetzt soll überall wo myMalloc stand myMalloc_DEBUG stehen.
weiß jemand einen Rat wie ich das am bestne umsetzen konnte?
-
#include <stdio.h> #ifdef _DEBUG #define MY_MALLOC malloc_debug #else #define MY_MALLOC malloc_release #endif void malloc_release(); void malloc_debug(); int main() { MY_MALLOC(); return 0; } void malloc_release() { printf("Release.\n"); } void malloc_debug() { printf("Debug.\n"); }
-
Man könnte natürlich auch sowas machen
#include<stdio.h> int my_malloc(size_t size); int main(int argc, char **argv) { my_malloc(5); return 0; } int my_malloc(size_t size) { /* original-malloc aufrufen usw*/ #ifdef _DEBUG cnt++; #endif }
-
Statt dem Client-Code ein Makro aufs Auge zu drücken, das Scopes etc. nicht respektiert, scheint mir eine Funktionszeigerkonstante sinnvoller:
#include <stddef.h> #include <stdio.h> extern void*(* const my_malloc)(size_t); void *my_malloc_debug(size_t x) { printf("Debug: %d\n", x); return NULL; } void *my_malloc_release(size_t x) { printf("Release: %d\n", x); return NULL; } #ifdef DEBUGGING void *(*const my_malloc)(size_t) = &my_malloc_debug; #else void *(*const my_malloc)(size_t) = &my_malloc_release; #endif int main(void) { my_malloc(10); return 0; }
Das heißt, sofern linux_c89-Lösung nicht sowieso sinnvoller ist - der Ansatz, zwischen Funktionen auszuwählen, macht eigentlich nur dann Sinn, wenn diese grundverschiedene Dinge tun. Wenn es nur darum geht, ein paar Debug-Ausgaben aus der Release-Version rauszunehmen, nimmt man diese besser direkt aus dem Funktionskörper hinaus.
-
auch wenn viele ihre eigenen malloc funktionen schreiben, finde ich das nicht so toll. malloc() kennt jeder c progger und deine eigene nicht. darüber hinaus gibt es keine alternative nicht gegen 0 zu testen, egal ob debugging oder release.
@edit naja man kann sich was mit longjmp() o.ä. zusammen bauen, dann kannst aber auch gleich c++ verwenden.
-
Ich verstehe auch nicht ganz was das problem ist statt
void *ptr; ptr=my_malloc(1234);
void *ptr if(!(ptr=malloc(1234))){ return ENOMEM; /* *oder: * errno=ENOMEM; * return -1; */ }
zu machen (es geht hier um eine Zeile oder so)
Aber jeder wies ihm gefällt
-
Vielleicht verstehe ich es falsch, aber es macht dieses malloc_release doch eigentlich nichts? Dann kann man es z.B. auch so machen:
#include <stdio.h> #include <stdlib.h> #define DEBUGGING #ifdef DEBUGGING void *(*const malloc_copy)(size_t) = malloc; #define malloc malloc_debug void *malloc_debug (size_t size) { puts ("debug"); return malloc_copy (size); } #endif int main (void) { void *foo = malloc (1); free (foo); return 0; }
Ich weiss aber nicht ob das vielleicht irgendwelche internen Möglichkeiten seitens des Compilers torpediert...
-
linux_c89 schrieb:
Ich verstehe auch nicht ganz was das problem ist statt
void *ptr; ptr=my_malloc(1234);
void *ptr if(!(ptr=malloc(1234))){ return ENOMEM; /* *oder: * errno=ENOMEM; * return -1; */ }
zu machen (es geht hier um eine Zeile oder so)
Aber jeder wies ihm gefälltdas beispiel ist nicht günstig, da im ersten fall die aufrufende funktion keine rückmeldung erhält ob malloc erfolgreich war. und einfach so in nen errorhandler springen und dort verharren ist nicht die beste lösung. wir wollen doch keine äpfel mit birnen vergleichen oder
-
Um ehrlich zu sein, verstehe ich nicht, was der Sinn der vielen debug/release mallocs. Am Ende muss ich eh doch überprüfen, ob debug/release malloc NULL zurückgeliefert hat.
-
Anstelle ein malloc_debug zu schreiben, würde ich eher LD_PRELOAD (oder die entsprechende Alternative auf dem System deiner Wahl) benutzen und dann wahlweise malloc mit einer Debugvariante überschreiben. LD_PRELOAD sagt dem dynamischen Linker, dass er eine bestimmte Bibliothek vor allen anderen Bibliotheken laden soll. Damit kann man dann gezielt Symbole in den Bibliotheken überschreiben. Alternativ kann man natürlich gleich zB DUMA benutzen, was noch auf mehr Fehler prüft und das ganze PRELOAD Zeugs schon für diverse Systeme macht.
Der Vorteil von dem ganzen ist einfach, dass man sein Programm nicht neu kompilieren muss (und dadurch möglicherweise das Verhalten ändert, weil man zB anderen DEBUG-Code reinkompiliert).
(Für Linux gäbe es alternativ natürlich noch Valgrind, wenn man Speicherlücken uvm. finden will.)
-
das beispiel ist nicht günstig, da im ersten fall die aufrufende funktion keine rückmeldung erhält ob malloc erfolgreich war. und einfach so in nen errorhandler springen und dort verharren ist nicht die beste lösung. wir wollen doch keine äpfel mit birnen vergleichen oder
Es ging mir eigentlich darum dass viele doch diese "mallocfunktionen" so schreiben
void *my_malloc(size_t size) { void *ptr; if(!(ptr=malloc(size))) { fprintf(stderr,"not enough memory"); exit(1); } return ptr; }
um sich halt diese Überprüfung zu sparen
auch wenn viele ihre eigenen malloc funktionen schreiben, finde ich das nicht so toll
Ich dachte das bezieht sich auf diese "automatisch-auf-0-überprüf-Funktionen"
-
Man kann ja auch einfach versuchen Speicher freizugeben, wenn ein malloc fehlschlägt. zB in dem man einen Cache freigibt. Nur weil man malloc überschreibt, heißt es ja nicht, dass man die Fehlerüberprüfung los werden will.