【发布时间】:2021-07-20 15:58:11
【问题描述】:
我对 DLL 的编写/使用非常陌生,并且在 DLL 中编写了一个函数,该函数接受一个字符串,并将另一个字符串作为输出返回给可执行文件。
#define DECL_EXPORT extern "C" __declspec(dllexport)
DECL_EXPORT char * organizeArgs(const char * args) {
uint32 outputLen;
...
char * result = new char[outputLen];
...
return result;
}
对我来说最简单的方法是在 DLL 中分配内存并将其返回给可执行文件以解除分配,但我读到这通常很糟糕,因为它会中断,当 dll 和 exe 之间的分配代码是不相同。试图避免在 dll 中分配和在可执行文件中解除分配会使这个函数及其使用方式变得更加复杂。
应该如何处理这种类型的分配/解除分配?
我有几个理论,但他们都觉得有点可怕:
- 在单独的 dll 函数调用中计算输出的大小,因此调用者可以为输出分配那么多内存并将其提供给 dll。这似乎是最明智的解决方案,但需要运行两次分析代码:
DECL_EXPORT uint32 organizeArgsSize(const char * args) {
...
return size;
}
DECL_EXPORT char * organizeArgs(const char * args, char * outputBuffer) {
...
return outputBuffer;
}
- 在 dll 上分配并返回一个指针,该指针不希望可执行文件释放,该指针在被 dll 函数的第二次调用覆盖之前是有效的。我认为这对调用者来说具有最佳的人体工程学设计,但由于我是多线程的,因此需要
thread_local存储。我仍在尝试研究在 dll 中使用thread_local是否可以接受并且没有发现任何东西:
DECL_EXPORT const char * organizeArgs(const char * args) {
thread_local std::string buffer;
...
return buffer.c_str();
}
我想这样的事情在 DLL 编写中经常出现,而且我认为它比实际更难。一般是怎么做的?
【问题讨论】:
-
一个函数获取资源,一个函数释放它。
-
MS 提供了一组用于跨(潜在)ABI 边界分配和释放内存的函数,请参阅docs.microsoft.com/en-us/windows/win32/memory/… 您需要告诉分配内存的函数的用户使用什么函数来释放它。
-
@Someprogrammerdude 我已经准备好避免拥有我无法删除的堆 [] 我犯了罪hastebin.com/uzeqivivug.cpp
-
FYI -- 如果这是 DLL 应该被其他语言使用,那么您使用的数据类型应该是 Windows 普遍识别的数据类型,即
LONG、LPCSTR等.
标签: c++ memory-management dll