为什么在从 dll 内部调整矢量大小时会出现堆损坏?
Why do I get a Heap Corruption when resizing a vector from inside a dll?
我正在编写调用 DLL 函数的 XLL(使用 XLW 库)。此 DLL 函数将获取矢量引用,修改矢量并通过参数 return 它。
我有一个 VS10 解决方案,其中包含几个 c++ 项目、一些 DLL 和一个将从 excel 调用 DLL 函数的 XLL。我使用 VS10 编译器编译所有内容,_HAS_ITERATOR_DEBUGGING=0
和 _CRT_SECURE_NO_WARNINGS
并对所有项目使用相同的运行时库 (/MDd)。
我还必须重建 XLW 库以符合我必须在我的项目中使用的 _HAS_ITERATOR_DEBUGGING=0
。
当调用 xll_function 时,我遇到了堆损坏错误并且无法弄清楚原因。
在我尝试在调用 dll 函数之前调整矢量大小之后,错误就消失了。也就是说,我可以调用该函数并通过参数获得正确的向量 return,并且没有堆损坏。
有人可以解释一下吗?
由于我是使用 DLL 的新手,所以我不确定是否会发生这种情况,或者我是否做错了什么。
正如您在下面的代码中看到的,dll 函数将尝试调整 forwards
的大小,这就是我认为产生堆错误的地方。
我试图理解为什么会发生这种情况以及这种调整大小和分配如何适用于 dll。也许我无法调整分配在另一个堆中的向量的大小。
** 下面的代码 - 第一个函数是来自 dll 项目的 class 中的静态方法,第二个函数导出到 XLL。
void dll_function(double quote, const std::vector<double>& drift, const std::vector<double>& divs, std::vector<double>& forwards)
{
size_t size = drift.size();
forwards.resize(size);
for( size_t t = 0; t < size; t++)
{
forwards[t] = (quote - divs[t]) * drift[t];
}
}
MyArray xll_function(double quote, const MyArray& drift, const MyArray& divs)
{
// Resizing the vector before passing to function
std::vector<double> forwards(drift.size());
dll_function(quote, drift, divs, forwards);
return forwards;
}
要跨 DLL 边界传递对 std::vector 或其他 C++ 集合的引用,您需要执行以下操作。
对两个模块使用相同的 C++ 编译器,并且使用相同版本的编译器。
在项目设置中,设置与设置通用/平台工具集相同的值。
在项目设置中,将C/C++/代码生成/运行时库值设置为“Multi-threaded DLL (/MD)”,或Multi-threaded用于调试配置的调试 DLL (/MDd)。如果其中一个项目有一个需要静态 CRT 设置的依赖项,抱歉你运气不好,它不会工作。
双方使用相同的配置:如果您构建了 DLL 的调试版本,请不要 link 使用 EXE 的发布版本。也不要更改 _ITERATOR_DEBUG_LEVEL 或 _SCL_SECURE_NO_WARNINGS 等预处理器定义,或者如果您更改了,请将它们更改为两个项目的相同值。
造成这些复杂情况的原因是 C++ 没有标准化的 ABI。 std::vector 和其他 类 的内存布局会根据很多事情发生变化。运算符 new
和 delete
也在 C++ 标准库中,即你不能在一个模块中使用 C++ 分配内存,在不同的模块中释放内存。
如果您不能满足这些条件,有几种解决方法,这里有一个很好的总结:https://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL
我正在编写调用 DLL 函数的 XLL(使用 XLW 库)。此 DLL 函数将获取矢量引用,修改矢量并通过参数 return 它。
我有一个 VS10 解决方案,其中包含几个 c++ 项目、一些 DLL 和一个将从 excel 调用 DLL 函数的 XLL。我使用 VS10 编译器编译所有内容,_HAS_ITERATOR_DEBUGGING=0
和 _CRT_SECURE_NO_WARNINGS
并对所有项目使用相同的运行时库 (/MDd)。
我还必须重建 XLW 库以符合我必须在我的项目中使用的 _HAS_ITERATOR_DEBUGGING=0
。
当调用 xll_function 时,我遇到了堆损坏错误并且无法弄清楚原因。 在我尝试在调用 dll 函数之前调整矢量大小之后,错误就消失了。也就是说,我可以调用该函数并通过参数获得正确的向量 return,并且没有堆损坏。
有人可以解释一下吗? 由于我是使用 DLL 的新手,所以我不确定是否会发生这种情况,或者我是否做错了什么。
正如您在下面的代码中看到的,dll 函数将尝试调整 forwards
的大小,这就是我认为产生堆错误的地方。
我试图理解为什么会发生这种情况以及这种调整大小和分配如何适用于 dll。也许我无法调整分配在另一个堆中的向量的大小。
** 下面的代码 - 第一个函数是来自 dll 项目的 class 中的静态方法,第二个函数导出到 XLL。
void dll_function(double quote, const std::vector<double>& drift, const std::vector<double>& divs, std::vector<double>& forwards)
{
size_t size = drift.size();
forwards.resize(size);
for( size_t t = 0; t < size; t++)
{
forwards[t] = (quote - divs[t]) * drift[t];
}
}
MyArray xll_function(double quote, const MyArray& drift, const MyArray& divs)
{
// Resizing the vector before passing to function
std::vector<double> forwards(drift.size());
dll_function(quote, drift, divs, forwards);
return forwards;
}
要跨 DLL 边界传递对 std::vector 或其他 C++ 集合的引用,您需要执行以下操作。
对两个模块使用相同的 C++ 编译器,并且使用相同版本的编译器。
在项目设置中,设置与设置通用/平台工具集相同的值。
在项目设置中,将C/C++/代码生成/运行时库值设置为“Multi-threaded DLL (/MD)”,或Multi-threaded用于调试配置的调试 DLL (/MDd)。如果其中一个项目有一个需要静态 CRT 设置的依赖项,抱歉你运气不好,它不会工作。
双方使用相同的配置:如果您构建了 DLL 的调试版本,请不要 link 使用 EXE 的发布版本。也不要更改 _ITERATOR_DEBUG_LEVEL 或 _SCL_SECURE_NO_WARNINGS 等预处理器定义,或者如果您更改了,请将它们更改为两个项目的相同值。
造成这些复杂情况的原因是 C++ 没有标准化的 ABI。 std::vector 和其他 类 的内存布局会根据很多事情发生变化。运算符 new
和 delete
也在 C++ 标准库中,即你不能在一个模块中使用 C++ 分配内存,在不同的模块中释放内存。
如果您不能满足这些条件,有几种解决方法,这里有一个很好的总结:https://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL