|
I'm kind of wondering what is being leaked - here's a trick that can sometimes find the culprit. It's more useful if the dump always shows the same allocation number.
Start your debug session with F10 - when it stops at the program entry, open the variables window and type in _crtBreakAlloc on a new line - you should get a -1 for the current value. Change that to the allocation number of the dump (1143) and the code will break when the allocation occurs. Use the call stack to see what object is being allocated.
This doesn't always work - the declspec of _crtBreakAlloc is controlled by the _CRTIMP macro in the runtime lib, meaning it's not always exported and visible to your application.
You can also search the MSDN for a more advanced approach to using _crtBreakAlloc.
|
|
|
|
|
Well, I created a new project, put a new Static Text control on my form, created a variable for it, copied code exactly from my old project and no more memory leaks.
I think it was because I changed the control I was using from an Edit Control to a Static Text, and used the same name. I checked to see if the DataExchange was set up correct and it seemed fine. Only thing I could think of would be behind-the-scenes type handling issues from changing the control type.
Thanks for the help though!
|
|
|
|
|
Hi,
I am using LoadLibrary() and GetProcAddress() to get an exported function from a dll. The exported function looks like this:
extern "C"
{
char *getStuff()
{
return new char[10];
}
}
When I call this function everything works fine until I try and 'delete' the memory that was allocated in this function. I get this error in the debug version - "HEAP[GenericTester.exe]: Invalid Address specified to RtlValidateHeap( 2f0000, 7b27a0 )". From what I guess that means that the application is trying to free memory from a different heap than the memory was allocated from?
My question then is: how do I allocate memory inside of the GetProcAddress() function that can be freed by the calling application?
Thanks!
|
|
|
|
|
|
well the hyperlink was supposed to take you to the article, but I tested it and it failed. I should have included the article title
DLL newing objects on process heap
Its on the next page down after the page this is on (with 20 odd to the page)
Stephen Kellett
|
|
|
|
|
Thanks!
It works now. I linked both with 'MultiThreaded DLL' so that the dll and application both use the same heap manager.
|
|
|
|
|
I usually go a different route in this case.
I generally add 2 functions: a CreateXXX and a DestroyXXX. The Create does the allocation and destroy frees the memory.
This has the following side benefit: usually you are not simply allocating a block of memory, you are setting up other things like access to ports, hw resources, etc. When it comes time to free the memory, you usually have to cleanup other stuff, so why not do it all in one spot and the end user doesn't have to worry about the details.
Mike
|
|
|
|
|
That is a good idea. I'm not sure that I want to use it in this case though?
The function in the DLL is called many times and returns many character buffers. That means that I have to keep track of all of these allocated character buffers in the dll, so that wehn DestroyXXX is called I free them all. I also can't have a DestroyLastAllocatedBuffer() function that frees the most recently allocated character buffer because the function in the DLL can be called by many different threads. (caveat: you probably could do both of the above with some extra work, but it might be more work than it is worth?)
I'd prefer for the calling application to be able to call the DLL function to get a characted buffer and then free it right after it is done with the buffer.
I think I have another solution though. You can create a C++ object with a destructor that does the memory freeing. It seems to work, anyone see any problems?
// Text holder class
CTextHolder
{
public:
CTextHolder()
~CTextHolder() { delete text; };
char *text;
};
// This is the exported function in the dll
extern "C"
{
CTextHolder * getText()
{
CTextHolder *blah = new CTextHolder();
blah->text = new char[20];
return blah;
}
}
// This is the function in the application that calls the exported function in the DLL
void testCall(void)
{
HMODULE mod = LoadLibrary("d:\\plugin.dll");
if(mod == NULL)
return;
// Test function is typdefed as.. typedef CTextHolder * (*aFunc)(void);
testFunction getText = (testFunction) GetProcAddress(mod, "getText");
if(getText == NULL)
return;
CTextHolder *blah = getText();
// Yay.. this seems to work fine
delete blah;
FreeLibrary(mod);
}
|
|
|
|
|
You wouldn't need to keep a list of anything.
s = CreateXXX();
...
DestroyXXX( s );
The functions would be something like this:
char *CreateXXX()
{
return new char[20];
}
///
//I would actually Code CreateXXX as follows
//ERRCODE CreateXXX( char **s )
//{
// *s = new char[20];
// return NOERR;
///}
ERRCODE DestroyXXX( char *s )
{
delete s[];
}
|
|
|
|
|
That seemed like a good solution to me too and I tried it, but it gave me an access violation. There may have been some bugs in my code (not allocating a large enough buffer and overflowing it), I'll try it again.
Thanks!
|
|
|
|
|
I think thats called a destructor.
|
|
|
|
|
I agree,
The CreateXXX,DestroyXXX approach is a good approach *if* the DLL the is designed to
be used as a black box, where it is always responsible for allocation and deallocation
of resources. However the original poster did not specify that.
Sometimes the black box approach is not appropriate for architectural or performance
reasons. Other times it is. I think both approaches have their merits.
Stephen Kellett
|
|
|
|
|
I am trying to use RasDial to establish an internet connection, but am getting an error that I don't understand. Here is the code that I am using:
RASDIALPARAMS dialParams;
DWORD dwRes;
CString cs;
char szError[50];
dialParams.dwSize = sizeof( RASDIALPARAMS );
strcpy( dialParams.szEntryName, "" );
strcpy( dialParams.szPhoneNumber, "szPhone" );
strcpy( dialParams.szCallbackNumber, "" );
strcpy( dialParams.szUserName, "szUser" );
strcpy( dialParams.szPassword, "szPW" );
strcpy( dialParams.szDomain, "" );
dwRes = RasDial( NULL, NULL, &dialParams, 0, NULL, &m_hRasConn );
if( dwRes == 0 )
{
     m_list.AddString( "Success." );
}
else
{
     RasGetErrorString( dwRes, szError, sizeof(szError) );
     cs.Format( "Error: #%d = %s - Handle: %s", dwRes, szError, (m_hRasConn == NULL) ? "NULL" : "Non-NULL" );
     m_list.AddString( cs );
}
The error that I'm getting is that it "Cannot find phonebook entry." My understanding is that this makes no sense, since in Win98, phonebooks are not valid and should be ignored.
I've checked the article at http://www.codeproject.com/internet/dialup.asp, but my code seems identical to that example.
Does anyone have any suggestions?
Thanks,
Matt J
|
|
|
|
|
Hello, the codegurus around the world.;)
I think that you should put any name in szEntryName.
If you put szEntryName as "", it means no entry phonebook.
Have a nice day!
-Masaaki Onishi-
|
|
|
|
|
I'm developing some kind of editor that needs line numbers in this format "N%i" to work.
How should I get the key press and modify the text of the edit control?
Thank you in advance.
|
|
|
|
|
I'm trying to write an MDI multithreaded app. I know I'll have a socket thread and what I'm trying to do is create a thread for each document that is opened. These document threads will need to talk with the socket thread and also with the GUI (menu selections, tiling etc.) The problem I'm having right now is that if the user touches any of the menus or drags a document view around, the other document view aren't updated. This is why I started down the thread per document road. I have the docuement thread working in that I created a UI thread (AfxBeginThread(RUNTIME_CLASS(MyDocThreadClass), THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
The problem that I think I have is that I'm creating the document in the main thread using the doctemplate stuff then giving a pointer to the document to the thread that I create for that document. The DocThreadClass will handle and catch the messages for the document (to/from the socket) but I'd like to update the document view when these socket messages come in. I might be mistaken but I believe that I'll still have the problem of the GUI "locking" the doc threads whenever I try to update the view or whenever the main frame/thread interacts with the user (dragging, menu selections). I'm new to the whole MFC thing so II might be overlooking something simple. I'm also sorry about the length but I couldn't explain it very simply.
|
|
|
|
|
Hi,
I cant access Access 2000 file from VC 6 Enterprise Edition.
I tried opening the database and got the "Unrecognized database format <filename>". Earlier that file was created in Access 97 format (thru VC) and it was working fine. The problem is that I converted that file to Access 2000.
One thing is that Access 97 had Jet Version 3.0. And Access 2000 has version 3.5/4 (I got this info from registry).
Any one any ideas? Any update I have to install? If yes, plz give me the URL.
Thanks,
Ammar
|
|
|
|
|
Hello, the codegurus around the world.
Configuration of Access 2000 issue is known well as the bug at VC++.
You can find the solution in MSDN magazine or MSDN help, I think.
Some header file, which I forgot, configures which version of Access is used in VC++ project. So, we simply add the new lines to this header file for Access 2000.
Have a nice day!
-Masaaki Onishi-
|
|
|
|
|
Actually I do not think this is a bug, the problem comes from the fact that the Access 2000 uses new version of DAO (3.6) and MFC by default supports version 3.5. To correct this all you have to do is chage version of MFC that you are using. This can be done with following line of code, just make sure that you call this before you try to open the database:
AfxGetModuleState()->m_dwVersion = 0x0601;
Pz
|
|
|
|
|
Hi,
Many many thanks. I think your line of code works. Atleast it went thru that line in debug mode.
One more thing...
I am creating an access file in runtime with this code:
db.Create("DOB.mdb", dbLangGeneral, dbVersion30);
db.Execute("CREATE TABLE DOB (Name Text, Email Text)");
What happens is that this creates a file comaptible with Access97. Now I want to create a file for Access2000. dbVersion30 is for A97. I tried dbVersion35 and dbVersion40 but these two are undeclared identifier.
How to create Access2000 mdb file?
I have VC 6.0 Enterprise Ed.
Ammar
|
|
|
|
|
Thanks for the solution. It works fine.
However I couldnt find any info on AfxGetModuleState() in MSDN. Can you help me on this? Where to find info about this API and AFX_MODULE_STATE ?
Your email address will be appreciated.
Thanks,
Ammar
|
|
|
|
|
Are all the VCPP Common Controls Active X controls? For example CEdit.
|
|
|
|
|
No - they are classes derived from CWnd.
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
Actually, CEdit is actually a Windows CONTROL which CEdit subclasses.
|
|
|
|
|
I'm a Windows programming beginner, been programming DOS for some time, starting to make the switch and I'm having a niggly bit of trouble trying to display a messagebox immediately after a dialog.DoModal() . Has anyone out there seen this type of behaviour where any messagebox call after a dialog box fails to be displayed? Did I miss something obvious?
The application was created as an simple MFC GUI app.
Your help is much appreciated.
//*********************************************************************
dlg.m_strWarningtext.Format(strMsgBuf);
nResponse = dlg.DoModal();
// >>>>> At this point, any messagebox call returns IDOK without even being displayed.
if (nResponse == IDOK)
{
// Do stuff
sprintf(strMsgBuf,"Messagebox text ");
nRetVal = MessageBox( NULL, (LPCTSTR)strMsgBuf, "Error", MB_OK | MB_ICONERROR );
// >>>>> nRetVal is always == IDOK and the messagebox won't display
}
else if (nResponse == IDCANCEL)
{
// Do stuff
}
//*********************************************************************
|
|
|
|