std::string memory leak - c++

I've got this class AppController and the function connectPlayer:
/* AppController.h */
class AppController
{
// Some other declarations ...
private:
static const string TAG;
};
/* AppController.cpp */
#include "AppController.h"
const string AppController::TAG = "AppController";
AppController::AppController() {
/* some code here...*/
}
void AppController::connectPlayer() {
std::string port;
std::string host;
port = CM->getMenu()->getData("PORT");
host = CM->getMenu()->getData("HOST");
this->setState("Connecting...");
Logger::info(TAG, "Port: " + port);
Logger::info(TAG, "Host: " + host);
}
And when I execute the program, I get this from valgrind:
==7848== 25 bytes in 1 blocks are definitely lost in loss record 160 of 671
==7848== at 0x402842F: operator new(unsigned int) (vg_replace_malloc.c:255)
==7848== by 0x4210A83: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==7848== by 0x4212CF7: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==7848== by 0x4212E65: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
==7848== by 0x8080501: AppController::connectPlayer() (in /home/maine/Escritorio/taller7542/UltimaVersion/src/main)
Any ideas? Thank you in advance!

You have std::string objects in global scope: AppController::TAG.
When application finished in not very normal way you've got these kind of valgrind errors for global objects. Probably nothing to worry.
If you (cannot/don't want to) change your program - read this doc: http://valgrind.org/docs/manual/manual-core.html#manual-core.suppress to get rid of this very error.

Sometimes, valgrind gives false positives. This means that even if valgrind says you lose memory, actually you don't.
The only thing to worry about is when you call the exit() function, as explained in this question.
If you do not want to see these warnings any more, you can create a suppressions file giving valgrind some information on which errors to ignore.

I had seen this issue once when I had a string in a class in global scope. Valgrind kept complaining that I was leaking memory. I just "deleted" the object at exit and the error was gone.

Related

valgrind memory access error when accessing result of string::c_str()

So I was writing some networking code when I ran into the strangest memory issue and I cant properly sort out what might be going on here. I am wondering if there might be some sort of implication in c_str() that I am not properly observing.
So here is the code with the error in it. (There is also a freeing error but I made this function as just a pet project).
#include <netdb.h> // for AF_UNSPEC, AF_INET, AF_INET6
#include <stdint.h> // for uint16_t, etc.
#include <sys/types.h> // for AF_UNSPEC, AF_INET, AF_INET6
#include <sys/socket.h> // for AF_UNSPEC, AF_INET, AF_INET6
#include <string> // for std::strin
#include <stdio.h>
#include <string.h>
int main() {
uint16_t port = 2098;
struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET6; // IPv6 (also handles IPv4 clients)
hints.ai_socktype = SOCK_STREAM; // stream
hints.ai_flags = AI_PASSIVE; // use wildcard "INADDR_ANY"
hints.ai_protocol = IPPROTO_TCP; // tcp protocol
hints.ai_canonname = nullptr;
hints.ai_addr = nullptr;
hints.ai_next = nullptr;
const char* port_num = (std::to_string(port)).c_str();
struct addrinfo *result;
int res = getaddrinfo(nullptr, port_num, &hints, &result);
printf("HI\n");
}
If you valgrind the resulting binary you get:
==45919== Invalid read of size 1
==45919== at 0x573BA5C: getaddrinfo (in /usr/lib64/libc-2.17.so)
==45919== by 0x400C95: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Address 0x5a22058 is 24 bytes inside a block of size 29 free'd
==45919== at 0x4C2B16D: operator delete(void*) (vg_replace_malloc.c:576)
==45919== by 0x4EF3B62: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400C7C: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Block was alloc'd at
==45919== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==45919== by 0x4EF3A18: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400FFE: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&, std::forward_iterator_tag) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400F14: char* std::string::_S_construct_aux<char*>(char*, char*, std::allocator<char> const&, std::__false_type) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400EDD: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E8F: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E20: std::string __gnu_cxx::__to_xstring<std::string, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400CDE: std::to_string(int) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400C60: main (in /homes/iws/kieruc/Coding/a.out)
==45919==
==45919== Invalid read of size 1
==45919== at 0x573BACA: getaddrinfo (in /usr/lib64/libc-2.17.so)
==45919== by 0x400C95: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Address 0x5a22058 is 24 bytes inside a block of size 29 free'd
==45919== at 0x4C2B16D: operator delete(void*) (vg_replace_malloc.c:576)
==45919== by 0x4EF3B62: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400C7C: main (in /homes/iws/kieruc/Coding/a.out)
==45919== Block was alloc'd at
==45919== at 0x4C2A1E3: operator new(unsigned long) (vg_replace_malloc.c:334)
==45919== by 0x4EF3A18: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.19)
==45919== by 0x400FFE: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&, std::forward_iterator_tag) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400F14: char* std::string::_S_construct_aux<char*>(char*, char*, std::allocator<char> const&, std::__false_type) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400EDD: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E8F: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string<char*>(char*, char*, std::allocator<char> const&) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400E20: std::string __gnu_cxx::__to_xstring<std::string, char>(int (*)(char*, unsigned long, char const*, __va_list_tag*), unsigned long, char const*, ...) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400CDE: std::to_string(int) (in /homes/iws/kieruc/Coding/a.out)
==45919== by 0x400C60: main (in /homes/iws/kieruc/Coding/a.out)
However if I change the code to this
std::string portstr = std::to_string(port);
struct addrinfo *result;
int res = getaddrinfo(nullptr, portstr.c_str(), &hints, &result);
Then there are no memory errors. And I dont quite understand why.
Another thing to note is that if I try to compile the version with the const char* variable with char* instead you get a warning that the variable should be constant.
What is going on here?
The buffer returned by c_str is valid only as long as the associated std::string object lives. And here
const char* port_num = (std::to_string(port)).c_str();
A temporary string object is created, its buffer address is taken, and then it dies at the end of the full expression. You get a memory error for using a dangling pointer.
If you wish to use a temporary std::string, it must be created during the full expression where you use the buffer:
int res = getaddrinfo(nullptr, std::to_string(port).c_str(), &hints, &result)
With const char* port_num = (std::to_string(port)).c_str();, you are creating a temporary object of type std::string, which will live just as long as the expression in which it is used. So the .c_str() will point to memory that will get freed right after your statement.
Make two lines out of it:
auto portStr = std::to_string(port);
const char* port_num = portStr.c_str();
Thereby, the portStr-object will live until the end of the function, and you may use the result of the .c_str-call right until the end of the function (unless you alter protStr in between).

