0

I'm trying to create a very simple dll and load it to another file for learning purpose. I'm using VC++ same version for both the DLL and the C++ file. Here is my source code:

load.cpp:

#include <iostream>
#include <windows.h>

using namespace std;

typedef int(__stdcall* nsum)(int a, int b);

int main(void)
{
    HINSTANCE myDll = LoadLibrary(L".\\DLL1.dll");
    nsum sum = (nsum)GetProcAddress(myDll, "sum");

    if (!myDll) {
        cout << "could not load the dynamic library" << endl;
        return EXIT_FAILURE;
    }


    int xfinal = sum(10, 20);
    cout << xfinal << endl;

    return 0;
}

and dll.cpp

#include <windows.h>
#include "pch.h"

using namespace std;

int __declspec(dllexport) __stdcall sum(int a, int b)
{
    return a + b;
}

pch.h

// pch.cpp: source file corresponding to the pre-compiled header

#include "pch.h"

// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.

But still I'm getting the exception. I searched for answers but found none, so I am writing this for help

In the load.cpp, in HINSTANCE myDll, I can peek and see the value being set to 0x000000000. Is it the reason? If so, How can i fix it?

Mayukh
  • 23
  • 6
  • _Why do I get an Exception Exception thrown at 0x00000000_ 0x00000000 is usually not a valid address to write to. (It's "reserved" for the `nullptr`.) Hence, you may not read from or write to it (or the OS aborts your application with Access Violation). – Scheff's Cat Apr 25 '21 at 06:53
  • @Scheff then what should I do to fix it? – Mayukh Apr 25 '21 at 06:54
  • 1
    Btw. you first use `myDll` and then check it's validity. If `myDll` isn't valid your application dies before the check. You should check in the debugger whether this is the essential issue or whether there are others as well. – Scheff's Cat Apr 25 '21 at 06:54
  • @Scheff can you guide me on how to check that? Is it like debugging? – Mayukh Apr 25 '21 at 06:56
  • Have a specific look at the two code lines after `HINSTANCE myDll = LoadLibrary(L".\\DLL1.dll");` – Scheff's Cat Apr 25 '21 at 06:57
  • FYI: [SO: What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/q/25385173/7478597) – Scheff's Cat Apr 25 '21 at 06:58
  • 1
    @Mayukh _"can you guide me on how to check that?"_ Just move the `if (!myDll) {` before any other usage of `myDll`. – πάντα ῥεῖ Apr 25 '21 at 06:58
  • @πάνταῥεῖ I did that, and the if statement was not executed. But still I'm getting the Exception at `cout << xfinal ,< – Mayukh Apr 25 '21 at 07:03
  • @Mayukh I am pretty sure your problem is actually here: `nsum sum = (nsum)GetProcAddress(myDll, "sum");` – πάντα ῥεῖ Apr 25 '21 at 07:05

1 Answers1

4

Your problem is quite simple. The exported name of your function is not sum because you are not use a C ABI. Instead, it's a mangled name ?sum@@YGHHH@Z which of course is not found by your use of GetProcAddress(myDLL, "sum"); There is no such function sum. As such, you are trying to invoke a function at address 0, i.e. exactly what the exception tells you.

Microsoft calls these Decorated Names rather than "mangled" but they both mean the same thing: the type information for the parameter types, calling-convention, and return value is encoded into special symbols that make up the name.

A few options here to fix this problem:

  • Use the import library instead of explicit linking which will use the mangled name so you can stick with a C++ ABI.

  • Use a C ABI via extern "C" keeping the existing __stdcall calling convention in which case the name will be _sum@8 when building for x86 (32-bit):

extern "C" int __declspec(dllexport) __stdcall sum(int a, int b)
  • Use a C ABI with extern "C" but use __cdecl which will actually result in sum for x86 (32-bit):
extern "C" int __declspec(dllexport) __cdecl sum(int a, int b)

For x64 there is one standard calling convention __fastcall (__cdecl, __stdcall are just aliases for __fastcall). In that, just using extern "C" will result in the name sum for any of those calling conventions. The only case that results in 'mangled' exports using a C ABI for x64 then is extern "C" __vectorcall.

Be sure to update your typedef to match the calling convention you are using if you change it.

Second, you should add more error-checking:

HMODULE myDll = LoadLibrary(L".\\DLL1.dll");
if (!myDll) {
    cout << "could not load the dynamic library" << endl;
    return EXIT_FAILURE;
}

nsum sum = (nsum)GetProcAddress(myDll, "sum");
if (!sum) {
    cout << "could not find the export" << endl;
    return EXIT_FAILURE;
}

If you are using C++11 or later (Visual Studio 2012 or later), then auto sum = reinterpret_cast<nsum>(reinterpret_cast<void*>(GetProcAddress(myDll, "sum"))); is better.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81