Thread: Dynamic Link to DLL with LoadLibrary corrupts control loop

  1. #1
    Registered User
    Join Date
    Dec 2008
    Location
    Sweden, Malmö
    Posts
    5

    Dynamic Link to DLL with LoadLibrary corrupts control loop

    Hello, hope someone could please help me with this, it has been driving me nuts for a while now. It is probably something simple but I can not find it
    I just want to be able to call a compiled C DLL from another C program. I made a special test project/DLL in order to find out what I am doing wrong.
    I am using DEVC++ 4.9.9.2

    The test program just loads the DLL and starts looping away, calling the same function(that returns a double) in the DLL a number of times but all of a sudden the loop counter memory space is somehow overwritten and the loop is exited.

    When I run the app, here is the output

    Code:
    Microsoft Windows XP [Version 5.1.2600]
    (C) Copyright 1985-2001 Microsoft Corp.
    
    F:\tmp\test>qtag_test
    Loading DLL...TESTDLL.DLL loaded
    Mapping functions...Functions mapped
    Reading values...
    Loop 1 1.234560e+005
    Loop 2 1.234560e+005
    Loop 3 1.234560e+005
    Loop 4 1.234560e+005
    Loop 5 1.234560e+005
    Loop 6 1.234560e+005
    Loop 7 1.234560e+005
    Loop 8 1.234560e+005
    Loop 1090397184 1.234560e+005
    Values read
    Unloading DLL...DLL unloaded.
    Program terminated normally.
    
    F:\tmp\test>
    Here is the DLL.h
    Code:
    #ifndef _DLL_H_
    #define _DLL_H_
    
    #if BUILDING_DLL
    # define DLLIMPORT __declspec (dllexport)
    #else /* Not BUILDING_DLL */
    # define DLLIMPORT __declspec (dllimport)
    #endif /* Not BUILDING_DLL */
    #include "windows.h"
    #include <string.h>
    
    DLLIMPORT double WINAPI ReadRealValue (LPSTR lpzTagName);
    #endif /* _DLL_H_ */
    and the DLL.C
    Code:
    #include "TESTDLL.h"
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                           DWORD reason        /* Reason this function is being called. */ ,
                           LPVOID reserved     /* Not used. */ )
    {
        switch (reason)
        {
          case DLL_PROCESS_ATTACH:
            break;
    
          case DLL_PROCESS_DETACH:
            break;
    
          case DLL_THREAD_ATTACH:
            break;
    
          case DLL_THREAD_DETACH:
            break;
        }
    
        /* Returns TRUE on success, FALSE on failure */
        return TRUE;
    }
    
    DLLIMPORT double WINAPI ReadRealValue (LPSTR lpzTagName)
    {
      double dValue=0;        
      dValue = 123456;;
      return dValue;
    }
    And finally the test program
    Code:
    #include <windows.h> 
    #include <stdio.h> 
    
    typedef double (*MYPROC)(LPSTR); 
     
    int main(VOID) 
    { 
        HINSTANCE hinstLib; 
        MYPROC ProcAdd=NULL;
        BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
        int uDummy;
        long lngLoop;
        double dvalue; 
        dvalue=0;
        // Get a handle to the DLL module.
        printf("Loading DLL...");
        hinstLib = LoadLibrary(TEXT("TESTDLL.dll")); 
        printf("TESTDLL.DLL loaded\n"); 
        // If the handle is valid, try to get the function address.
        if (hinstLib != NULL) 
        { 
            printf("Mapping functions..."); 
            ProcAdd = (MYPROC) GetProcAddress(hinstLib, "ReadRealValue");  
            printf("Functions mapped\n");
            // If the function address is valid, call the function.
            if (NULL != ProcAdd) 
            {                       
                fRunTimeLinkSuccess = TRUE;            
                printf("Reading values...\n");
                // loop and read
                lngLoop=0;            
                for (lngLoop=1;lngLoop<200;lngLoop++)
                {
                  dvalue=ProcAdd("APP_REAL_1_B"); 
                  printf("Loop %i %e\n",lngLoop,dvalue);
                  sleep(0);
                }
                printf("Values read\n");
            }
            // Free the DLL module.
            printf("Unloading DLL...");
            fFreeResult = FreeLibrary(hinstLib); 
            printf("DLL unloaded.\n");
        } 
     
        // If unable to call the DLL function, use an alternative.
     
        if (! fRunTimeLinkSuccess)
        { 
            printf("Failure loading dll.\n"); 
        }
        
        printf("Program terminated normally.\n");
        return 0;
    }
    What am I doing wrong here?
    Thankful for help,
    /R

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    That does look a bit weird.

    I'm wondering if there is something to do with calling convention that goes wrong?

    You may find out by looking at the assembly code generated by the compiler.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Dec 2008
    Location
    Sweden, Malmö
    Posts
    5
    Thanks for the reply, however I must admit that I do not know what you mean by this ?
    Quote Originally Posted by matsp View Post
    You may find out by looking at the assembly code generated by the compiler.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Ramses800 View Post
    Thanks for the reply, however I must admit that I do not know what you mean by this ?
    Give the compiler a -S to generate a listing of the assembler code that the compiler generated. Pay particular attention to the stack handling in both of the callee and caller code.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Aug 2008
    Location
    Belgrade, Serbia
    Posts
    163
    Maybe the problem is in dll.c at assigning the value to dValue because of the double semicolon, or because of the TEXT macro used in loading the dll. Also, try out wiping the dllmain function for it may be causing trouble.
    If nothing works (including looking at the assembly code) go complain to Microsoft about the problem.
    Vanity of vanities, saith the Preacher, vanity of vanities; all is vanity.
    What profit hath a man of all his labour which he taketh under the sun?
    All the rivers run into the sea; yet the sea is not full; unto the place from whence the rivers come, thither they return again.
    For in much wisdom is much grief: and he that increaseth knowledge increaseth sorrow.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by hauzer View Post
    Maybe the problem is in dll.c at assigning the value to dValue because of the double semicolon, or because of the TEXT macro used in loading the dll. Also, try out wiping the dllmain function for it may be causing trouble.
    If nothing works (including looking at the assembly code) go complain to Microsoft about the problem.
    I very much doubt that Microsoft are at fault here - and even if they are, since the compiler is not a MS product, it probably will be blamed on the compiler.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> I'm wondering if there is something to do with calling convention that goes wrong?
    Mixing __cdecl and __stdcall will do that

    Either remove WINAPI from the interface, or add it to the MYPROC typedef.

    gg

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Codeplug View Post
    >> I'm wondering if there is something to do with calling convention that goes wrong?
    Mixing __cdecl and __stdcall will do that

    Either remove WINAPI from the interface, or add it to the MYPROC typedef.

    gg
    Indeed - I just "felt" that it was going wrong in that sense, but I didn't actually spot that there was WINAPI in one place (WINAPI translates to __stdcall for more compact code). Since you are using dynamic resolution and function pointers, the compiler can't tell you that the DLL and local reference are the wrong type.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Registered User
    Join Date
    Dec 2008
    Location
    Sweden, Malmö
    Posts
    5
    Quote Originally Posted by Codeplug View Post
    >> I'm wondering if there is something to do with calling convention that goes wrong?
    Mixing __cdecl and __stdcall will do that

    Either remove WINAPI from the interface, or add it to the MYPROC typedef.

    gg
    Absolutely! That is the solution!
    Thank you Codeplug and everyone else for the help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. syntax question
    By cyph1e in forum C Programming
    Replies: 19
    Last Post: 03-31-2006, 12:59 AM
  2. Getting the loop control form the user
    By Extropian in forum C Programming
    Replies: 6
    Last Post: 08-11-2005, 09:50 AM
  3. ad-hoc link causing loop
    By Waldo2k2 in forum Networking/Device Communication
    Replies: 3
    Last Post: 04-11-2005, 10:09 PM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  5. Loop control
    By astro_not in forum C Programming
    Replies: 5
    Last Post: 02-28-2003, 08:43 AM