导出 c++ dll class 意外行为
Exporting a c++ dll class unexpected behavoir
我是 c++ 语言的新手,具有广泛的 c# 背景。
我在 visual studio 2022 中设置了一个解决方案,包括一个控制台可执行项目和一个 dll 项目,可执行文件取决于 dll 项目。
dll 依赖于其他一些静态库来最终提供类似 httpclient 的功能。
这些项目是我进一步了解 c++ 的游乐场。
我决定在 exe 和 dll 之间使用类似 c# 的功能,所以我从 dll class MyHttpClient
.
导出了一个 class
我的第一个尝试是将 class 作为一个整体导出,但这导致 exe 依赖于 dll 所依赖的某些库,因为 class 具有成员字段,其类型来自这些库,即使构建成功,exe 也会崩溃..
所以我决定在一个单独的干净头文件中创建一个接口 class,其中只有一个 public 构造函数和关键 public 函数;此 class 与完整的 class 具有相同的名称和相同的名称 space,我使用预定义的宏将此摘要 class 修饰为 __declspec(dllexport)
__decspec(dllexport/import)
class 基于它所在的项目,并将此头文件导入到我的 exe 主文件中。
p.s。请注意完整的 class 也用 __declspec(dllexport)
.
修饰
//inteface.h
#include "def.h"
//This is the abstract(interface) class
class EXPORT_API MyHttpClient
{
public:
MyHttpClient();
std::string Get();
};
main.cpp 在 exe 中包含 interface.h 文件。
//MyHttpClient.h
//Multiple #include "def.h" ...
class EXPORT_API MyHttpClient
{
public:
MyHttpClient();
std::string Get();
private:
// some member fields
};
//MyHttpClient.cpp
provides implementation for the MyHttpClient class
现在是这样:
#include "inteface.h"
int main()
{
// if I declare the class's object on the stack everything works as intended.
MyHttpClient client;
auto result = client.Get();
//if I set it on the heap the program crashes with Access violation
// on the private members as if they were not there!!
HttpClient* cli = new HttpClient;
auto result = cli->Get(); // crash
...
}
Q1:为什么我会看到这样的行为?
我怀疑 new 运算符调用了抽象 class 的大小并且
因此所有字段都没有分配内存,而堆栈调用
构造器(初始化这些成员的地方)并扩展为这些
成员已初始化(这是我的猜测,但我真的不知道!)。
Q2:如何解决这个问题?
谢谢。
So I decided to make an interface class with only a public constructor and key public functions in a seperate clean headerfile; this class has the same name and inside the same name space as the full class
这违反了 one-definition-rule 并导致您的程序具有未定义的行为。同一个class在不同翻译单元中的定义必须由相同的token序列组成(加上一些额外的要求)
如果你想要一个抽象 class 作为接口,使用继承和(纯)虚函数。
我是 c++ 语言的新手,具有广泛的 c# 背景。 我在 visual studio 2022 中设置了一个解决方案,包括一个控制台可执行项目和一个 dll 项目,可执行文件取决于 dll 项目。
dll 依赖于其他一些静态库来最终提供类似 httpclient 的功能。
这些项目是我进一步了解 c++ 的游乐场。
我决定在 exe 和 dll 之间使用类似 c# 的功能,所以我从 dll class MyHttpClient
.
我的第一个尝试是将 class 作为一个整体导出,但这导致 exe 依赖于 dll 所依赖的某些库,因为 class 具有成员字段,其类型来自这些库,即使构建成功,exe 也会崩溃..
所以我决定在一个单独的干净头文件中创建一个接口 class,其中只有一个 public 构造函数和关键 public 函数;此 class 与完整的 class 具有相同的名称和相同的名称 space,我使用预定义的宏将此摘要 class 修饰为 __declspec(dllexport)
__decspec(dllexport/import)
class 基于它所在的项目,并将此头文件导入到我的 exe 主文件中。
p.s。请注意完整的 class 也用 __declspec(dllexport)
.
//inteface.h
#include "def.h"
//This is the abstract(interface) class
class EXPORT_API MyHttpClient
{
public:
MyHttpClient();
std::string Get();
};
main.cpp 在 exe 中包含 interface.h 文件。
//MyHttpClient.h
//Multiple #include "def.h" ...
class EXPORT_API MyHttpClient
{
public:
MyHttpClient();
std::string Get();
private:
// some member fields
};
//MyHttpClient.cpp
provides implementation for the MyHttpClient class
现在是这样:
#include "inteface.h"
int main()
{
// if I declare the class's object on the stack everything works as intended.
MyHttpClient client;
auto result = client.Get();
//if I set it on the heap the program crashes with Access violation
// on the private members as if they were not there!!
HttpClient* cli = new HttpClient;
auto result = cli->Get(); // crash
...
}
Q1:为什么我会看到这样的行为? 我怀疑 new 运算符调用了抽象 class 的大小并且 因此所有字段都没有分配内存,而堆栈调用 构造器(初始化这些成员的地方)并扩展为这些 成员已初始化(这是我的猜测,但我真的不知道!)。
Q2:如何解决这个问题?
谢谢。
So I decided to make an interface class with only a public constructor and key public functions in a seperate clean headerfile; this class has the same name and inside the same name space as the full class
这违反了 one-definition-rule 并导致您的程序具有未定义的行为。同一个class在不同翻译单元中的定义必须由相同的token序列组成(加上一些额外的要求)
如果你想要一个抽象 class 作为接口,使用继承和(纯)虚函数。