Thread: Access violation reading location (Dll and Lib)

  1. #1
    Registered User
    Join Date
    May 2009
    Posts
    64

    Access violation reading location (Dll and Lib)

    Can anyone here explain me what did I do wrong?

    I'm creating a plugin for my engine right now. Here's how it works. I have a dll that will loaded by the main library. So while loading the dll, the dll calls the function addToList in the main library via singleton.

    Code:
    void Core::addToList( Device* newDevice )
    {
    	mDeviceList.push_back( newDevice );
    }
    To add the device to the library's list of device.

    Now when I try to load it via this function

    Code:
    void Core::Go()
    {
    	std::vector<Device*>::iterator it;
    	for( it=mDeviceList.begin(); it<mDeviceList.end(); it++ )
    	{
    		(*it)->_initialise();
    	}
    }
    This pops up. Unhandled exception at 0x6098a116 (Engine.dll) in Game.exe: 0xC0000005: Access violation reading location 0x60fb967c.

    I tried to call _initialize on the addToList function by using this function, and it works fine.

    Code:
    void Core::addToList( Device* newDevice )
    {
    	newDevice->_initialise();
    }
    I don't know what did I do wrong. This is the first time I create some dll and library. I hope you understand what I'm trying to say.

    Thank you
    Sarah22

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Maybe the problem lies in the way you are calling those functions, and the code in between. You might want to post the smallest and simplest compilable program that demonstrates the problem.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    This may not be the issue anymore but back in the day I remember MS DLLs having issues interacting with STL objects, something to do with copy on write; I doubt that is what is happening here. Or is this the dreaded ptr to ptr issue?

    Take this with a heavy caveat of I am pre-caffeinated ATM. <yawn>
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    This code is suspect.

    1. You are passing in pointers to objects you did not create in the DLL. Who is cleaning these up? I hope you understand that the vector in the DLL cannot clean these up or you will corrupt the heap.
    2. You are using the STL in DLLs. This can be problematic if you are not careful. You cannot expose any portion of the STL at the DLL interface...or what I would call the module boundary. If you do you will get the exact error your post is about.
    3. In addToList you are not checking to make sure that the Device pointer is valid prior to using it. What if the pointer is null? Your code will crash.
    4. Your function is called addToList() however I do not see anywhere in the function where the pointer is added to any list or vector.

  5. #5
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Quote Originally Posted by Bubba View Post
    This code is suspect.

    1. You are passing in pointers to objects you did not create in the DLL. Who is cleaning these up? I hope you understand that the vector in the DLL cannot clean these up or you will corrupt the heap.
    2. You are using the STL in DLLs. This can be problematic if you are not careful. You cannot expose any portion of the STL at the DLL interface...or what I would call the module boundary. If you do you will get the exact error your post is about.
    3. In addToList you are not checking to make sure that the Device pointer is valid prior to using it. What if the pointer is null? Your code will crash.
    4. Your function is called addToList() however I do not see anywhere in the function where the pointer is added to any list or vector.
    I am SO glad to leave these limitations behind. This is why I will only do Windows coding anymore if it means feeding my family or starving.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  6. #6
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    It's because Microsoft treats DLLs as what amount to separate processes. An EXE and a DLL only differ from one another by the first character in the file - one byte is all that separates a DLL and an EXE. The program rundll.exe is what loads and runs these DLLs but they are not that much different than exes other than they are loaded dynamically. Because of this they also have a separate CRT which causes all sorts of trouble b/c of the way DLLs were designed to be used.

  7. #7
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    I know this is just opinion but I like working with shared objects way way more. They work in a fashion I would expect all DLL/shared objects should work...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  8. #8
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Actually my boss told me the same thing. Unfortunately I develop primarily for Windows-based systems. Once you get used to the limitations you can still do a lot with DLLs. Nothing beats being able to change impl underneath a common interface all the while never having to compile the code using the DLL.

  9. #9
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Um you can pretty much do that with any shared library. Thats how the system I am working on can do hot-upgrades: I push a new version of the .so (DLL) to the box along with a message saying (your upgrade for function X is *here*), it shuts down the old one, moves it to a backup folder (in case of rollbacks), copies the new one into place, a dlopen() later and I am in business.
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    64
    I took a break coding though. haha :P

    I found the problem few minutes ago.

    First, I have a warning message "class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class"

    So, I found this piece of code somewhere on some forum that made the warning disappear.

    template class DllExport std::allocator<Device*>;
    template class DllExport std::vector<Device*, std::allocator<Device*> >;
    Can someone explain me what this code does. Does this one solves the STL problem with DLL?

    Second, I read that I need to have both my project be compiled as Dynamic Library (.dll), so they can share memory? Honestly, I don't understand what the guy said, really. Both are set in DLL but when I try to set the main to .lib, nothing was stored on my vector.

    Third, I'm calling FreeLibrary(hinstLib); on my loadDLL function resulting my vector of objects pointing to nothing. This one solves my problem with the access violation.

    Anyway, everything is working on what I expected for now.

    Thank you for the help everyone.
    Sarah

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    First, I have a warning message "class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class"
    This is the exact warning I'm talking about. You cannot safely export instances of templates or templates themselves across module boundaries. This only works if you are using the same compiler for both the DLL and the client of the DLL.
    Last edited by VirtualAce; 05-25-2010 at 10:00 PM.

  12. #12
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You really should either tell the entire story or none of it.

    Soma

  13. #13
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Quote Originally Posted by Bubba View Post
    It's because Microsoft treats DLLs as what amount to separate processes. An EXE and a DLL only differ from one another by the first character in the file - one byte is all that separates a DLL and an EXE. The program rundll.exe is what loads and runs these DLLs but they are not that much different than exes other than they are loaded dynamically. Because of this they also have a separate CRT which causes all sorts of trouble b/c of the way DLLs were designed to be used.
    Actually, the first byte is identical. A little further down into the file is where it's marked, and the difference between them is just one single bit. Also, they usually use the same CRT (provided that the specific file requested is the same*); Windows loads a single copy into the shared address space (in fact, when relocation isn't necessary, that same copy is used by other processes, as well). The real problem lies in ABI incompatibilities, eg: the DLL was compiled with SGI's STL and the calling program was compiled with RogueWave's implementation, for example; the binary formats of the respective implementations may well be completely incompatible, and in that case, returning, say, an stl::list from your DLL obviously wouldn't work properly.

    *Since Windows often maintains a database of DLL's having the same functionality in numerous locations, and because these DLL's may differ in version or even vendor source, there is always the danger that more than one CRT could be loaded, and if used in conjunction (such as calling srand() from your application because you know the DLL you're using calls rand(), and assuming that everything will work together) could potentially create some nasty (and often mysterious) problems. But this sort of thing is actually quite rare, I think - in most cases, the two CRT's wouldn't even interact.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  14. #14
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    *Since Windows often maintains a database of DLL's having the same functionality in numerous locations, and because these DLL's may differ in version or even vendor source, there is always the danger that more than one CRT could be loaded, and if used in conjunction (such as calling srand() from your application because you know the DLL you're using calls rand(), and assuming that everything will work together) could potentially create some nasty (and often mysterious) problems. But this sort of thing is actually quite rare, I think - in most cases, the two CRT's wouldn't even interact.
    I've ran into this several times. Singletons are a great way to illustrate what happens or what can happen. Templates are an absolute nightmare. Best practices are to never expose templates and never ever pass uncontrolled pointers across the boundary unless there is a strict agreement who owns those pointers and/or the pointer is wrapped in an object that is designed to handle the issue correctly.

    After many many strange crashes I've begun to adhere to these two rules and have had much success. I find that anything else, contrary to the MS docs, is just asking for trouble later down the line.
    Also I believe the docs say they normally use the same version of the CRT not necessarily the same CRT. Allocate an object in a DLL and clean it up outside of the DLL and you will corrupt the heap of the object that cleans it up. Allocate memory inside the application and pass the pointer to a DLL and then clean it up in the DLL and you will corrupt the heap of the DLL.

    Granted if you have a static build environment then they will use the same CRT but when creating DLLs you cannot assume the application using the DLL is using the same version of the CRT as the DLL itself. Once you separate the two then your DLL is guaranteed to work with older code. If you do not separate the two and rely on 'the same version of the CRT' rule you will be in for a rude awakening later when you distribute the DLL and get a call sometime after that your app has crashed on the customer's system. If your app is using 2005 and your DLL is using 2008 you will have issues and vice versa. However if you can guarantee your app is using 2005 and your DLL will always be using 2005 then STL, templates, etc. will work as expected. But as I said when creating DLLs which are supposed to be modular and independent from the app this is a big assumption to make and you lose most of the power and flexibility DLLs offer. It is for this reason I think of the app as one CRT and the DLL as another 'EXE' with its own CRT. It keeps me out of trouble later.
    Last edited by VirtualAce; 05-26-2010 at 08:23 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Linking to DLL without LIB and call it's function of stdcall
    By leiming in forum Windows Programming
    Replies: 2
    Last Post: 04-14-2010, 11:07 PM
  2. difference in the content of Dll and Lib
    By Alexpo in forum C++ Programming
    Replies: 1
    Last Post: 07-07-2008, 01:57 AM
  3. DLL compiling question
    By Noose in forum Windows Programming
    Replies: 2
    Last Post: 12-16-2004, 07:16 AM
  4. Making a LIB file from a DEF file for a DLL
    By JMPACS in forum C++ Programming
    Replies: 0
    Last Post: 08-02-2003, 08:19 PM
  5. Passing parameters from VB to C++ through ActiveX DLL
    By torbjorn in forum Windows Programming
    Replies: 0
    Last Post: 12-10-2002, 03:13 AM