std::string causing memory leaks

I am running into a situation where my application is having memory leaks. After running valgrind, it looks as if I am getting a memory leak related to a std::string:
==20274== 34 bytes in 1 blocks are definitely lost in loss record 34 of 140
==20274== at 0x4C29DB5: operator new(unsigned long) (vg_replace_malloc.c:332)
==20274== by 0x7F843C8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.13)
==20274== by 0x7F84DE4: ??? (in /usr/lib64/libstdc++.so.6.0.13)
==20274== by 0x7F84F32: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib64/libstdc++.so.6.0.13)
==20274== by 0xA50CC71: __static_initialization_and_destruction_0(int, int) (filename.cpp:22)
==20274== by 0xA50D03F: _GLOBAL__sub_I_filename.cpp (filename.cpp:112)
==20274== by 0x400E9CE: _dl_init (in /lib64/ld-2.12.so)
==20274== by 0x4000B69: ??? (in /lib64/ld-2.12.so)
The code in question is:
in filename.h:
extern std::string aString;
in filename.cpp:
std::string aString = "a string";
Also worth note, this is in a separate namespace i.e.
namespace aNamespace {
//...
std::string aString; // in extern in .h
//...
}
Every place in code, it is (of course) referenced as:
aNamespace::aString;
And, from what I can tell, it is never reset, and is used either as a constant reference, or to initialize another string.
Can there ever be a situation where std::string would give memory leaks?
edit:
A related portion of the valgrind output:
==20274== by 0x400EFBB: _dl_fini (in /lib64/ld-2.12.so)
==20274== by 0x88DAA01: exit (in /lib64/libc-2.12.so)
==20274== by 0x88C3D26: (below main) (in /lib64/libc-2.12.so)
Is this making an exit call? Is it the standard exit(0)?
Valgrind produces this kind of messages if on program termination there's still some heap-allocated memory, but no variable holds a pointer to.
std::string allocates memory in it's constructor to provide storage for chars. Destructor should free memory back.
My guess is that application is terminated using exit(0) or so. In this case stack does not unwind, and no destructors are called.

C++, Valgrind reporting "possibly lost" after char* to std::string "conversion"

