Question about memory management of jsoncpp - c++

Hello !
I have a question about memory with jsoncpp. I have to load large JSon file (55 MB) in c++ with jsoncpp. I noticed my program use lot of RAM. I tried something, just open, parse and close the JSON file. After the closing of file the memory usage did'nt decrese at all.
I also tried with RapidJson and after returning a lot of memory is freed.
I'm using Linux
I tried this code, which prints statm file in /proc/PID/statm before and after Jsoncpp parse.
It prints the memory before, during and after the parse function.
#include <iostream>
#include <json/json.h>
#include <fstream>
#include <unistd.h>
#include <iostream>
#include <json/json.h>
#include <fstream>
#include <unistd.h>
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/document.h>
void printmem()
{
char tmp[128];
std::string t;
sprintf(tmp, "/proc/%d/statm", getpid());
std::ifstream ifs(tmp);
std::getline(ifs, t);
std::cout << t <<"\n";
ifs.close();
}
void jsoncpp()
{
std::ifstream ifs("../../../AlloDB/db.json");
Json::CharReaderBuilder builder;
Json::Value value;
JSONCPP_STRING errs;
Json::parseFromStream(builder, ifs, &value, NULL);
ifs.close();
printmem();
}
void rapid_json()
{
using namespace rapidjson;
std::ifstream ifs("../../../AlloDB/db.json");
std::string t;
IStreamWrapper isw(ifs);
Document d;
d.ParseStream(isw);
printmem();
}
int main(int argc, char** argv)
{
printmem();
//jsoncpp();
rapid_json();
printmem();
}
The result is:
For jsoncpp
2552 629 516 51 0 188 0
107744 106364 1052 51 0 105380 0
107744 106364 1052 51 0 105380 0
So before the parse, the total memoy used is 2552*4096 +/-= 10 MiB. During and after the function memory usage is strictly the same 107744*4096 +/-= 420 MiB.
For RapidJson:
2552 642 530 51 0 188 0
24275 22871 1056 51 0 21911 0
4140 2780 1056 51 0 1776 0
RapidJson free a lot of memory but not etire.
Jsoncpp should free his memory after returning jsoncpp(), isnt it ? I tried Valgrind with this program (with jsoncpp), and there is no memory leak.
==133628== Memcheck, a memory error detector
==133628== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==133628== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==133628== Command: bin/Debug/db
==133628==
50448 39807 1539 498 0 47403 0
649572 639457 1671 498 0 646527 0
440676 431819 1671 498 0 437631 0
==133628==
==133628== HEAP SUMMARY:
==133628== in use at exit: 0 bytes in 0 blocks
==133628== total heap usage: 5,917,609 allocs, 5,917,609 frees, 601,544,185 bytes allocated
==133628==
==133628== All heap blocks were freed -- no leaks are possible
==133628==
==133628== For lists of detected and suppressed errors, rerun with: -s
==133628== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Why jsoncpp does not free memory in returning the jsoncpp() function ?
After parsing i dont need to acces the data, hot to clean it ?
Thanks

Related

Segment Fault 11 with Dynamic C-String being Displayed from Class Function

