malloc



  • 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ällt

    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 😉



  • 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.


Anmelden zum Antworten