this code is obviously leaking the memory allocated by curl_easy_init() 
    
    
    import libcurl
    
    proc initializer_generator() : proc =
        var started = false
        proc fun() =
            if started:
                discard global_init(GLOBAL_DEFAULT)
        return fun
    
    let init_curl = initializer_generator()
    init_curl()
    discard easy_init()
    

and if I run it with valgrind i get 
    
    
    ==20004== Memcheck, a memory error detector
    ==20004== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==20004== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==20004== Command: ./gc_test
    ==20004==
    ==20004==
    ==20004== HEAP SUMMARY:
    ==20004==     in use at exit: 101,649 bytes in 78 blocks
    ==20004==   total heap usage: 3,394 allocs, 3,316 frees, 210,683 bytes 
allocated
    ==20004==
    ==20004== 37,967 (21,256 direct, 16,711 indirect) bytes in 1 blocks are 
definitely lost in loss record 17 of 17
    ==20004==    at 0x4C2EF35: calloc (in 
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
    ==20004==    by 0x5B5F35E: ??? (in /usr/lib/libcurl.so.4.5.0)
    ==20004==    by 0x5B6C3D5: curl_easy_init (in /usr/lib/libcurl.so.4.5.0)
    ==20004==    by 0x109E6C: NimMainModule (in 
/home/walter/code/nim_test/gc_test)
    ==20004==    by 0x109CC4: NimMainInner (in 
/home/walter/code/nim_test/gc_test)
    ==20004==    by 0x109D00: NimMain (in /home/walter/code/nim_test/gc_test)
    ==20004==    by 0x109D4E: main (in /home/walter/code/nim_test/gc_test)
    ==20004==
    ==20004== LEAK SUMMARY:
    ==20004==    definitely lost: 21,256 bytes in 1 blocks
    ==20004==    indirectly lost: 16,711 bytes in 4 blocks
    ==20004==      possibly lost: 0 bytes in 0 blocks
    ==20004==    still reachable: 63,682 bytes in 73 blocks
    ==20004==         suppressed: 0 bytes in 0 blocks
    ==20004== Reachable blocks (those to which a pointer was found) are not 
shown.
    ==20004== To see them, rerun with: --leak-check=full --show-leak-kinds=all
    ==20004==
    ==20004== For counts of detected and suppressed errors, rerun with: -v
    ==20004== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
    
    

so far, so good.. but If I replace the last line with this 
    
    
    let curl = easy_init()
    

this is what I get when I run the program with valgrind 
    
    
    ==23000== Memcheck, a memory error detector
    ==23000== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==23000== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
    ==23000== Command: ./gc_test
    ==23000==
    ==23000==
    ==23000== HEAP SUMMARY:
    ==23000==     in use at exit: 63,682 bytes in 73 blocks
    ==23000==   total heap usage: 3,389 allocs, 3,316 frees, 172,716 bytes 
allocated
    ==23000==
    ==23000== LEAK SUMMARY:
    ==23000==    definitely lost: 0 bytes in 0 blocks
    ==23000==    indirectly lost: 0 bytes in 0 blocks
    ==23000==      possibly lost: 0 bytes in 0 blocks
    ==23000==    still reachable: 63,682 bytes in 73 blocks
    ==23000==         suppressed: 0 bytes in 0 blocks
    ==23000== Reachable blocks (those to which a pointer was found) are not 
shown.
    ==23000== To see them, rerun with: --leak-check=full --show-leak-kinds=all
    ==23000==
    ==23000== For counts of detected and suppressed errors, rerun with: -v
    ==23000== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
    
    

I really cannot understand how can it not leak memory anymore: the only right 
way to free the memory allocated by easy_init is to call easy_cleanup on the 
same pointer, which cannot happen since the compiler doesn't know anything 
about it, in the same way I don't think it is possible for the compiler not to 
call easy_init only because the returned value is not used, since it doesn't 
know whether it has side effects or not. What's happening under the hood, then? 

Reply via email to