Tracking down Valgrind 40 bytes in 1 blocks are definitely lost in loss record

27,761

The Valgrind message means that you have allocated some memory (at line 49 of cassie.cc), but you are losing/overwriting the pointer without ever invoking delete on it.

You should track where that pointer value goes (either in the debugger or by inspection), in order to spot where it's being lost. You might consider putting a debugger watchpoint on the pointer; this would identify the problem in the scenario where it's being overwritten. If you're going to do this in the debugger, make sure you've compiled with no optimisations enabled.

Share:
27,761
chrislovecnm
Author by

chrislovecnm

Deep experience in both IT and Software in both technical and leadership roles. For the past 5 years, he has focused on building a business that implements Cloud and Big Data solutions for a number of companies including multiple Fortune 500 companies such as Cisco, Coca Cola, Warner Bros, CenturyLink, AT&T, Johnson & Johnson, and First Data. Specialties Cassandra, Apache Spark, Cloud DevOps, Grails, Apache Camel, ActiveMQ, Redis, Integration, Elastic (ELK) Technical Dragon Fighting Upon Request

Updated on July 09, 2022

Comments

  • chrislovecnm
    chrislovecnm almost 2 years

    I am new to Valgrind (and my C/C++ is rusty) and I am getting an error:

    40 bytes in 1 blocks are definitely lost in loss record 35 of 111
    ==26930==    at 0x4C275C2: operator new(unsigned long) (vg_replace_malloc.c:261)
    ==26930==    by 0x5EFAFDB: cassie_init_with_timeout (cassie.cc:49)
    ==26930==    by 0x46E647: ngx_cassandra_upstream_get_peer (ngx_cassandra_upstream.c:274)
    ==26930==    by 0x41E00B: ngx_event_connect_peer (ngx_event_connect.c:25)
    

    I am guessing that the char *last_error_string is giving me fits, but how do I track this down?

    Here is my source:

    Creation of the Cassie object:

    cassie_t cassie;
    
    char *error = NULL;
    cassie = new Cassie(host,port,error,CASSIE_ERROR_NONE);  /* this is line 49 in the above valgrind trace */
    cassie->cassandra               = cassandra;
    

    cassie_t is a struct of an Object.

    typedef struct Cassie *cassie_t;
    

    I have this because I am wrapping a C++ lib in order to call it from C.

    Here is our object cassie_private.h

    #include <string>
    #include "libcassandra/cassandra.h"
    #include "libcassie/cassie.h"
    
    #ifdef __cplusplus
    namespace libcassie {
        using namespace std;
        using namespace boost;
        class Cassie
        {
          // TODO do we need the host and the port??
          public:
                const char*     host;
            int             port;
            cassie_error_code_t last_error_code;
            char*           last_error_string; /* I am guessing my memory problem is here */
            tr1::shared_ptr<libcassandra::Cassandra>                    cassandra;
    
            Cassie();
            Cassie(const char *&host, int &port,char* &in_error_str, cassie_error_code_t error);
            ~Cassie();
        };
    #else
        typedef
             struct Cassie
               Cassie; /* this is for in C */
    #endif
    
    }
    
    #endif
    

    Here is cassie_private.cc

    #include "cassie_private.h"
    
    namespace libcassie {
    
    using namespace std;
    using namespace libcassandra;
    
    Cassie::Cassie() :
        host(),
        port(0),
        last_error_code(),
        last_error_string(NULL),
        cassandra()
    {}
    
    Cassie::Cassie(const char * &in_host, int &in_port, char* &in_error_str, cassie_error_code_t error) :
            host(in_host),
            port(in_port),
            last_error_code(error),
            last_error_string(in_error_str),
            cassandra()
    {}
    
    Cassie::~Cassie() {
        if(last_error_string) delete last_error_string;
    }
    
    }
    

    This is being called in order to delete the Object at the end of use:

    void cassie_free(cassie_t cassie) {
    
        if(!cassie) return;
        cassie->~Cassie();
        if(cassie) delete cassie;
    
    }
    

    How do I track this memory leak down?

    • Dan Fego
      Dan Fego over 12 years
      What is cassie.cc line 49? Valgrind seems to be thinking you're calling new and then not calling delete on said object.
    • Oliver Charlesworth
      Oliver Charlesworth over 12 years
      @Dan: It's worse than that; the Valgrind message means that the OP is calling new and then discarding the pointer at some point.
    • Dan Fego
      Dan Fego over 12 years
      @OliCharlesworth: Yeah, that's more correct. Though often the cause is letting a pointer leave scope or get overwritten when you no longer need it, so you should have freed it at some point. :)
    • Oliver Charlesworth
      Oliver Charlesworth over 12 years
      The cassie_free function looks very suspicious. Why are you manually calling the destructor, and then invoking delete? And why the redundant check for NULL? Also, hiding a pointer behind a typedef is usually considered bad practice, because it makes the resulting code so confusing to read.
    • chrislovecnm
      chrislovecnm over 12 years
      As I mentioned my C/C++ is rusty as hell. How would I not use the a typedef in this instance? Use the Cassie struct itself?
    • Oliver Charlesworth
      Oliver Charlesworth over 12 years
      @chrislovecnm: Something like Cassie *cassie = new Cassie(...).
  • chrislovecnm
    chrislovecnm over 12 years
    How can I isolate which pointer valgrind is bitching about? Is it the char* error?
  • Oliver Charlesworth
    Oliver Charlesworth over 12 years
    @chrislovecnm: It tells you to look at line 49 of cassie.cc. Follow the value that new returns on that line.
  • chrislovecnm
    chrislovecnm over 12 years
    Sorry if I am being dense. But specifically the pointer to cassie_t, not pointer inside of the struck.
  • Oliver Charlesworth
    Oliver Charlesworth over 12 years
    @chrislovecnm: I'm not sure what you mean. From your code snippet, I can now see that you're assigning the result of new to a pointer called cassie. Where does it go next?
  • chrislovecnm
    chrislovecnm over 12 years
    I think I need to clean up the code w/o the typedef, and track it from there. This is some open source code that was not externed into C code well.