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).
Related
I am getting a memory leak when I run try to read from Clipboard.
Sample code:
void SomeFunction()
{
OpenClipboard(nullptr);
HGLOBAL hglb = GetClipboardData(CF_TEXT);
char* ch = static_cast<char*>(GlobalLock(hglb));
CString rawClipboardData(ch);
GlobalUnlock(hglb);
CloseClipboard();
}
It is the middle row above which causes the memory leak according to Visual Studio. This row:
CString rawClipboardData(ch);
If I do not run it, there is no leak reported.
But if I do run it I get the following debug output in visual studio output window:
Detected memory leaks!
Dumping objects ->
f:\dd\vctools\vc7libs\ship\atlmfc\src\strcore.cpp(158) : {75645} normal block at 0x00000000072C89A0, 52 bytes long.
Data: <`x > 60 78 F7 D3 FE 07 00 00 0D 00 00 00 0D 00 00 00
Object dump complete.
Any ideas?
UPDATE: Added OpenClipboard(nullptr) in code above. Also in real code there are nullptr-checks. Just keeping it clean here to reduce amount of guard-clause code.
GlobalLock(hglb) should be a LPTSTR so I would assume that the leak is caused by the cast to char*. For Unicode platforms, TCHAR is defined as synonymous with the WCHAR type.
you should be able to do something like
CString rawClipboardData = GlobalLock(hglb);
If not then
CString rawClipboardData;
LPTSTR lptstr = GlobalLock(hglb);
rawClipboardData = lptstr;
will definitely work
I'm on windows, qt 4.7. part of my code takes a FILE* from a file which is open for reading by another part of the system (legacy, C). I open a QTextStream as follows:
// file currently opened (readonly), and partially read
FILE *infile = function_to_get_file_pointer();
QTextStream is(infile, QIODevice::ReadOnly);
The second line crashes when built in release mode but is fine in debug. I can step through the debug version and see the QFile that is opened internally by QTextStream.
The most I've managed to get out of the windows call stack in release mode at the time of the crash is below:
ntdll.dll!77450226()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!77450142()
msvcr80.dll!_lock_file(_iobuf * pf=0x71962148) Line 241 + 0xa bytes C
msvcr80.dll!_ftelli64(_iobuf * stream=0x71962148) Line 51 + 0x8 bytes C
QtCore4.dll!6708b87d()
QtCore4.dll!67099294()
QtCore4.dll!6713d491()
which could be a red herring but look like something's gone wrong trying to lock the file. Prior to this, I have enabled debug output for my code so I know that it is the QTextStream creation that is causing the problem.
I welcome any suggestions!
After some further digging, I have found that the file, although ASCII, is originally fopened with "rb" in order to stop the win32 CRT converting line endings from \r\n to \n.
I assumed this would be confusing Qt so modified the fopen to use "r" only. Then a comment below linked to here which shows that the FILE* should be opened in binary mode, e.g. "rb", so this is not a problem.
Trying tezrigs suggestion below, freopen on the FILE* gives the following:
msvcr100.dll!_crt_debugger_hook(int _Reserved=8633404) Line 65 C
msvcr100.dll!_call_reportfault(int nDbgHookCode=2, unsigned long dwExceptionCode=3221226519, unsigned long dwExceptionFlags=1) Line 167 + 0x6 bytes C++
msvcr100.dll!_invoke_watson(const wchar_t * pszExpression=0x00000000, const wchar_t * pszFunction=0x00000000, const wchar_t * pszFile=0x00000000, unsigned int nLine=0, unsigned int pReserved=8633376) Line 155 + 0xf bytes C++
msvcr100.dll!_invalid_parameter(const wchar_t * pszExpression=0x00000000, const wchar_t * pszFunction=0x00000000, const wchar_t * pszFile=0x00000000, unsigned int nLine=0, unsigned int pReserved=0) Line 110 + 0x14 bytes C++
msvcr100.dll!_invalid_parameter_noinfo() Line 121 + 0xc bytes C++
msvcr100.dll!_freopen_helper(_iobuf * * pfile=0x0083bc3c, const char * filename=0x00000000, const char * mode=0x013ee350, _iobuf * str=0x71962148, int shflag=64) Line 31 + 0x1f bytes C
msvcr100.dll!freopen(const char * filename=0x00000000, const char * mode=0x013ee350, _iobuf * str=0x71962148) Line 111 C
The exception code passed to _call_report_fault is 0x0000417 - Fatal Error: Unknown Software Exception, which isn't much help..
OK: more detail, and some self contained, replicable code (myfile.txt must be over 1000 chars long):
#include <QtCore/QCoreApplication>
#include "qtextstream.h"
#include <iostream>
int main(int argc, char *argv[])
{
// QCoreApplication a(argc, argv);
std::cin.get();
FILE *myfile = fopen("myfile.txt", "rb");
int c;
for(int i=0; i < 1000; i++)
c = getc(myfile);
fflush(myfile);
long pos = ftell(myfile);
QTextStream is(myfile, QIODevice::ReadOnly);
while(!is.atEnd())
{
QString in_line = is.readLine();
std::cout << in_line.toStdString();
}
fseek(myfile, pos, SEEK_SET);
fclose(myfile);
return 0;
}
All the following in release mode:
This lets me attach a debugger if I run outside visual studio. If I run in outside visual studio, it crashes.
If I attach to it once it has started from outside visual studio, it crashes on construction of QTextStream.
If I start it from inside visual studio with shift-F5 (i.e. running outside the debugger) it writes the contents of the file to the display.
likewise, when running under the debugger, it works as expected.
It is down to the dlls. I have a locally compiled set of dlls (created with MSVC2010) and using them to replace those in the main product solves the problem. Ditto with the test code. The release code was using Qt compiled with 2005, using msvcr80.
All credit to #KarstenKoop - feel free to post your answer here. The problem was due to Qt dlls that were using msvcr80.dll while the rest of the application was compiled using visual studio 2010 and thus using msvcr100.dll
This link explains the perils of mixing visual studio versions quite nicely
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <stdlib.h>
#include <crtdbg.h>
#define _CRTDBG_MAP_ALLOC
using namespace std;
int main(void){
string file = "hello";
string foo;
char response;
_CrtDumpMemoryLeaks();
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
return 0;
}
Just a small self contained example. The console will read:
Detected memory leaks!
Dumping objects ->
{143} normal block at 0x007DAE50, 8 bytes long.
Data: < B > 18 FB 42 00 00 00 00 00
{142} normal block at 0x007DAE08, 8 bytes long.
Data: << B > 3C FB 42 00 00 00 00 00
After running. Is this an issue with CRT not handling strings properly?
It's because you call _CrtDumpMemoryLeaks before main has returned, so the strings haven't yet gone out of scope. You should only check for leaks after the strings should have been freed, for example:
void myFunc() {
string file = "hello";
string foo;
char response;
}
int main(void){
myFunc();
_CrtDumpMemoryLeaks();
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
return 0;
}
I think this will solve it:
int main(void){
{
string file = "hello";
string foo;
char response;
} // file's destructor called here
_CrtDumpMemoryLeaks();
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
return 0;
}
bacause the strings will otherwise only be deleted at the end of the main function, and will thus be still in the scope (and therefore own heap-memory) when the _CrtDumpMemoryLeaks() function is called.
_CrtDumpMemoryLeaks();
You are asking for a leak report before the string destructors could run. Putting curly braces around code before this statement would be a workaround.
But you are simply helping too much, it already generates a leak report after main() returns. So just delete the statement. And add, say, auto leak = new int; so you see a real leak.
I had a memory leak in my big program, detected by the Visual Studio CRT debug system. I reduced my program to the following, with still shows a memory leak.
#include "stdafx.h"
#include "crtdbg.h"
int main()
{
int tmp = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
_CrtSetDbgFlag(tmp | _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
int* k = new int(8);
delete k;
return 0;
}
When I run it in my Visual Studio 2012 system, I see the following:
Detected memory leaks!
Dumping objects ->
{65} normal block at 0x00663008, 4424 bytes long.
Data: <X #f > 58 CF 14 00 90 23 66 00 01 00 00 00 00 00 00 00
{64} normal block at 0x00662390, 4 bytes long.
Data: < > 00 C3 14 00
Object dump complete.
If I remove the allocation and deallocation, the leaks don't appear. If I replace the allocation and deallocation by any standard library feature that uses memory allocation (e.g. std::string k), the leaks appear.
Why do the memory leaks appear? How can I remove them?
I tried debugging my problem by setting _crtBreakAlloc to 64; the system stopped at a place that is supposed to help me (see stack trace below). But I don't know what to do with this info.
> test_it.exe!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 393 C++
test_it.exe!_nh_malloc_dbg_impl(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 239 C++
test_it.exe!_nh_malloc_dbg(unsigned int nSize, int nhFlag, int nBlockUse, const char * szFileName, int nLine) Line 302 C++
test_it.exe!malloc(unsigned int nSize) Line 56 C++
test_it.exe!_PlatformSpecificMalloc() Unknown
test_it.exe!MemoryLeakWarningPlugin::ignoreAllLeaksInTest(void) Unknown
test_it.exe!operator new(unsigned int) Unknown
test_it.exe!MemoryLeakWarningPlugin::getGlobalDetector(void) Unknown
test_it.exe!std::error_condition::value(void) Unknown
test_it.exe!operator new(unsigned int) Unknown
test_it.exe!main() Line 9 C++
My system is:
Microsoft Visual Studio Professional 2012
Version 11.0.61030.00 Update 4
Visual C++ 2012 04938-004-0034007-02224
Windows 7
Your call stack suggests that there is another memory leak tool being used, besides the Visual C++ runtime functions.
Using google takes me to this link: https://github.com/auser/cpputest/blob/master/src/CppUTest/MemoryLeakWarningPlugin.cpp
So possibly, cppuTest is being applied to your simple project without you being aware of it.
I suggest you create a brand new Win32 Console application, copy and paste your code, and retest. Make sure that the new project has no additional dependencies.
Just tried it with clean VS 2012 installation with Deleaker installed. No leaks shown. And no output from CRT in the final.
What is MemoryLeakWarningPlugin mentioned in the stack trace? Seems it's a part CppUTest (I did Google a bit).
I think either MemoryLeakWarningPlugin leaks itself or it breaks CRT diagnostic system somehow.
I wrote this code in Visual c++ to control LED's through parallel port:
// InpoutTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include <conio.h>
short _stdcall Inp32(short PortAddress);
void _stdcall Out32(short PortAddress, short data);
int main(int argc, char* argv[])
{
Out32(888, 255);
system("pause");
Out32(888, 0);
return 0;
}
Now, what I thought was that the line 'Out32(888, 255);' will write 1 in all data registers, and all LED'd connected from D0 to D7 will turn on; but nothing happened, the led's which were on before execution remained on and same case with the led's which were off.
Same was the case with 'Out32(888, 0);', no led's were turned off.
What is wrong in the above code? I used 'Inpoutx64.dll' as I'm working on 64 bit OS (windows 8). I also included 'Inpoutx64.lib' in project properties > linked > input > Additional dependencies.
I've also copied "inpoutx64.dll' to Windows/system 32
Make sure you have inpoutx64.dll in the same directory as your generated .exe file, and that you have run the InstallDriver.exe program included with inpoutx64.dll, and allowed UAC elevation, in order to install the required system driver.