problem with freeing memory in dll
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 37

Thread: problem with freeing memory in dll

  1. #1
    Join Date
    Nov 2009
    Location
    California
    Posts
    31

    problem with freeing memory in dll

    i have a dll that exports a class - it uses an abstract base class with pure virtual functions(defined in a header file), then a function to export it that returns a new object. insided the class is a 'release' function that deletes the object. now in another dll of mine, i dont do anything with the deconstructor, but in this one for some reason i have to have the same 'delete this' as i do in the release function or it crashes. now in the host application is where i get some sort of problem. note - it runs/finishes without error but some code isnt being exectued or something.

    typedef IMyObj* (*PFNCreate)();
    //main
    char dllName[] = "dllname.dll";
    HMODULE hmod = LoadLibrary(dllName);
    if (!hmod)
    {
    cout << "error loading dll" << endl;
    return 0;
    }
    PFNCreate pfnCreate = (PFNCreate)GetProcAddress(hmod, \
    TEXT("CreateObject"));
    IMyObject* obj = (pfnCreate)();
    obj->function1();
    //some code
    cout << "??" << endl; //i get this outputted
    obj->release();
    delete obj;
    FreeLibrary(hmod);
    cout << "??"; //######## THIS DOESNT GET PRINTED
    return 0;

    thank you in advance, if more code is necessary to see what is going on let me know and ill post it.

  2. #2
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Wink Re: problem with freeing memory in dll

    Quote Originally Posted by rhboarder View Post
    obj->release();
    delete obj;
    Why are you using delete here? You said yourself that release() deletes the object.
    My hobby projects:
    www.rclsoftware.org.uk

  3. #3
    Join Date
    Nov 2007
    Location
    Birmingham, England
    Posts
    157

    Re: problem with freeing memory in dll

    I'm a bit confused by your code.

    You've gone through the effort of using dynamic access to the DLL. That is you used "LoadLibrary" and then "GetProcAddress" to find the function pointer to the "CreateObject" function.

    But your code doesnt do the same for the "release function".
    Is "release" a function pointer in the object?

    If so, can you check to see that its getting fired correctly.

    If not then could you explain how your code finds "release" but requires "GetProcAddress" to find "CreateObject"

    Regards
    Last edited by couling; November 12th, 2009 at 05:07 PM.
    Signature
    Please use: [ code ][/ code ] tags and reasonably correct tabbing. They really help us read your code
    End Signature

  4. #4
    Join Date
    Nov 2009
    Location
    California
    Posts
    31

    Re: problem with freeing memory in dll

    for the 1st reply: honestly i dont know why i needed it, i saw it done that way in a tutorial i read when learning how to export a class. and also the program crashes if i dont... 2nd reply - the release function is a class member in the class that's exported by CreateObject so you dont need to call getprocaddress for that. and i did check and it is getting fired correctly. here is a more complete code:
    //#### header file for the dll
    #if defined(DLL_EXPORT)
    #define MYAPI __declspec(dllexport)
    #else
    #define MYAPI __declspec(dllimport)
    #endif
    class IMyObj //abstract interface
    {
    public:
    //note - in sample tutorials ive read it says to have a deconstructor for the
    // interface class but whenever i add 'virtual ~IMyObj()=0;' it doesnt compile.
    virtual bool function1()=0;
    virtual bool function2()=0;
    virtual void release()=0;
    };

    extern "C" MYAPI IMyObj* __stdcall CreateObject();

    //#####in dll(.cpp) file
    #define DLL_EXPORT
    #include "myheaderfile.h"
    class myObj : public IMyObj
    {
    public:
    ~myObj()
    {
    cout << "deconstructor" << endl;
    delete this; //as i said earlier in another app i wrote this line
    //wasn't needed but now if i dont the program crashes
    }
    virtual bool function1()
    {
    //code
    }
    virtual void release()
    {
    delete this;
    }
    };
    IMyObj* __stdcall CreateObject()
    {
    return new myObj;
    }

    //#### and then i include this header in the file that contains the code i previously posted.

  5. #5
    Join Date
    Nov 2007
    Location
    Birmingham, England
    Posts
    157

    Re: problem with freeing memory in dll

    Quote Originally Posted by rhboarder View Post
    and also the program crashes if i dont...
    Any chance you could find what the error message is. If you're on windows vista you may have to go digging.

    It just all seems that something is not happening as it appears. Deleting an object twice will cause an error and this code is deleting obj twice by what you're telling me:
    Code:
    obj->release();
    delete obj;
    If you like I could take a look at your full source code (dll as well) and have a dig into what's happening. Which compiler are you using?
    Signature
    Please use: [ code ][/ code ] tags and reasonably correct tabbing. They really help us read your code
    End Signature

  6. #6
    Join Date
    Nov 2009
    Location
    California
    Posts
    31

    Re: problem with freeing memory in dll

    sorry bout the tags guys. i totally agree that deleting it twice should cause an error. but when i remove one i get another crash. For the compilor I'm using Borland 5.5 command line tools (bcc32). the error -
    (in ollydbg) - access violation when writing to -
    Code:
    3250308F  8943 08  MOV DWORD PTR DS:[EBX+8],EAX
    //and it says DS:[00000008] = ???
    do you have an email address you'd like me send it to couling?

  7. #7
    Join Date
    Nov 2007
    Location
    Birmingham, England
    Posts
    157

    Re: problem with freeing memory in dll

    I can PM you my email if you open your PM, or you can attach it as a zip on another message on this thread.
    Signature
    Please use: [ code ][/ code ] tags and reasonably correct tabbing. They really help us read your code
    End Signature

  8. #8
    Join Date
    Nov 2009
    Location
    California
    Posts
    31

    Re: problem with freeing memory in dll

    here you go, i've attached a zip file containing the source files. thank you for taking a look at it.
    Attached Files Attached Files

  9. #9
    Join Date
    Apr 1999
    Posts
    27,422

    Re: problem with freeing memory in dll

    Quote Originally Posted by rhboarder View Post
    here you go, i've attached a zip file containing the source files. thank you for taking a look at it.
    The design is bad.

    You are using two different heap managers, the DLL's and the apps. You can't call "new" in the DLL, and then use that same pointer in the call to "delete" in the application. The bottom line is -- unless your application and DLL are using the same heap manager, pointers returned by "new" from one DLL/app are incompatible with calls to "delete" in another DLL/app.

    The DLL should be solely responsible for allocating and deallocating its own memory. If the DLL allocates, the DLL does the deallocation. The app shouldn't be in the business of knowing how the instance was created -- that detail is within the DLL.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; November 13th, 2009 at 04:34 AM.

  10. #10
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: problem with freeing memory in dll

    Quote Originally Posted by rhboarder View Post
    for the 1st reply: honestly i dont know why i needed it, i saw it done that way in a tutorial i read when learning how to export a class. and also the program crashes if i dont...
    The program will crash anyway!

    Quote Originally Posted by rhboarder View Post
    [code]
    ~myObj()
    {
    cout << "deconstructor" << endl;
    delete this;
    }

    virtual void release()
    {
    delete this;
    }
    Think about what happens when you call release(). The delete will correctly call the destructor, but then the delete in the destructor will also call the destructor, an infinite loop!

    So you need to remove the delete from the destructor and then find out the other reasons why the program crashes.
    My hobby projects:
    www.rclsoftware.org.uk

  11. #11
    Join Date
    Nov 2009
    Location
    California
    Posts
    31

    Re: problem with freeing memory in dll

    so i removed the delete from the deconstructor and the 'delete obj' in the hosting application so now it is:
    Code:
    IMyObj = (pfnCreate)();
    obj->function1();
    cout << "????" << endl;
    obj->realease();
    FreeLibrary(hmod);
    //this last cout gets printed but the program crashes right after 
    //it outputs it
    cout << "??????";
    return 0;
    function1 is good, it executes perfectly, and i checked and release is getting fired... still unable to figure out what could be causing it to crash.

  12. #12
    Join Date
    Apr 1999
    Posts
    27,422

    Re: problem with freeing memory in dll

    Quote Originally Posted by rhboarder View Post
    so i removed the delete from the deconstructor
    The correct term is destructor, not deconstructor.

    Also, please use code tags when posting code.

    still unable to figure out what could be causing it to crash.
    Please repost the changed code for both the DLL and the application (and again, use code tags when posting code -- the code you posted is unformatted and almost impossible to read).

    Regards,

    Paul McKenzie

  13. #13
    Join Date
    Nov 2007
    Location
    Birmingham, England
    Posts
    157

    Re: problem with freeing memory in dll

    Sorry that took me a while. Haven't used Borland in a while, so I needed to crank up my old pc. For your reference I'm using Borland C++ explorer 2005.

    The code you attached was fine, I took out the two lines mentioned by Paul and Zaccheus and and there was little else wrong with it as such. That's not to say it didn't crash, just I don't think you'd done anything else particularly wrong.

    The reason why putting "delete this;" in the destructor stopped it crashing was because (somehow) the resulting stack overflow it was causing was making it crash silently before it had chance for anything else to go wrong. And the line "delete spy" was doing nothing for me at all (different compiler version perhaps ).

    So What's making it crash?
    A little testing revealed that calling any virtual function in the DLL would cause a crash iif FreeLibrary was used to unload the dll. The crash actually occurred at the very end of your program (when main() called return 0; ). My only explanation is that its being caused by a little black magic going on in the way Borland calls virtual functions.

    How to fix it?
    you need to stop using vartual function calls across exe/dll boundaries or stop using Borland. When I compiled this with MinGW everything ran fine, when I removed all calls to virtual functions in the DLL in Borland it ran fine. When I had only one call to a virtual function that did nothing more than [ cout << "hello world" << endl; ] it crashed again.


    Accessing DLLs in this way is really only necessary to load plug-in modules or to load a DLL after the program has started running. I was just wondering if you've been told to load a DLL this way by an article / tutorial of if you have a specific reason for doing it this way?
    Attached Files Attached Files
    Last edited by couling; November 13th, 2009 at 03:31 PM. Reason: Correcting Typos and forgot the attachment
    Signature
    Please use: [ code ][/ code ] tags and reasonably correct tabbing. They really help us read your code
    End Signature

  14. #14
    Join Date
    Nov 2009
    Location
    California
    Posts
    31

    Re: problem with freeing memory in dll

    yes it was from several articles i had read that made me think you had to do it that way. with the virtual functions, doesn't it have to be that way though because you change the implementation in the derived class? i've removed the virtual keywords. but now i get an error when compiling the application that loads the dll:
    Code:
    Error: Unresolved external 'IProcSpy::showProcesses(int __stdcall (*)(std::basic
    _string<char, std::char_traits<char>, std::allocator<char> >))' referenced from
    I:\TOOLS\BIN\WINPROCSPY.OBJ
    Error: Unresolved external 'IProcSpy::release()' referenced from I:\TOOLS\BIN\WI
    NPROCSPY.OBJ
    here is the new code:
    Code:
    //header file
    #ifndef PROCESSVIEWER_H
    #define PROCESSVIEWER_H
    
    #include <windows.h>
    #include <string.h>
    #include <tlhelp32.h>
    
    #if defined(DLL_EXPORT)
    	#define MYAPI __declspec(dllexport)
    #else
    	#define MYAPI __declspec(dllimport)
    #endif
    
    typedef BOOL (CALLBACK* PSENUMPROC_S)(string);
    
    class IProcSpy
    {
    public:
    	bool showProcesses(PSENUMPROC_S);
    	void release();
    };
    extern "C" MYAPI IProcSpy* __stdcall CreateProcSpy();
    
    #endif
    
    //dll cpp file
    #define DLL_EXPORT
    #include "processViewer.h"
    
    class procSpy : public IProcSpy
    {
    public:
    	~procSpy()
    	{
    		cout << "destructor" << endl;
    	}
    	bool showProcesses(PSENUMPROC_S cbkProc)
    	{
    		HANDLE snapshot = (0);
    		snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    		if (snapshot == INVALID_HANDLE_VALUE) return false;
    		PROCESSENTRY32 pe32;
    		pe32.dwSize = sizeof(PROCESSENTRY32);
    		if (!Process32First(snapshot, &pe32))
    		{
    			CloseHandle(snapshot);
    			return false;
    		}
    		ostringstream oss;
    		do
    		{
    			oss << pe32.szExeFile << ", PID = " << pe32.th32ProcessID;
    			(*cbkProc)(oss.str());
    			oss.str(std::string());
        		                oss.seekp(0,std::ios_base::beg);
    		} while (Process32Next(snapshot, &pe32));
    		CloseHandle(snapshot);
    		return true;
    	}
    
    	void release()
    	{
    		delete this;
    	}
    };
    
    IProcSpy* __stdcall CreateProcSpy()
    {
    	return new procSpy;
    }
    
    //in the main program
    #include "processViewer.h"
    
    typedef IProcSpy* (*PFNCreate)();
    
    BOOL CALLBACK cbkProc(string);
    
    int main()
    {
    	char dllName[] = "processviewer.dll";
    	HMODULE hmod = LoadLibrary(dllName);
    	if (!hmod) return 0;
    	PFNCreate pfnCreate = (PFNCreate)GetProcAddress(hmod, \
    				TEXT("CreateProcSpy"));
    	IProcSpy* spy = (pfnCreate)();
    	spy->showProcesses(cbkProc);
    	spy->release();
    	FreeLibrary(hmod);
    	return 0;
    }
    
    BOOL CALLBACK cbkProc(string str)
    {
    	cout << str << endl;
    	return TRUE;
    }
    thank you guys for all your help and your patience with me.
    Last edited by rhboarder; November 13th, 2009 at 06:35 PM. Reason: changed code

  15. #15
    Join Date
    Nov 2007
    Location
    Birmingham, England
    Posts
    157

    Re: problem with freeing memory in dll

    Ah I see. That raises a number of issues.

    Options for libraries:
    1. Keep the source in a folder and just add it every project
      The easiest option, but it does increses build time and isn't the best way to share a library that's not open source.
    2. Staticly compile it into a lib and add it to every project
      It should be no more dificult than using a DLL. You get a single exe at the end. But you can't mix and match libraries without re-compiling your exe (unlike dlls)
    3. Compile it into a dll
      When you compile a dll, Borland will give you a lib as well. This contains stubs for all your functions. Each "stub" simply calls the aprorpriate function in the dll.


    I want to use a dll... but how?
    There are two options:
    1. By compiling the asociated lib into your exe (making it appear as if everything in the dll is in the lib). With this option windows will load the dll at the same time it loads your exe do all the work in connecting the two for you.
    2. By loading the dll after the program has started running using "LoadLibrary". This is only useful when you want to load a dll after the program has started running, or when you want to make your program load different dlls based on settings or a script.


    If you're just starting out with dlls, I'd get to grips with option 1 first.

    Do I need virtual functions?
    No, not unless you'd need them anyway to achieve your goal in a standalone exe.
    You can even replace virtual functions with function pointers in the object if virtual functions are going to cause problems.

    Why do dlls get used?
    • They're a reasonably reliable way to make redistributable code without giving out the source code.
    • Advanced users can use them as a way to interface between code built with a number of different compilers.
    • You can mix and match dlls after the exe has been compiled (as long as they have the same functions).
    • You can make a program that accepts plugins.
    • because they're cool!

    Okay commercially they dont get used because they're cool, but particularly when learning to program it's allways fun to see what they're about.

    Hope this is of some help
    Last edited by couling; November 13th, 2009 at 07:09 PM.
    Signature
    Please use: [ code ][/ code ] tags and reasonably correct tabbing. They really help us read your code
    End Signature

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center