Dynamic c-string 'textString' causes Segmentation fault 11 when used by a class member function to be displayed.
#include "Text.h"
#include <iostream>
#include <cstring>
using namespace std;
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
char* textString = new char[textLength];
strcpy(textString, textArray);
cout << textString << endl;
}
Text::~Text()
{
delete[] textString;
}
void Text::displayText() const
{
cout << textString << endl;
}
My provided driver:
#include <iostream>
#include "Text.h"
using namespace std;
int main()
{
Text *myString1;
char tvshow[1000];
cout << "\n\nWhat is the most recent TV show you watched?\n";
cin.getline(tvshow, 1000);
myString1 = new Text(tvshow);
cout << "\n\nTV SHOW:\t";
myString1->displayText();
cout << "\t# CHARACTERS:\t" << myString1->getLength() << endl;
return 0;
}
In the Constructor for the Text class, the line cout << textString << endl; works as intended. However, when the main function calls myString1->displayText();, bash ends the program with Segmentation fault: 11.
Any help would be greatly appreciated. Thank you.
Additionaly to what Algirdas says, your other problem is, that you actually don't assign the class member textString (assuming you have one), but shadow it in your constructor.
Change your constructor to something like this:
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
textString = new char[textLength + 1];
strcpy(textString, textArray);
cout << textString << endl;
}
Note the missing char * in front of textString.
How did I spot this?
As with any other segfault, you should learn how to debug. Your best tools are gdb and valgrind. Running this with valgrind gives me:
$ echo franz | valgrind ./a.out
==6222== Memcheck, a memory error detector
==6222== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==6222== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==6222== Command: ./a.out
==6222==
What is the most recent TV show you watched?
franz
TV SHOW: ==6222== Invalid read of size 1
==6222== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6222== by 0x108DB6: Text::getLength() const (a.cpp:37)
==6222== by 0x108E70: main (a.cpp:51)
==6222== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==6222==
==6222==
==6222== Process terminating with default action of signal 11 (SIGSEGV)
==6222== Access not within mapped region at address 0x0
==6222== at 0x4C32CF2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6222== by 0x108DB6: Text::getLength() const (a.cpp:37)
==6222== by 0x108E70: main (a.cpp:51)
==6222== If you believe this happened as a result of a stack
==6222== overflow in your program's main thread (unlikely but
==6222== possible), you can try to increase the size of the
==6222== main thread stack using the --main-stacksize= flag.
==6222== The main thread stack size used in this run was 8388608.
==6222==
==6222== HEAP SUMMARY:
==6222== in use at exit: 14 bytes in 2 blocks
==6222== total heap usage: 5 allocs, 3 frees, 77,838 bytes allocated
==6222==
==6222== LEAK SUMMARY:
==6222== definitely lost: 6 bytes in 1 blocks
==6222== indirectly lost: 0 bytes in 0 blocks
==6222== possibly lost: 0 bytes in 0 blocks
==6222== still reachable: 8 bytes in 1 blocks
==6222== suppressed: 0 bytes in 0 blocks
==6222== Rerun with --leak-check=full to see details of leaked memory
==6222==
==6222== For counts of detected and suppressed errors, rerun with: -v
==6222== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
fish: Process 6222, “valgrind” “echo franz | valgrind ./a.out” terminated by signal SIGSEGV (Address boundary error)
You can clearly see, that the crash happens in getLength, because it tries to access address 0x0. When you run this with gdb, you will stop at exactly that point and can see print textString, that it is 0 and not properly initiliazed.
Please read What is a debugger and how can it help me diagnose problems? for further information!
You are witnessing undefined behavior, due to strcpy(textString, textArray); writing out of bounds.
In
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
char* textString = new char[textLength];
strcpy(textString, textArray);
cout << textString << endl;
}
strlen (textArray) returns the length of a null-terminated string pointed at by textArray. Such length doesn't include the null-terminator itself. However, strcpy writes the null-terminator to the destination string. To avoid such an issue, allocate a place for the null-terminator:
Text::Text(const char* textArray)
{
textLength = strlen(textArray);
char* textString = new char[textLength + 1];
strcpy(textString, textArray);
cout << textString << endl;
}
I am assuming that textLengthand textString are member variables of your class (of type size_t and char * respectively). You don't show the definition of your class Text.
You made a mistake in your constructor. This line
char* textString = new char[textLength];
should be
char* textString = new char[textLength+1];
to allow for the trailing '\0' that C strings have. Also you might want to bulletproof your class Text by making sure your write a copy contructor, destructor and assignment operator. Also consider what happens if NULL is passed to Text constructor. Alternatively a better option is to use std::string as a member variable, which means you can do away with the copy constructor, destructor and assignment operator (the compiler generated versions will just work); you can also do away with textLength and you can write a constructor that is member initialised.

Valgrind invalid read on FILE*

The following code, when built on ubuntu creates an executable.
#include <stdio.h>
void otherfunc(FILE* fout){
fclose(fout);//Line 4
fout = fopen("test.txt", "w");//Delete contents and create a new file//Line 5
setbuf(fout, 0);//Line 6
}
int main() {
FILE *fout = fopen("test.txt", "r");//Line 10
if (fout) {
//file exists and can be opened
fclose(fout);//Line 13
fout = fopen("test.txt", "a");//Line 14
setbuf(fout, 0);
}
else {
//file doesn't exists or cannot be opened
fout = fopen("test.txt", "a");//Line 19
}
otherfunc(fout);//Line 22
fclose(fout);//Line 24
return 0;
}
When run through valgrind, valgrind gives the following warnings:
==13569== Invalid read of size 4
==13569== at 0x4EA7264: fclose##GLIBC_2.2.5 (iofclose.c:53)
==13569== by 0x400673: main (newmain.cpp:24)
==13569== Address 0x52042b0 is 0 bytes inside a block of size 552 free'd
==13569== at 0x4C2EDEB: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13569== by 0x4EA7362: fclose##GLIBC_2.2.5 (iofclose.c:84)
==13569== by 0x4005CD: otherfunc(_IO_FILE*) (newmain.cpp:4)
==13569== by 0x400667: main (newmain.cpp:22)
==13569== Block was alloc'd at
==13569== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13569== by 0x4EA7CDC: __fopen_internal (iofopen.c:69)
==13569== by 0x400657: main (newmain.cpp:19)
Essentially, it is complaining that the fclose(fout); on Line 24 is closing an already freed memory that was freed on line 4 fclose(fout); within otherfunc(). But the Line 24's fclose(fout); is meant to close the fopen() performed on Line 5.
At any point in time in the code, whenever a fclose() is called, there is always exactly one open fopen(). Why is this then an invalid read as reported by valgrind?
otherfunc takes a file pointer by value. So the value you've assigned at line 5 is lost after returning from otherfunc and when it returns into main the value of fout there remains unchanged. It contains a dangling file pointer value that you've closed at line 4. Therefore a call to close on line 24 will receive an invalid pointer.

Memory leak while using libcurl in C++ program

