这是一个延续较早的帖子 https://stackoverflow.com/questions/70788173/eigen-static-lib-memory-align.
但这一次希望有一个更好的例子。设置向量时,这个简单的测试会崩溃。
我正在使用 Ubuntu 20.04、gcc 9.3.0、c++17、eigen 3.3.7
main.cpp
#include <iostream>
#include <memory>
#include "C.h"
using namespace std;
class B {
public:
C c;
B() {
cout << (uint64_t)this << endl;
}
~B(){}
};
int main() {
shared_ptr<B> b = make_shared<B>();
b->c.v = VectorXd(5); // << crashes here
// SIGABRT on `Eigen::internal::aligned_free` when trying to do `std::free()`
return 0;
}
C 类作为静态库链接。静态库以Release模式编译(--std=c++17 -DNDEBUG -O3
),而主程序在调试中运行 - 没有优化。
如果静态库和主程序都以调试方式运行,则不会发生崩溃。
另外,如果它们都在 Release 中运行,则不会发生崩溃。仅当在Release中编译静态lib并且在Debug中编译主程序时,才会出现该问题。
C.h
#pragma once
#include <vector>
#include <Eigen/Core>
using namespace std;
using namespace Eigen;
class C {
public:
VectorXd v;
C();
~C();
};
C.cpp
#include "C.h"
C::C() {
v = VectorXd(5);
}
C::~C() {
}
如果您编译的库和主要可执行文件具有不匹配的体系结构标志(-m...海湾合作委员会的标志 https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html),您可以观察崩溃情况。例如,当我编译启用 avx 的库时(-mavx
)并且没有 avx 的主可执行文件,反之亦然,它会崩溃。该崩溃也发生在 Eigen 3.4.0 中。而且,在没有优化的情况下也会发生这种情况(-O0
).
本征aligned_malloc()
and aligned_free()
函数根据值做不同的事情EIGEN_DEFAULT_ALIGN_BYTES
宏,当例如启用或禁用 AVX(以及其他)。 Eigen 根据使用的编译器标志自动选择正确的值。因此,如果仅在静态库中启用 AVX,则C
uses handmade_aligned_malloc()
在内部,它不返回接收到的指针malloc()
直接移动,但稍微移动一下以确保正确对齐。另一方面,为C::v
来自可执行文件(没有 AVX 编译的)将首先尝试通过调用来释放内存b->c.v.~VectorXd()
,然后最终调用free()
代替handmade_aligned_free()
. Thus, free()
接收到一个不指向所分配内存开始的地址,这会导致崩溃。
当然,如果您在可执行文件中启用 AVX 并在库中禁用它,您会得到不匹配的调用malloc()
and handmade_aligned_free()
相反,也会导致崩溃。
解决方案很简单:确保使用相同的体系结构标志编译静态库和可执行文件。如果由于某种原因这是不可能的,请确保创建和销毁始终发生在同一组件中。例如,你可以使C::v
私有并且只允许通过在中实现的函数对其进行修改C.cpp
file.
注意:您的其他帖子 https://stackoverflow.com/q/70788173/3740047有点不同,因为它不涉及动态内存管理,而在当前的帖子中您使用VectorXd
它确实使用动态内存管理。
注2:所描述的问题与使用无关std::shared_ptr
。但对于 3.4.0 之前的 Eigen 版本,您可能需要使用EIGEN_MAKE_ALIGNED_OPERATOR_NEW
以确保指针b
无论架构和 C++17 如何,都正确对齐;至少是原来的特征问题 https://gitlab.com/libeigen/eigen/-/issues/1409仅针对 3.4.0 实施。但我在这一点上可能是错的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)