Tracking down Valgrind 40 bytes in 1 blocks are definitely lost in loss record
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.
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, 2022Comments
-
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 over 12 yearsWhat is cassie.cc line 49? Valgrind seems to be thinking you're calling
new
and then not callingdelete
on said object. -
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 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 over 12 yearsThe
cassie_free
function looks very suspicious. Why are you manually calling the destructor, and then invokingdelete
? And why the redundant check forNULL
? Also, hiding a pointer behind a typedef is usually considered bad practice, because it makes the resulting code so confusing to read. -
chrislovecnm over 12 yearsAs 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 over 12 years@chrislovecnm: Something like
Cassie *cassie = new Cassie(...)
.
-
-
chrislovecnm over 12 yearsHow can I isolate which pointer valgrind is bitching about? Is it the char* error?
-
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 over 12 yearsSorry if I am being dense. But specifically the pointer to cassie_t, not pointer inside of the struck.
-
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 calledcassie
. Where does it go next? -
chrislovecnm over 12 yearsI 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.