I have a class with a constructor like,
Foo::Foo(string p) {
path = p;
}
And I use it like this,
Foo foo = Foo("/tmp/foo");
Sorry for my C++ naivety. I understand that this is creating a std::string object implcitly (what's the right terminology for what's going on here?).
This causes Valgrind to complain as such,
==28188== 66 bytes in 1 blocks are possibly lost in loss record 3 of 5
==28188== at 0x4C2B0E0: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28188== by 0x4EFBF28: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EFD9B4: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EFDDDB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EC2B05: std::logic_error::logic_error(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EC5AA8: std::__throw_logic_error(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EFDA38: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EFDDDB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4022F3: main (main.cpp:13)
==28188==
==28188== 144 bytes in 1 blocks are possibly lost in loss record 4 of 5
==28188== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28188== by 0x4E9FF9F: __cxa_allocate_exception (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EC5A92: std::__throw_logic_error(char const*) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EFDA38: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4EFDDDB: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.24)
==28188== by 0x4022F3: main (main.cpp:13)
It looks like ultimately the "conversion" (sorry again) new'ing a std::string.
If I change my code to this,
string d = string("/tmp");
Foo Foo = Foo(d);
Valgrind does not report the leak.
This is really a leak, right? Seems like it.
What's the proper idiom to do what I'm doing here? I want the call semantics to be able to pass a char* but internally I want the class member to be a std::string.
The Valgrind error that you're getting seems to suggest that your program terminated abnormally due to an exception. You can see this through the call stack: it looks like an internal std::__throw_exception function is getting called and that there's an object of type std::logic_error getting constructed. From context, it seems like what's happening here is that you passed an invalid argument into the std::string constructor, which then caused the std::logic_error to get thrown, causing a different std::string to get constructed and then thrown. Since the program terminated due to an exception, the destructors for the std::strings constructed this way never got called, hence the leak.
I'd run this program in gdb rather than valgrind to see if you can debug the source of the error. From what you've posted above I don't think we have enough context to provide any specific insights.
Problem here is when you passed string literal which is actually of type const char * (c string) to const string , compiler creates temporary object by invoking overaloded ctor string(const char * ). This temporary object is then passed by value to Foo().
Temporary object of type string has internal allocation created something on heap and it should be freed when temporary object goes out of scope.
This is not definite memory leak but valgrind thinks (due to temp object doesnot have definite starting pointer pointing to it) in that way.
That's the reason it is reported as possbily lost (and not definitely lost).
The idiom I like to use is Foo::Foo(const std::string &str)
Passes strings by reference, but also allows for string literals.
The one thing to look out for is a NULL char pointer. That is quite possibly what you are seeing.

Memory Leak using C++ Exceptions

I'm struggling to write a little file handle class in C++11.
I know there already is a lot in the STL to actually handle files, but for learning purposes I wanted to do this by myself.
Unfortunately I don't seem understand, what effect exceptions have on the memory leakage behavior of a C++ program because Valgrind tells me, there are 2 memory leaks in following code:
file.h
#ifndef FILE_H
#define FILE_H
#include <iostream>
#include <memory>
#include <string>
#include <stdio.h>
class FileDeleter {
public:
void operator()(FILE *p);
};
class File {
public:
File(const std::string path);
private:
const std::string _path;
std::unique_ptr<FILE, FileDeleter> _fp;
};
#endif // FILE_H
file.cpp
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <utility>
#include <stdio.h>
#include "file.h"
void FileDeleter::operator()(FILE *p)
{
if (!p)
return;
if (fclose(p) == EOF)
std::cerr << "FileDeleter: Couldn't close file" << std::endl;
}
File::File(const std::string path)
: _path(std::move(path)),
_fp(fopen(_path.c_str(), "a+"))
{
if (!_fp)
throw std::runtime_error("Couldn't open file");
}
main.cpp
#include <cstdlib>
#include "file.h"
int main()
{
File my_file("/root/.bashrc");
return EXIT_SUCCESS;
}
I did choose to open /root/.bashrc on purpose to actually make the File ctor throw the exception. If I don't throw there, Valgrind is perfectly happy.
What am I missing here in using exceptions?
How do you implement a simple file handle "correctly" (exception safe)?
Thanks in advance!
Note: the read/write operations are still missing, since I'm already struggling with the basics.
Edit #1:
This is the actual Valgrind output, using --leak-check=full:
==7998== HEAP SUMMARY:
==7998== in use at exit: 233 bytes in 3 blocks
==7998== total heap usage: 5 allocs, 2 frees, 817 bytes allocated
==7998==
==7998== 38 bytes in 1 blocks are possibly lost in loss record 1 of 3
==7998== at 0x4C27CC2: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7998== by 0x4EEC4F8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x4EEDC30: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x4EEE047: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x40137D: main (in ../a.out)
==7998==
==7998== 43 bytes in 1 blocks are possibly lost in loss record 2 of 3
==7998== at 0x4C27CC2: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7998== by 0x4EEC4F8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x4EEDC30: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x4EEE047: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x400EBF: File::File(std::string) (in /home/frank/3Other/Code/Laboratory/c++/c++namedpipe/a.out)
==7998== by 0x401390: main (in ../a.out)
==7998==
==7998== 152 bytes in 1 blocks are possibly lost in loss record 3 of 3
==7998== at 0x4C27730: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7998== by 0x4E8F8F2: __cxa_allocate_exception (in /usr/lib/libstdc++.so.6.0.18)
==7998== by 0x400E9B: File::File(std::string) (in /home/frank/3Other/Code/Laboratory/c++/c++namedpipe/a.out)
==7998== by 0x401390: main (in ../a.out)
==7998==
==7998== LEAK SUMMARY:
==7998== definitely lost: 0 bytes in 0 blocks
==7998== indirectly lost: 0 bytes in 0 blocks
==7998== possibly lost: 233 bytes in 3 blocks
==7998== still reachable: 0 bytes in 0 blocks
==7998== suppressed: 0 bytes in 0 blocks
Edit #2:
Fixed exception thrown in Destructor.
Edit #3:
Removed FileException class, using std::runtime_error instead.
Edit #4:
Added NULL check in deleter.
I see the following problems:
fclose(NULL) is not allowed ...
but fortunately std::unique_ptr doesn't call the deleter if get() == nullptr, so this should be ok here
FileDeleter:operator() is called from a destructor, which means it should never throw. In your specific case, any error returned from fclose will cause std::terminate to be called
your exception should store the string by value, not reference. That reference is to a temporary which will have been destroyed by the time you call what().
As Vlad & Praetorian pointed out, you can remove the buggy code instead of fixing it, and just let std::runtime_error handle that for you. TBH, unless you're planning to add some file-specific data to the exception, or you plan to catch file exceptions separately, you don't need this class at all.
Edit: with the valgrind output provided, it looks like stack unwinding never completed. Since my initial thought about FileDeleter::operator() being called and throwing looks wrong, a reasonable test would be: what happens if you stick a try/catch inside the body of main?
General notes:
never throw an exception inside a destructor
never call something else that might throw, from a destructor
because if your destructor is invoked during exception handling/stack unwinding, the program will terminate instantly.

Segmentation fault in malloc_consolidate (malloc.c) that valgrind doesn't detect [duplicate]

This question already has answers here:
Segfaults in malloc() and malloc_consolidate()
(2 answers)
Closed 7 years ago.
My program goes in segmentation faults, and I cannot find the cause.
The worst part is, the function in question does not always lead to segfault.
GDB confirms the bug and yields this backtrace:
Program received signal SIGSEGV, Segmentation fault.
0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169
5169 malloc.c: No such file or directory.
in malloc.c
(gdb) bt
#0 0xb7da6d6e in malloc_consolidate (av=<value optimized out>) at malloc.c:5169
#1 0xb7da9035 in _int_malloc (av=<value optimized out>, bytes=<value optimized out>) at malloc.c:4373
#2 0xb7dab4ac in __libc_malloc (bytes=525) at malloc.c:3660
#3 0xb7f8dc15 in operator new(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#4 0xb7f72db5 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#5 0xb7f740bf in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Rep::_M_clone(std::allocator<char> const&, unsigned int) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#6 0xb7f741f1 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#7 0xb7f6bfec in std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::overflow(int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#8 0xb7f70e1c in std::basic_streambuf<char, std::char_traits<char> >::xsputn(char const*, int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#9 0xb7f5b498 in std::ostreambuf_iterator<char, std::char_traits<char> > std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::_M_insert_int<unsigned long>(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#10 0xb7f5b753 in std::num_put<char, std::ostreambuf_iterator<char, std::char_traits<char> > >::do_put(std::ostreambuf_iterator<char, std::char_traits<char> >, std::ios_base&, char, unsigned long) const () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#11 0xb7f676ac in std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<unsigned long>(unsigned long) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#12 0xb7f67833 in std::basic_ostream<char, std::char_traits<char> >::operator<<(unsigned int) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#13 0x08049c42 in sim::Address::GetS (this=0xbfffec40) at address.cc:27
#14 0x0806a499 in sim::UserGenerator::ProcessEvent (this=0x80a1af0, e=...) at user-generator.cc:59
#15 0x0806694b in sim::Simulator::CommunicateEvent (this=0x809f970, e=...) at simulator.cc:144
#16 0x0806685d in sim::Simulator::ProcessNextEvent (this=0x809f970) at simulator.cc:133
#17 0x08065d76 in sim::Simulator::Run (seed=0) at simulator.cc:53
#18 0x0807ce85 in main (argc=1, argv=0xbffff454) at main.cc:75
(gdb) f 13
#13 0x08049c42 in sim::Address::GetS (this=0xbfffec40) at address.cc:27
27 oss << m_address;
(gdb) p this->m_address
$1 = 1
Method GetS of class Address translates a number (uint32_t m_address) into a string and returns it. The code (very simple) is the following:
std::string
Address::GetS () const
{
std::ostringstream oss;
oss << m_address;
return oss.str ();
}
Besides, as can be seen in the backtrace, m_address is properly defined.
Now, I have tried to run my program using valgrind.
The program doesn't crash, likely due to the fact that valgrind replaces malloc () among other functions.
The error summary shows no memory leaking:
LEAK SUMMARY:
definitely lost: 0 bytes in 0 blocks
indirectly lost: 0 bytes in 0 blocks
possibly lost: 4,367 bytes in 196 blocks
still reachable: 9,160 bytes in 198 blocks
suppressed: 0 bytes in 0 blocks
All possibly lost refer to backtraces like this:
80 bytes in 5 blocks are possibly lost in loss record 3 of 26
at 0x4024B64: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
by 0x40DBDB4: std::string::_Rep::_S_create(unsigned int, unsigned int, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
by 0x40DE077: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
by 0x40DE1E5: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/i386-linux-gnu/libstdc++.so.6.0.16)
by 0x806AF62: sim::UserGenerator::CreateUser(unsigned int) (user-generator.cc:152)
I don't think this is related to the bug. However, the code in question can be found following this link.
I am thinking of a bug in libstdc++. However, how likely would that be?
I have also upgraded such library. Here's the versions currently installed on my system.
$ dpkg -l | grep libstdc
ii libstdc++5 1:3.3.6-23 The GNU Standard C++ Library v3
ii libstdc++6 4.6.1-1 GNU Standard C++ Library v3
ii libstdc++6-4.1-dev 4.1.2-27 The GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.3-dev 4.3.5-4 The GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.4-dev 4.4.6-6 GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.5-dev 4.5.3-3 The GNU Standard C++ Library v3 (development files)
ii libstdc++6-4.6-dev 4.6.1-1 GNU Standard C++ Library v3 (development files)
Now the thing is, I am not sure which version g++ uses, and whether there's some means to enforce the use of a particular version.
What I am pondering is to modify GetS. But this is the only method I know. Do you suggest any alternative?
Eventually, I am even considering to replace std::string with simpler char*.
Maybe a little drastic, but I wouldn't set it aside.
Any thought in merit?
Thank you all in advance.
Best,
Jir
Ok. This is NOT the problem:
I am thinking of a bug in libstdc++
The problem is that you overwrote some memory buffer and corrupted one of the structures used by the memory manager. The hard part is going to be finding it. Does not valgrind give you information about writting past the end of an allocated piece of memory.
Don't do this:
Eventually, I am even considering to replace std::string with simpler char*. Maybe a little drastic, but I wouldn't set it aside.
You already have enough problems with memory management. This will just add more problems. There is absolutely NOTHING wrong with std::string or the memory management routines. They are heavily tested and used. If there was something wrong people all over the world would start screaming (it would be big news).
Reading your code at http://mercurial.intuxication.org/hg/lte_sim/file/c2ef6e0b6d41/src/ it seems like you are still stuck in a C style of writting code (C with Classes). So you have the power of C++ to automate (the blowing up of your code) but still have all the problems associated with C.
You need to re-look at your code in terms of ownership. You pass things around by pointer way too much. As a result it is hard to follow the ownership of the pointer (and thus who is responsible for deleting it).
I think you best bet at finding the bug is to write unit tests for each class. Then run the unit tests through val-grind. I know its a pain (but you should have done it to start with now you have the pain all in one go).