CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Aug 2004
    Posts
    29

    Unhappy A Newbie's Problems w/ DLLs

    I have a "Model" abstract class with several concrete derived classes. Originally,
    I had test cases to create the various different classes. For instance:

    If (...)
    modelPtr = new Model1;
    else
    modelPtr = new Model2;

    I then call various members functions such as Model1.printParams(paramList), where paramList is a map of name strings with values.

    The declaration of printParams looks something like:
    void printParams(paramList& parameters);

    I wanted to change my implementation so that I could input in the name of a dll file and it would dynamically load the correct concrete model. To do so, I created a DLL for each model and an accompanying interface function that returned a new instance of the specific model. So instead of the above, I simply called:

    getModel(&modelPtr);

    After I had successfully grabbed the "getModel" interface function from whatever DLL I wanted to use. Each DLL basically was a seperate concrete class for Model and an interface function that looked like:

    int getModel(Model** model)
    {
    if (*model == NULL)
    return -1;
    else
    *model= new Model1;
    return 0;
    }

    Unfortunately, now when I attempt to call my printParams function from the newly created Model1, I get a access violation trying to iterate through the list of parameters. Whereas before it would print out each one, now it gives me an exception after printing the first one. The implementation of the printParams function is identical to the one previous; it just got moved along with the rest of the definition of the Model1 to a seperate project and then made into a DLL. Likewise, the definition of paramList is identical between the client code and the DLL model code. I test to verify that I have correctly opened the library, grabbed the function pointer, and gotten a non-NULL model** back after the getModel call.

    I don't understand how this could happen -- especially since I am passing in a reference to the parameters, and both the client code and the DLL code have the same header / source defining what a parameter list is. Any help would be greatly appreciated. Am I just missing something obvious that I should understand about DLL's? Is my interface function create poorly?
    Last edited by liquidroyl; August 26th, 2004 at 06:33 PM.

  2. #2
    Join Date
    Jun 2002
    Location
    Moscow, Russia.
    Posts
    2,176

    Re: A Newbie's Problems w/ DLLs

    The declaration of printParams looks something like:
    void printParams(paramList& parameters);
    Maybe it was just a misprint, but you should declare this function virtual, ot the parent class method would be called. Anyway you should trace in your printParams function to determine the very cause of access violation.
    "Programs must be written for people to read, and only incidentally for machines to execute."

  3. #3
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    Yes it is actually declared virtual -- the code I posted exemplified my issue and is not verbatim. A paramList contains a map of <string, Parameter*> called List_T. When I call the function, I get an access violaton iterating through the map of parameters in this section of code in the "XTREE" include:

    static _Nodeptr _Min(_Nodeptr _P)
    {_Lockit _Lk;
    while (_Left(_P) != _Nil)
    _P = _Left(_P);
    return (_P); }

    This code is called from:
    printParams--
    ...
    List_t::const_iterator foo = mParams.begin();
    List_t::const_iterator end = mParams.end();
    List_t::const_iterator tmp = foo;

    *ERROR HERE* for (tmp; tmp != end; tmp++)
    std::cout<<tmp->first<<std::endl;
    ...

    mParams is the interior List_T containing the paramters.
    It errors after printing the first parameter of the parameter list (there are three). When I revert to using my old code without using DLL's, the function works just fine.
    Last edited by liquidroyl; August 27th, 2004 at 11:44 AM.

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: A Newbie's Problems w/ DLLs

    You are possibly using inconsistent versions of the runtime library between the DLL and the application. If this is the case, any object, not just std::map, will have problems if the object allocates memory internally.

    Please see this link,

    http://www.codeguru.com/forum/showth...+runtime+crash

    Regards,

    Paul McKenzie

  5. #5
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    Paul, thank you for the advice -- I will verify that now. The parameter
    list is being passed by reference from the client code to the Model1 object in both versions; the only difference is that Model1 is created from the DLL now instead of within the client program.

    Both the DLL and client code are set to "debug" mode; I am using VC6.0

  6. #6
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    I am having trouble understanding how it could be a memory problem since it successfully displays the first element ("foo") and only crashes when attempting to get to the second. However, I checked on the runtime libraries being included, and my client code uses /MLd (singly threaded static linked) while my DLL uses /MTd (multithreaded static linked). However, changing my DLL to /MLd did not fix the problem.


    Here is the compilable code
    Model.h (shared)
    Code:
    #ifndef MODEL_H
    #define MODEL_H
    
    #include <string>
    #include <map>
    
    typedef std::map<std::string, int> List_t ;
    
    class Model
    {
    public:
    
        virtual int getID() = 0;
        virtual void print(List_t&) = 0;
    private:
        std::string name;
        
    };
    
    
    extern "C"
    {
    
    typedef int (*LPGETMODEL)(Model** model);
    int getModel(Model **model);
    }
    
    
    
    #endif
    Test.cpp
    ----
    Code:
    
    #include <windows.h>
    #include <stdio.h>
    
    #include "Model.h"
    
    
    HINSTANCE hDLL = NULL;
    LPGETMODEL lpGetModel;
    
    int main()
    {
    
        Model* tempModel;
    
        printf("Loading Model 1...\n");
        hDLL = LoadLibrary("PPM1");
        
    	if( hDLL == NULL )
    		printf("Could not aquire DLL\n");
    	else
    	{
    	    lpGetModel = (LPGETMODEL)GetProcAddress(hDLL, "getModel");
    	}
    
        int a=   lpGetModel(&tempModel);
        List_t foo;
        foo.insert(List_t::value_type("foo", 3));
        foo.insert(List_t::value_type("yup", 4));
    
        int uid = tempModel->getID();
        tempModel->print(foo);
    
        printf("Model 1's UID is: %d\n", uid);
        FreeLibrary(hDLL);
    
    return 0;
    }
    PPM1.cpp
    Code:
    // PPModel1.cpp : Defines the entry point for the DLL application.
    //
    
    #include <windows.h>
    #include "Model1.h"
    #include "head.h"
    
    
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved
    					 )
    {
        return TRUE;
    }
    Model1.cpp
    Code:
    #include "Model1.h"
    
    void Model1::print(List_t& params)
    {
        List_t::const_iterator begin = params.begin();     
        List_t::const_iterator end = params.end();
        List_t::const_iterator tmp = begin;
    
        for(tmp; tmp != end; tmp++)
        {
            std::cout<<tmp->first.c_str()<<std::endl;
        
        }
    
    }
    Model1.h
    Code:
    #ifndef MODEL1_H
    #define MODEL1_H
    
    #include "Model.h"
    #include <stdio.h>
    #include <iostream>
    
    class Model1: public Model
    {
    public:
        Model1(){}
        ~Model1(){}
    
        int getID() {return 7;}
        
        virtual void print(List_t&);
    private:
        std::string name;
        
    };
    
    #endif

    head.cpp
    Code:
    #include "Model1.h"
    
    int getModel(Model** model)
    {
        if (*model == NULL)
            return -1;
        else
    
            *model=  new Model1;
        return 0;
    }
    Last edited by liquidroyl; August 27th, 2004 at 01:01 PM.

  7. #7
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    In this stripped down version the error occurs inside the print function on the
    std::cout<<tmp->first.c_str()<<std::endl;

    line after printing out the first string ("foo"). The nature of the problem seems to be the same however. Again, any additional ideas / help would be greatly appreciated at this point. I attempted using various combinations of runtime libraries with both in debug and both in release modes with no luck.

  8. #8
    Join Date
    Dec 2003
    Location
    Montreal
    Posts
    58

    Re: A Newbie's Problems w/ DLLs

    I also had this problem with different runtime libraries between my EXE and DLL, the ONLY soultion I found was to make everything Multithreaded DLL (Debug or Release), then everything worked again.

    The runtimes have static variables, tables, etc. that need to be shared between the EXE & DLL when you are creating an object in one and processing it in the other. If both are static libraries, they will each have their own copy but they do NOT share so you still have the problem.

    Just remember that now everything will use the DLLs, you MUST make sure the DLLs are available when you install on another computer. This is usually only an issue if you try to distribute the Debug version (of the EXE or DLL). Use the dependancy walker to get a list of all DLLs required for the EXE and DLL you create.

  9. #9
    Join Date
    Feb 2002
    Posts
    4,640

    Re: A Newbie's Problems w/ DLLs

    Another problem could be that you are creating an STL container in your EXE and using that instance in the DLL or vice versa. Microsoft's impelmentation of the STL had (in VS 6.x) issues with passing instances of STL containers from DLL to EXE.

    http://support.microsoft.com/default...b;EN-US;168958

    The issue stemmed from the fact that Microsoft's STL used global variables.

    I don't know if this was fixed in 7.x, I haven't tried it yet, myself.

    Viggy

  10. #10
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    Am I mistaken, or do you just have to change the project options under Project/settings/C++/project options (VC6) to change the the run time libraries?

    Before any changes, the DLL was using the following:

    /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPM1_EXPORTS" /Fp"Debug/PPM1.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c

    And the program was using:

    /nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/PPModel.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c

    I have changed the combinations to MTd/MTd, MLd/MLD, MDd/MDd with no success.

  11. #11
    Join Date
    Feb 2002
    Posts
    4,640

    Re: A Newbie's Problems w/ DLLs

    Quote Originally Posted by liquidroyl
    Am I mistaken, or do you just have to change the project options under Project/settings/C++/project options (VC6) to change the the run time libraries?

    Before any changes, the DLL was using the following:

    /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PPM1_EXPORTS" /Fp"Debug/PPM1.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c

    And the program was using:

    /nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"Debug/PPModel.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c

    I have changed the combinations to MTd/MTd, MLd/MLD, MDd/MDd with no success.
    Did you see the link I posted? Given that you're using VC6.0, you can't create an STL container in your main app, and pass it into your DLL. Microsoft's version of the STL does not support this at all. This is why you are crashing on the second iteration of your container. You either need to encapsulate the STL container completely in the DLL; switch to a vector (which can be passed around); or use another implementation of the STL.

    Viggy

  12. #12
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    Mr Viggy, apologies -- the post after yours was posted in response to a previous poster. I am reading your links right now. Thank you for your advice.

  13. #13
    Join Date
    Feb 2002
    Posts
    4,640

    Re: A Newbie's Problems w/ DLLs

    No problem.

    Vig.

  14. #14
    Join Date
    Aug 2004
    Posts
    29

    Re: A Newbie's Problems w/ DLLs

    Mr. Viggy, I just attempted a similar function call using vectors instead of a map and it worked just fine, so it looks like you are correct. I will look into if the situation is any better on VC 7+. However, if they are not, how would I correct my existing code? As I understand it now, I basically can never have a member function in the DLL class that takes any stl container (or pointer / reference to one) besides a vector?

  15. #15
    Join Date
    Feb 2002
    Posts
    4,640

    Re: A Newbie's Problems w/ DLLs

    Yep, that's right. You'll need to embed the STL container inside the DLL (inside the class in the DLL), and then export your own functions that work on the container. Which is annoying, to say the least.

    Or, you could download a different implementation of the STL. STLPort is one. I think SGI makes one too, but I haven't heard much about it.

    Viggy

Posting Permissions

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





Click Here to Expand Forum to Full Width

Featured