I've been scratching my head over this for the past month now and I still can't figure out what is going on.
The problem is that I have a very serious memory leak on a C++ application running on Windows Server 2008, compiled using Visual Studio 2005. This is a managed project. The application starts at around 5-6MB (according to Task Manager) and starts to exhibit symptoms of failure around the ~200MB mark. I know Task Manager is a crude tool, but given the scale of the leak it seems OK to use.
I've narrowed the problem to MySQL Database interaction. If the application does not interact with the database, no memory is leaked.
All database interactions use mysql++. I've followed the build instructions in the man pages on tangentsoft.net.
We've evaluated the code for thread safety (that is, we ensured that each thread only uses mysqlpp object from that thread and no other) and checked to make sure all destructors are called for any dynamically generated objects created using 'new'.
Looking on the internet I keep seeing various reports from users of the mysqlpp class that indicate there is a leak somewhere. In particular, there was a discussion about how the Win C API would leak when mysqlpp was used:
http://www.phpmarks.com/6-mysql-plus/ffd713579bbb1c3e.htm
This discussion seems to conclude in a fix, however, when I try the fixes in my application it still leaks.
I implemented a version of the application cited in the thread above, but with some of the advice from the man pages added:
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
while (true)
{
//Initialise MySQL API
mysql_library_init(0, NULL, NULL);
Sleep(50);
//Connect to Database.
mysqlpp::Connection c;
c.connect("myDatabase","localhost","username","password");
Sleep(50);
//Disconnect from Database
c.disconnect();
Sleep(50);
//Free memory allocated to the heap for this thread
c.thread_end();
Sleep(50);
//Free any memory allocated by MySQL C API
mysql_library_end();
Sleep(50);
}
return 1;
}
I added the Sleep(50) just to throttle each stage of the loop, so that each function has time to "settle down". I know it probably isn't necessary but at least this way I can eliminate that as a cause.
Nevertheless, this program leaks quite rapidly (~1mb per hour).
I've seen similar questions to mine asked in a few places, with no conclusions made :(
So i'm not alone with this issue. It occurs to me that the mysqlpp class has a reputation for usefulness and so must be quite robust. Given that is the case, I still can't see what i've done wrong. Does anyone have some experience of mysqlpp with Visual Studio 2005 that might shed light on the problem?
Cheers,
Adam.
EDIT
I created another example using a pointer, just in case c was being duplicated in the loop:
//LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
mysqlpp::Connection * c;
while (true)
{
mysql_library_init(0, NULL, NULL);
c = new mysqlpp::Connection;
Sleep(50);
c->connect("myDatabase","localhost","username","password");
Sleep(50);
c->disconnect();
Sleep(50);
c->thread_end();
Sleep(50);
mysql_library_end();
Sleep(50);
delete c;
c = NULL;
}
return 1;
}
This also leaks. I then created a control example based on this code, which doesn't leak at all:
//NOT LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
char * ch;
while (true)
{
mysql_library_init(0, NULL, NULL);
//Allocate 4000 bytes
ch = new char [4000];
Sleep(250);
mysql_library_end();
delete ch;
ch = NULL;
}
return 1;
}
Note that I also left the calls to the MySQL C API here to prove that it isn't the cause of the leak. I then created an example using a pointer but without the calls to connect/ disconnect:
//NOT LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
mysqlpp::Connection * c;
while (true)
{
mysql_library_init(0, NULL, NULL);
c = new mysqlpp::Connection;
Sleep(250);
mysql_library_end();
delete c;
c = NULL;
}
return 1;
}
This doesn't leak.
So the difference is just the use of the mysqlpp::connect / disconnect methods. I'll dig into the mysqlpp class itself and try to see whats up.
Cheers,
Adam.
EDIT
Here is an example of the leaky code where checks are made.
//LEAKY
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
mysqlpp::Connection * c;
while (true)
{
mysql_library_init(0, NULL, NULL);
c = new mysqlpp::Connection;
Sleep(50);
if ( c->connect("myDatabase","localhost","username","password") == false )
{
cout << "Connection Failure";
return 0;
}
Sleep(50);
c->disconnect();
Sleep(50);
c->thread_end();
Sleep(50);
mysql_library_end();
Sleep(50);
delete c;
c = NULL;
}
return 1;
}
Cheers,
Adam.
Related
I'm trying to write a simple C++ app that registers to Windows sensor events.
I followed the MSDN documentaion and managed succesfully to get notifications when sensor events occur, my problem is that my main function ends, and so does the application.
How to i cuase it to wait forever for events to occur? Currently it registers and dies...
I have the following code:
My main looks like this:
int _tmain(int argc, _TCHAR* argv[])
{
RegisterToSensorEvents();
return 0;
}
void RegisterToSensorEvents()
{
ISensorManager* pSensorManager = NULL;
CoInitialize(NULL);
HRESULT hr = ::CoCreateInstance(CLSID_SensorManager, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSensorManager));
// Get a collection of all sensors on the computer.
ISensorCollection* pSensorCollection = NULL;
hr = pSensorManager->GetSensorsByCategory(SENSOR_CATEGORY_ALL, &pSensorCollection);
EventsManager *pEventClass = NULL;
ISensorEvents* pMyEvents = NULL;
pEventClass = new(std::nothrow) EventsManager();
hr = pEventClass->QueryInterface(IID_PPV_ARGS(&pMyEvents));
ULONG numOfSensors;
pSensorCollection->GetCount(&numOfSensors);
for(int i=0; i< numOfSensors; i++)
{
ISensor *sensor = NULL;
pSensorCollection->GetAt(i,&sensor);
hr = sensor->SetEventSink(pMyEvents);
}
}
EventsManager is a class that derives from ISensorEvents and implements its callbacks, for example:
STDMETHODIMP EventsManager::OnDataUpdated(ISensor *pSensor,ISensorDataReport *pNewData)
{
cout <<"got here: Data Update" << endl;
}
I tried:
int _tmain(int argc, _TCHAR* argv[])
{
RegisterToSensorEvents();
while(true){}
return 0;
}
but seems like this infinte loop did not leave time for the program to process the incomming events, I tried adding Sleep in the loop body, but it didn't work either.
anyone?
UPDATE:
after investigation i see that the issue is different - seems like somehow my registartion of SetEventSink gets canceled and that is why i don't get any event notification.
if i copy this line:
hr = sensor->SetEventSink(pMyEvents); into my loop:
while(true)
{
hr = sensor->SetEventSink(pMyEvents);
}
the events are fired as expected. But it sounds to me very wrong to do such a thing.
Need to understand why this is hapenning.
Can anyone help?
Why don't you launch a new thread to do the listening, and just have the main function wait for an input?
How to simulate "Press any key to continue?"
Simple example of threading in C++
You can combine these to get your desired result.
I have a really strange problem. Looking for the cause on the web and try everything. Nothing helps.
First case:
(This works exactly as expected. Windows task manager shows the constant memory size, and does not increase.)
unsigned long WINAPI thfun(void * arg)
{
::Sleep(50);
::ExitThread(0);
return 0;
}
int main(int argc, const wchar_t ** argv)
{
HANDLE th = 0;
DWORD thid, err;
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
}
return 0;
}
Second case:
unsigned long WINAPI thfun(void * arg)
{
::Sleep(50);
::ExitThread(0);
return 0;
}
int main(int argc, const wchar_t ** argv)
{
WORD ver;
WSADATA wsadata;
ver = MAKEWORD(2, 2);
if (WSAStartup(ver, &wsadata)) return 1;
::Sleep(50);
HANDLE th = 0;
DWORD thid, err;
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
}
return 0;
}
If I call any function from winsock least once created threads do not release memory.
Windows task manager shows ever-growing memory of my application.
What should I do so that I achieve the same behavior as in the first case when I use winsock?
I use visual studio 2013
Thank you very much for any help
You do not close your thread handles. A common error.
Your core loop should look like that:
while (true)
{
th = ::CreateThread(0, 0, thfun, 0, 0, &thid);
if (!th)
{
err = ::GetLastError();
}
::WaitForSingleObject(th, INFINITE);
CloseHandle(th);
}
That problem exists in both of your examples. That memory grow of the second sample can be a side effect.
ExitThread(0) is never a good idea and I do not understand why Microsoft recommand it for C. As the Winsock API should not have any destructor, it should not be a problem. Nevertheless, do not use it.
UPDATE
I tested your code as release on a Windows 7 64bit SP1 System with Antivira personal installed (my gaming machine). Also on my Windows 8 VM (parallels). Both system did not show the problems you described and show in your video. This is IMHO good news for you, because it seems a problem of your installation and not a general problem.
The video shows a leak of only a few bytes per ended thread and strict linear growing per thread. This looks for me like thread associated information, usually stored nowadays in TLS (Thread Local Storage). Also it only appears when you init The WSASocket system. If the WSASocket system itself would be the problem, we would found reports of it for sure(but I didn't). I believe a hook DLL is causing that problem, a DLL is informed over the DllMain of any started or ended thread of the process. Any virus scanner or keyboard addon(!) can cause such a problem as they usually use hook DLLs and manipulate IOs like pipes and sockets.
Unfortunatly I only know one way to find out:
Make a release canditate of your sample. Make sure the problem exist.
Make a clean install of Windows 7
Install step by step the environment you use on your produktive system. Make sure you restart the Computer after every step.
Hopefully find the culprit.
Deactivating or uninstall hooks may help but need not. Unfortunately installing programs on windows system is maximal inversive.
Sorry for not heaving the easy answer.
I've been trying to debug a memory leak in my program, and have narrowed it down to the WinHttp comms. I've been able to reproduce the problem in the following test code:
#include <windows.h>
#include "winhttp.h"
void main() {
while (1) {
HINTERNET send_session = WinHttpOpen(L"asdf", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
WinHttpCloseHandle(send_session);
}
}
After running this for a few seconds, the program is already using over 20MB memory. Why is it doing this? The API states that you need to call WinHttpCloseHandle after the handle is no longer needed - I'm doing that.
I'm compiling using mingw32 on Arch Linux, and running the code on Windows 7.
If you modify the code a bit, you will see what is happening.
int _tmain(int argc, _TCHAR* argv[])
{
for(INT n = 0; n < 1000000; n++)
{
if(!(n % 10000))
_tprintf(_T("%d\n"), n / 10000);
HINTERNET send_session = WinHttpOpen(L"asdf", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
WinHttpCloseHandle(send_session);
}
_tprintf(_T("Done\n"));
Sleep(INFINITE);
return 0;
}
Along with creating/closing one million of sessions you will see counters climbing up. The API creates background resources including threads and does not release them immediately, so they keep piling up.
However as soon as you stop creating new sessions and let it have a few seconds of idle time - you will see all that memory is released.
The bottom line is that in real code you should not create a separate session for every small thing. One session might be hosting multiple connections and requests.
I am using C++ and Visual Studio 2005.
I have a project that memory Increases in a very abnormal. When debug the code I Realized That there are Several parts That Contribute to it. Like this for example:
// has to add crypt32.lib to link
#include <windows.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void memoryUP( const unsigned char *pData, int cData )
{
HCRYPTMSG msg = NULL;
HCRYPTPROV hProv = NULL;
CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,0);
msg = CryptMsgOpenToDecode(MY_ENCODING_TYPE,0,0,hProv,NULL,NULL);
if(!(CryptMsgUpdate( msg, pData, cData, TRUE)))
{
if(msg != NULL)
{
CryptMsgClose(msg);
msg = NULL;
}
}
if (hProv != NULL)
CryptReleaseContext(hProv,0);
if (msg != NULL)
{
CryptMsgClose(msg);
msg = NULL;
}
}
int main(int argc, char** argv)
{
MyFile myfile = myReadFile("c:\\file.p7s");
{
for(int i=0; i<100000; ++i)
{
memoryUP( myfile._data, myfile._length );
}
}
delete myfile;
return 0;
}
When I run this code, the memory goes up continuously "when call CryptMsgUpdate". Am I deallocating wrong?
I tried to use Memory Leak Detection Enabling method to detect memory leak but nothing appears:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
and
_CrtDumpMemoryLeaks();
Thanks in Advance
You have to release resources in reverse order of their acquisition:
CryptAcquireContext();
if (success)
{
CryptMsgOpenToDecode();
if (success)
{
CryptMsgClose();
}
// else: nothing to close, opening failed
CryptReleaseContext();
}
// else: nothing to release, acquisition failed
The deeper nested constructions depend on the outer ones and may lock up resources, so you can only release the prerequisite resources after you've released the dependent ones.
Since you tagged this C++, I would be remiss to mention that those sort of things should be handled with RIAA, and you should make a class that takes responsibility for the resource. As you can see even in this simple example, writing the correct error checking paths very quickly become onerous, so it'd be much better and more modular to have a class that cleans up after itself, which automatically happens in the correct order.
I think you should call CryptMsgClose before CryptReleaseContext.
I am working on getting the version of the Software which is installed on the Computer. I have implemented the logic for reading the Uninstall hive of registry, but i have observed that some of the software are not having version entries in the Uninstall hive of the registry. But i want to show the version of those softwares also.
Can some one help me out in this regard?
Supplying a software version to the registry of Windows is voluntary. If the developer of the software you're looking at chose to not display the version there or was simply unaware of such possibility, I am unable to point you to any other location he would choose to use or be aware of. In fact, the software might not even have a version number/name.
Ask yourself this: Where else is the Version detail of the software available if not in the registry? If it is available somewhere else other than registry, ask us if you could get that detail using C++. I guess this would be a better approach to solve your issue.
Added the information below since OP is looking for file version
See if the below code could help you.
CString GetFileVersionInfo(CString strFile, CString strProperty)
{
int rc;
UINT nLen;
DWORD nSize;
DWORD dwHandle = 0;
CString strBuffer;
CString strValue;
CString strBlock;
void *lpPropertyBuffer;
struct LANGANDCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
nSize = GetFileVersionInfoSize(strFile.GetBuffer(strFile.GetLength()), &dwHandle);
::GetFileVersionInfo(strFile.GetBuffer(strFile.GetLength()), 0, nSize, strBuffer.GetBuffer(nSize));
// Read the list of languages and code pages.
if (VerQueryValue(strBuffer.GetBuffer(strBuffer.GetLength()), "\\VarFileInfo\\Translation", (LPVOID *) &lpTranslate, &nLen))
{
strBlock.Format("\\StringFileInfo\\%04x%04x\\%s",
lpTranslate->wLanguage,
lpTranslate->wCodePage,
strProperty);
rc = VerQueryValue(strBuffer.GetBuffer(strBuffer.GetLength()), strBlock.GetBuffer(nSize), &lpPropertyBuffer, &nLen);
if (rc != 0 && nLen > 0)
{
strncpy(strValue.GetBuffer(nLen + 1), (char *) lpPropertyBuffer, nLen);
strValue.ReleaseBuffer(nLen);
}
}
return strValue;
}
user version.lib while linking and you might need winver.h for compilation. You can call the function like this
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
AfxMessageBox(GetFileVersionInfo("shell32.dll", "ProductVersion"));
}
return nRetCode;
}
I'd say look at the file version information. And you might find this article useful on how the Add/Remove Programs dialog gets its information.
If the software developers chose not to add version information into Uninstall information, then there's no reliable way to get it.
You can try to find where application is installed. But even if you have the path, the application can consist of several .exe files which can have different versions and product names. If you add DLLs into the candidate list for getting version information, your results become even less predictable.