I am using libcurl in my C++ program to get data from a link. The program is getting result but whenever I do valgrind I see a huge memory leak.
This is my code:
#include <string>
#include <iostream>
#include <curl/curl.h>
#include <map>
using namespace std;
int main(){
string url_;
string paramname_;
string paramvalue_;
cout << "Enter domain name(without parameters): ";
cin >> url_;
cout << "Enter parameter name: ";
cin >> paramname_;
cout << "Enter parameter value: ";
cin >> paramvalue_;
CURL* c;
curl_global_init(CURL_GLOBAL_DEFAULT);
c = curl_easy_init();
string finalurl_ = url_ + "?" + paramname_ + "=" + paramvalue_;
cout << finalurl_ << endl;
curl_easy_setopt(c, CURLOPT_URL, finalurl_.c_str());
cout << curl_easy_perform(c);
curl_easy_cleanup(c);
curl_global_cleanup();
//free(c);
return 0;
}
This is what I get while running valgrind:
==2379== LEAK SUMMARY:
==2379== definitely lost: 7,648 bytes in 116 blocks
==2379== indirectly lost: 1,240 bytes in 27 blocks
==2379== possibly lost: 2,152 bytes in 51 blocks
==2379== still reachable: 103,874 bytes in 192 blocks
==2379== suppressed: 612,674 bytes in 228 blocks
==2379==
==2379== For counts of detected and suppressed errors, rerun with: -v
==2379== ERROR SUMMARY: 130 errors from 130 contexts (suppressed: 19 from 15)
[1] 2379 segmentation fault valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./test
One of the definitely lost places while running valgrind is:
==2379== 224 (64 direct, 160 indirect) bytes in 1 blocks are definitely lost in loss record 341 of 381
==2379== at 0x10009C232: calloc (vg_replace_malloc.c:714)
==2379== by 0x100E54BA0: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E54C4D: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E54C4D: realizeClass(objc_class*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E5A72D: getClass_impl(char const*) (in /usr/lib/libobjc.A.dylib)
==2379== by 0x100E5AAF2: object_setClass (in /usr/lib/libobjc.A.dylib)
==2379== by 0x10067B8BD: __CFInitialize (in /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation)
==2379== by 0x10001D846: ImageLoaderMachO::doImageInit(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==2379== by 0x10001DC12: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==2379== by 0x1000194A9: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==2379== by 0x100019440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
==2379== by 0x100019440: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, char const*, ImageLoader::InitializerTimingList&, ImageLoader::UninitedUpwards&) (in /usr/lib/dyld)
I am compiling the program using g++:
g++ -std=c++11 -g -o test -lcurl test.cpp
I am looking for ways to free up the memory. Any help would be appreciated.

Visual C++ 2013 std::string memory leak

During development of proprietary app. I have noticed memory leak, related to std::string in a MS Visual C++ 2013, Update 4.
Take a look at the following (basic) code prototype which causes memory leak:
static std::string MemoryLeakTest()
{
static size_t const test_size = 2002;
std::unique_ptr<char[]> result1(new char[test_size]);
std::string result2(result1.get(), test_size);
return result2;
}
calling it by:
std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;
Am I doing something wrong, or is it a memory leak in a Visual C++ STL?
P.S. this is DebugView output showing mem leak detected by VLD:
[11140] WARNING: Visual Leak Detector detected memory leaks!
[11140] ---------- Block 3 at 0x00A95620: 2002 bytes ----------
[11140] Leak Hash: 0x1DA884B6, Count: 1, Total 2002 bytes
[11140] Call Stack (TID 9568):
[11140] 0x0FF5C260 (File and line number not available): MSVCR120D.dll!operator new
[11140] f:\dd\vctools\crt\crtw32\stdcpp\newaop.cpp (6): TestCpp.exe!operator new[] + 0x9 bytes
[11140] c:\work\testcpp\testcpp.cpp (307): TestCpp.exe!MemoryLeakTest + 0xA bytes
[11140] c:\work\testcpp\testcpp.cpp (401): TestCpp.exe!wmain + 0x9 bytes
[11140] f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (623): TestCpp.exe!__tmainCRTStartup + 0x19 bytes
[11140] f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c (466): TestCpp.exe!wmainCRTStartup
[11140] 0x75557C04 (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0x24 bytes
[11140] 0x77C4B54F (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x8F bytes
[11140] 0x77C4B51A (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
[11140] Data:
Tried your code with Deleaker and it couldn't find any leak.
Then tried this code:
while (true)
{
std::string const testML = MemoryLeakTest();
std::cout << testML << std::endl;
}
Task Manager shows that memory usage remains the same: no leaks.
I think this is a bug in VLD, you can find that std::unique_ptr really frees the memory, just step into during debugging, look:
~unique_ptr() _NOEXCEPT
{ // destroy the object
_Delete();
}
Go further:
void _Delete()
{ // delete the pointer
if (this->_Myptr != pointer())
this->get_deleter()(this->_Myptr);
}
};
Go further:
void operator()(_Ty *_Ptr) const _NOEXCEPT
{ // delete a pointer
static_assert(0 < sizeof (_Ty),
"can't delete an incomplete type");
delete[] _Ptr;
}
};
Aha, delete[] is called!
The call
std::unique_ptr<char[]> result1(new char[test_size]);
is correct. The tricky part is NOT to write std::unique_ptr<char>, which also compiles and can cause a memory leak (unique_ptr calls delete to release resource. When initialized with new[], we need to instruct unique_ptr to call the correct delete[]).
The std::string constructor call is also OK and it's very unlikely there's a memory leak. The std::string can be initialized from a C-style pointer in the same way.
I don't see any memory leak in your code snippet. How do you know it's a memory leak?

Detecting memory leaks in Visual C++ (Windows)

I'm working on a large C++ project under Visual Studio 2010 and think that there are some memory leaks inside. I tried the approach with including crtdbg.h but it does not help much as I don't see where the leaks occured. Defining new has 2 pitfalls: First it needs to be done in every cpp file which is not really an option, and 2nd it breaks with e.g. Boost. Using new(nothrow) or anything that uses boosts "has_new_operator.h" breaks this. [EDIT: It fails to compile as the redefined "new" has no overloads for something like "nothrow" or the "boost magic"] (Unless one defines "new" after all boost headers including headers referencing boost)
Last but not least: I have singletons. They are implemented using subclasses of the singleton template and a static function variable. One of them is a config container where one registers settings (pairs of strings and ints that are than stored in maps) Since the mem leak dump is called before deallocation of the singleton instance I get a massive amount of leaks for all those strings and the singleton itself.
Any way to have only the real leaks shown or make it dump after static object deallocation?
Which free tools can handle this case?
I have used the Visual Leak Detector with quite positive results. It is small and neat, and can be built into your project (assuming you have a running Debug configuration) in a matter of seconds:
https://vld.codeplex.com/
If set-up correctly (which can be done using the installer) then you only have to
#include <vld.h>
in one of your .cpp files for each module - that's it, the header will do the linking for you. You don't have to put it everywhere. Internally the tool uses the CrtDbg, so you have to have a debug build running in order for it to work.
It gives you debugger or text output after each run (if configured using a config file), even when not run through a debugger. It is not the most powerfull tool, but these usually cost some coin ;)
EDIT: There is a possibility to enable the VLD also in non-debug configurations by defining VLD_FORCE_ENABLE before including the header. But the results may be tempered with then.
EDIT: I have tried a fresh installation of VLD. Note that for VS2013 compilers the v2.4rc2 version must be used (or anything greater v2.3). Version v2.3 only works up until VS2010 compilers.
After installation I created a new project and set-up my include- and library-directories to include the respective VLD folders. After that I used the following code to test memleak reports of singletons (note that this code doesn't make sense, it just proves a point):
#include <iostream>
#include <string>
#include <sstream>
#include <map>
// Uncomment this, if you want VLD to work in non-debug configurations
//#define VLD_FORCE_ENABLE
#include <vld.h>
class FooSingleton {
private:
std::map<std::string, std::string*>
_map;
FooSingleton() {
}
public:
static FooSingleton* getInstance(void) {
/* THIS WOULD CAUSE LEAKS TO BE DETECTED
SINCE THE DESTRUCTOR WILL NEVER BE CALLEd
AND THE MAP IS NOT CLEARED.
*/
// FooSingleton* instance = new FooSingleton;
// return instance;
static FooSingleton instance;
return &instance;
}
void addString(const std::string& val) {
_map.insert(std::make_pair(val, new std::string(val)));
}
~FooSingleton(void) {
auto it = _map.begin();
auto ite = _map.end();
for(; it != ite; ++it) {
delete it->second;
}
}
};
int main(int argc, char** argv) {
FooSingleton* fs = FooSingleton::getInstance();
for(int i = 0; i < 100; ++i) {
std::stringstream ss;
ss << i << "nth string.";
fs->addString(ss.str());
}
return 0;
}
With this code, the VLD does not report any leaks because the static auto-variable in getInstance() will be destructed upon exit and the elements in the map will be deleted. This must be done nevertheless, even if it's a singleton, otherwise the leaks will be reported. But in this case:
Visual Leak Detector Version 2.3 installed.
Aggregating duplicate leaks.
Outputting the report to the debugger and to D:\dev\projects\tmp\memleak\memleak\memory_leak_report.txt
No memory leaks detected. Visual Leak Detector is now exiting.
If the code in the getInstance() is changed to the commented version, then the singleton is never cleared up and the following leaks (amongst others) is reported:
---------- Block 11 at 0x008E5928: 52 bytes ----------
Leak Hash: 0x973608A9 Count: 100
Call Stack:
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (36): memleak.exe!std::_Allocate<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0x15 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory (187): memleak.exe!std::allocator<std::_Tree_nod<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::alloca + 0xB bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (560): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0xD bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (588): memleak.exe!std::_Tree_val<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,s + 0x8 bytes
c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree (756): memleak.exe!std::_Tree<std::_Tmap_traits<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::basic_string<char,std::char_traits<char>,std::allocator<char> > *,std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std:: + 0x17 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (33): memleak.exe!FooSingleton::addString + 0xA9 bytes
d:\dev\projects\tmp\memleak\memleak\main.cpp (51): memleak.exe!main + 0x37 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): memleak.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): memleak.exe!mainCRTStartup
0x76BF919F (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes
0x7739A22B (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x84 bytes
0x7739A201 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x5A bytes
Data:
C0 53 8E 00 30 67 8E 00 C0 53 8E 00 98 58 8E 00 .S..0g.. .S...X..
30 6E 74 68 20 73 74 72 69 6E 67 2E 00 CD CD CD 0nth.str ing.....
0C 00 00 00 0F 00 00 00 CD CD CD CD 48 56 8E 00 ........ ....HV..
01 00 CD CD
You can clearly see the Count: 100 for this block of code, which is correct.
I also edited my vld.ini file in the installation directory to have the following set to be enabled:
AggregateDuplicates = yes
ReportTo = both
These make sure that a) all duplicate leaks are squashed together to one report with a leak-count (as above, otherwise there would be 100 entries) and the other so that a report-file is dumped in the directory of the application.
So for singletons it works fine as long as you use the static auto-variable approach you are using and do your cleanup in the destructor.
EDIT: Also, the instrumentation can be disabled at specific code pieces. If the above code would be modified like this:
void addString(const std::string& val) {
VLDDisable();
_map.insert(std::make_pair(val, new std::string(val)));
VLDEnable();
}
The leaks will never be profiled and not tracked.
You can get memory leaks source from crtdebug. it won't help you with the boost allocations, unless you compile boost (or any library) in the same way, but for the rest, it will show you allocation file and line.
This is how you use properly the crtdebug.h:
in the top of your stdafx.h (or any PCH file) add the following lines:
#ifdef DEBUG
//must define both _CRTDBG_MAP_ALLOC and _CRTDBG_MAP_ALLOC_NEW
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#include <stdlib.h>
#include <crtdbg.h>
//if you won't use this macro you'll get all new as called from crtdbg.h
#define DEBUG_NEW new( _CLIENT_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
Now in the beginning of your main or winmain or any entry point to your program add the following lines:
//register memory leak check at end of execution:
//(if you use this you won't need to use _CrtDumpMemoryLeaks at the end of your main)
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
//set report mode:
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
Now here a small test I've made:
After a new console program from VS10 called "test":
My stdafx.h:
#pragma once
#ifdef _DEBUG
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#include <stdlib.h>
#include <crtdbg.h>
#define DEBUG_NEW new( _CLIENT_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#endif
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
and my test.cpp is:
#include "stdafx.h"
void CheckMemoryLeak()
{
char *ptr=new char[100];
int n=900;
sprintf(ptr,"%d",n);
}
int _tmain(int argc, _TCHAR* argv[])
{
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_DEBUG );
CheckMemoryLeak();
return 0;
}
Output is:
'tests.exe': Loaded 'C:\Users\shr\Documents\Visual Studio 2010\Projects\tests\Debug\tests.exe', Symbols loaded.
'tests.exe': Loaded 'C:\Windows\SysWOW64\ntdll.dll', Cannot find or open the PDB file
'tests.exe': Loaded 'C:\Windows\SysWOW64\kernel32.dll', Cannot find or open the PDB file
'tests.exe': Loaded 'C:\Windows\SysWOW64\KernelBase.dll', Cannot find or open the PDB file
'tests.exe': Loaded 'C:\Windows\SysWOW64\msvcr100d.dll', Symbols loaded.
Detected memory leaks!
Dumping objects ->
c:\users\shr\documents\visual studio 2010\projects\tests\tests\tests.cpp(9) : {97} client block at 0x01003288, subtype 0, 100 bytes long.
Data: <900 > 39 30 30 00 CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.
The program '[1600] tests.exe: Native' has exited with code 0 (0x0).