Почему экспортированный класс DLL дает мне нарушение доступа к памяти в клиентской программе? [Решено] - PullRequest
0 голосов
/ 02 апреля 2020

Итак, у меня есть этот интерфейсный класс, который я включаю как в dll, так и в клиентский проект

// InterfaceClass.h 

#pragma once

class InterfaceClass
{
public:
    virtual void Update() = 0;
}; 

Это класс dll, который вызывает один из своих собственных методов внутри update

// DLLClassThatDoesSomething.cpp

#include "InterfaceClass.h"
#include <iostream>
#include <string>

class __declspec(dllexport) DLLClass : public InterfaceClass
{
public:
    void Update()
    {
        std::cout << this->GetString();
    }
    std::string& GetString()
    {
        std::string thestring = "bruhmoment";
        return thestring;
    }
};

extern "C"
{
    __declspec(dllexport) InterfaceClass* CreateInstance()
    {
        return new DLLClass();
    }
}

И это проект "Клиент"

// main.cpp

#include "InterfaceClass.h"
#include <Windows.h>

typedef InterfaceClass* (__cdecl *Class) ();

int main()
{
    HINSTANCE dll = LoadLibrary(L"DLLClass.dll");

    Class klass = (Class)GetProcAddress(dll, "CreateInstance");

    InterfaceClass* IKlass = klass();

    IKlass->Update();

    FreeLibrary(dll);

    return 0;
}

В тот момент, когда я вызываю IKlass->Update(), я получаю исключение для нарушения памяти доступа из-за вызова DLLClass своего собственного метода. error

Я ничего не пробовал, так как я почти не знаю, как загрузить DLL во время выполнения, и я использовал этот отличный учебник

Как я могу позволить этому вызвать метод и не получить исключение? Я пытаюсь позволить ppl, который будет создавать моды для моей игры, создавать свои собственные моды со своими пользовательскими классами для боссов, мобов и т. Д. c. в DLL.

РЕДАКТИРОВАТЬ: Оказывается, это была ошибка синтаксиса с моей стороны. Вместо return new DLLClass; это должно было быть return new DLLClass();. После исправления он работает как задумано.

1 Ответ

1 голос
/ 02 апреля 2020

Вы возвращаете ссылку на локальную переменную thestring, и к тому времени, когда вы пытаетесь обратиться к ней в std::cout << this->GetString(), ссылочные данные уже уничтожены. Фактически, он уничтожается сразу после окончания включенной области видимости составного оператора, в котором была объявлена ​​переменная.

Может иногда «работать» из-за того, что стек еще не перезаписан, но в конечном итоге произойдет сбой жалко, как это было в вашем случае. Это вызывает UB (неопределенное поведение).

...