woher kommt das memory leak



  • Hallo,

    ich habe folgende funktion, wie kann hier valgrind ein memory leak erkennen und warum?

    gibt es noch eine bessere, moeglichkeit einen temp filenamen zu erzeugen?
    in der doku steht: "...it is possible that a file with that name is created by another process between the moment std::tmpnam returns and the moment this program attempts to use the returned name to create a file"

    std::string build_tmp_file_name() {
        return std::tmpnam(nullptr);
    }
    
    $ valgrind --tool=memcheck --leak-check=full ./main
    ==68971== Memcheck, a memory error detector
    ==68971== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==68971== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
    ==68971== Command: ./main
    ==68971== 
    --68971-- run: /usr/bin/dsymutil "./main"
    ==68971== 
    ==68971== HEAP SUMMARY:
    ==68971==     in use at exit: 35,786 bytes in 429 blocks
    ==68971==   total heap usage: 557 allocs, 128 frees, 177,393 bytes allocated
    ==68971== 
    ==68971== 1,024 bytes in 1 blocks are definitely lost in loss record 68 of 79
    ==68971==    at 0x10001C44B: malloc (in /usr/local/Cellar/valgrind/HEAD/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)
    ==68971==    by 0x10033D1A2: tmpnam_buf_allocate (in /usr/lib/system/libsystem_c.dylib)
    ==68971==    by 0x100556AF3: __pthread_once_handler (in /usr/lib/system/libsystem_pthread.dylib)
    ==68971==    by 0x100545F12: _os_once (in /usr/lib/system/libsystem_platform.dylib)
    ==68971==    by 0x100556A92: pthread_once (in /usr/lib/system/libsystem_pthread.dylib)
    ==68971==    by 0x10033D142: tmpnam (in /usr/lib/system/libsystem_c.dylib)
    ==68971==    by 0x100001320: build_tmp_file_name() (util.cpp:43)
    


  • HannesJ schrieb:

    Hallo,

    ich habe folgende funktion, wie kann hier valgrind ein memory leak erkennen und warum?

    vermutlich ein false positive.

    HannesJ schrieb:

    gibt es noch eine bessere, moeglichkeit einen temp filenamen zu erzeugen?

    besser ist relativ.
    ich verwende immer GUIDs für solche dinge.
    kollisionen sind da von haus aus schon sehr sehr unwahrscheinlich.

    und natürlich kann man das kollisions-problem vermeiden, indem man die funktion die den filenamen generiert auch gleich das file erzeugen lässt. dann kann die nämlich retries machen falls es schon eine datei mit dem namen gibt.



  • Hallo hustbaer,

    was kann ich gegen das false positive machen, valgrind anders starten?

    LG



  • Wohl weil tmpnam_buf_allocate 1024 Bytes per new/malloc anlegt und nicht wieder freigibt. Darin sehe ich aber kein Problem.

    std::string build_tmp_file_name() {
        static char buf[1024];
        return std::tmpnam(buf);
    }
    


  • HannesJ schrieb:

    gibt es noch eine bessere, moeglichkeit einen temp filenamen zu erzeugen?
    in der doku steht: "...it is possible that a file with that name is created by another process between the moment std::tmpnam returns and the moment this program attempts to use the returned name to create a file"

    Einfach die Duku weiterlesen.

    Although tmpnam() generates names that are difficult to guess, it is nevertheless possible that
    between the time that tmpnam() returns a pathname, and the time that the program opens it, another
    program might create that pathname using open(2), or create it as a symbolic link. This can lead to
    security holes. To avoid such possibilities, use the open(2) O_EXCL flag to open the pathname. Or
    better yet, use mkstemp(3) or tmpfile(3).

    Upps, hab "man tmpnam" genutzt statt "c++ tmpnam"



  • @HannesJ
    Es sollte aber eine Möglichkeit geben valgrind beizubringen bestimmte Allokationen zu ignorieren.
    In deinem Beispiel sollte es reichen valgrind beizubringen dass er alles ignorieren soll was von tmpnam_buf_allocate alloziert wird.

    Da ich valgrind nie verwende (ich verwende hauptsächlich Visual Leak Detector), kann ich dir leider nicht sagen wie/wo man das eintragen/angeben kann.

    EDIT: Hier sind suppression files dokumentiert, damit müsste das gehen: http://valgrind.org/docs/manual/mc-manual.html#mc-manual.suppfiles

    ps:

    volkard schrieb:

    Wohl weil tmpnam_buf_allocate 1024 Bytes per new/malloc anlegt und nicht wieder freigibt. Darin sehe ich aber kein Problem.

    std::string build_tmp_file_name() {
        static char buf[1024];
        return std::tmpnam(buf);
    }
    

    Ist das originale tmpname auch nicht threadsafe?
    Wenn die Funktion schon nen std::string zurückgibt, dann würde es ja sogar reichen einfach das static wegzumachen:

    std::string threadsafe_build_tmp_file_name() {
        char buf[1024];
        return std::tmpnam(buf);
    }
    


  • oder mit boost, was mir auch ein memory leak gibt... 😞
    ist boost version thread safe?

    std::string build_tmp_file_name() {
        return boost::lexical_cast<std::string>((boost::uuids::random_generator())());
    }
    

    volkard's version funktioniert ohne memory leak, da kein speicher am heap angelegt wird...ok...



  • hustbaer schrieb:

    Ist das originale tmpname auch nicht threadsafe?

    tmpname(NULL) ist nicht threadsafe und ich hab dummerweise nur das nachgebildet.

    hustbaer schrieb:

    Wenn die Funktion schon nen std::string zurückgibt, dann würde es ja sogar reichen einfach das static wegzumachen:

    Ja, viel besser.



  • oje:

    warning: 'tmpnam' is deprecated: This function is provided for compatibility reasons only. Due to security concerns
          inherent in the design of tmpnam(3), it is highly recommended that you use mkstemp(3) instead. [-Wdeprecated-declarations]
        return std::tmpnam(buf);
    

Log in to reply