【发布时间】:2020-05-03 15:31:51
【问题描述】:
我正在编写一个小型库,到目前为止,我已经在add_executable 命令中直接使用单元测试添加了库源文件,如下所示:
CMakeLists.txt(生成可执行文件OK)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_STANDARD 17)
find_package(Eigen3 REQUIRED)
find_package(GTSAM 4.0.2 REQUIRED)
add_executable(my_test test/unit_test.cpp src/my_lib.cpp)
target_include_directories(my_test PUBLIC include ${EIGEN3_INCLUDE_DIR} ${GTSAM_INCLUDE_DIR})
target_link_libraries(my_test PUBLIC gtsam)
在我创建了一个实际的库并链接了单元测试之前,一切正常,类似于下面:
CMakeLists.txt(生成的可执行文件不正常)
cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_STANDARD 17)
find_package(Eigen3 REQUIRED)
add_library(my_lib STATIC src/my_lib.cpp)
target_include_directories(my_lib PRIVATE include ${EIGEN3_INCLUDE_DIR})
find_package(GTSAM 4.0.2 REQUIRED)
add_executable(my_test test/unit_test.cpp)
target_include_directories(my_test PUBLIC include ${EIGEN3_INCLUDE_DIR} ${GTSAM_INCLUDE_DIR})
target_link_libraries(my_test PUBLIC gtsam my_lib)
但是,现在测试段出现故障。valgrind 报告以下内容:
==18501== Memcheck, a memory error detector
==18501== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==18501== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==18501== Command: ./my_test
==18501==
==18501== Invalid read of size 8
==18501== at 0x509CFBB: gtsam::noiseModel::Diagonal::Sigmas(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, bool) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4F3C713: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501== Address 0x7241df8 is 8 bytes before a block of size 8 alloc'd
==18501== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18501== by 0x4ED9FD: Eigen::internal::aligned_malloc(unsigned long) (Memory.h:159)
==18501== by 0x507875B: Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::resize(long, long) [clone .constprop.1340] (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x5085698: Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::PlainObjectBase<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > >(Eigen::DenseBase<Eigen::CwiseNullaryOp<Eigen::internal::scalar_constant_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> > > const&) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x509CFA2: gtsam::noiseModel::Diagonal::Sigmas(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, bool) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4F3C713: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501==
==18501== Invalid read of size 8
==18501== at 0x4F3C71D: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501== Address 0x7241da8 is 8 bytes before a block of size 8 alloc'd
==18501== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18501== by 0x4ED9FD: Eigen::internal::aligned_malloc(unsigned long) (Memory.h:159)
==18501== by 0x51492E1: Eigen::Matrix<double, -1, 1, 0, -1, 1>::Matrix<int>(int const&) [clone .constprop.1305] (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4F3C6F4: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501==
==18501== Invalid read of size 8
==18501== at 0x509CDD1: gtsam::noiseModel::Diagonal::Variances(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, bool) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4F3C77A: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501== Address 0x72420f8 is 8 bytes before a block of size 24 alloc'd
==18501== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18501== by 0x4ED9FD: Eigen::internal::aligned_malloc(unsigned long) (Memory.h:159)
==18501== by 0x509A53B: Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::resize(long, long) [clone .constprop.1216] (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x50A4A0A: Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::PlainObjectBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_sqrt_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> >(Eigen::DenseBase<Eigen::CwiseUnaryOp<Eigen::internal::scalar_sqrt_op<double>, Eigen::Matrix<double, -1, 1, 0, -1, 1> const> > const&) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x509CD63: gtsam::noiseModel::Diagonal::Variances(Eigen::Matrix<double, -1, 1, 0, -1, 1> const&, bool) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4F3C77A: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501== Invalid read of size 8
==18501== at 0x4F3C784: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501== Address 0x7242098 is 8 bytes before a block of size 24 alloc'd
==18501== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18501== by 0x4ED9FD: Eigen::internal::aligned_malloc(unsigned long) (Memory.h:159)
==18501== by 0x513A304: Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::DenseBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> > const&) (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4F3C766: _GLOBAL__sub_I_lago.cpp (in /usr/local/lib/libgtsam.so.4.0.2)
==18501== by 0x4010732: call_init (dl-init.c:72)
==18501== by 0x4010732: _dl_init (dl-init.c:119)
==18501== by 0x40010C9: ??? (in /lib/x86_64-linux-gnu/ld-2.27.so)
==18501==
test_orient: /usr/local/include/eigen3/Eigen/src/Core/DenseStorage.h:128: Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 32>::plain_array() [with T = double; int Size = 4; int MatrixOrArrayOptions = 0]: Assertion `(internal::UIntPtr(eigen_unaligned_array_assert_workaround_gcc47(array)) & (31)) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.
==18501==
==18501== Process terminating with default action of signal 6 (SIGABRT)
==18501== at 0x5F95E97: raise (raise.c:51)
==18501== by 0x5F97800: abort (abort.c:79)
==18501== by 0x5F87399: __assert_fail_base (assert.c:92)
==18501== by 0x5F87411: __assert_fail (assert.c:101)
==18501== by 0x4D98AE: Eigen::internal::plain_array<double, 4, 0, 32>::plain_array() (DenseStorage.h:128)
==18501== by 0x4D78AD: Eigen::DenseStorage<double, 4, 4, 1, 0>::DenseStorage() (DenseStorage.h:187)
==18501== by 0x4D61C7: Eigen::PlainObjectBase<Eigen::Matrix<double, 4, 1, 0, 4, 1> >::PlainObjectBase() (PlainObjectBase.h:484)
==18501== by 0x4D4DBB: Eigen::Matrix<double, 4, 1, 0, 4, 1>::Matrix() (Matrix.h:259)
==18501== by 0x4ECF6A: orient::quaternionFromAngleAxis(Eigen::Matrix<double, 3, 1, 0, 3, 1> const&) (from_angle_axis.cpp:56)
==18501== by 0x4D21C4: ____C_A_T_C_H____T_E_S_T____10() (from_angle_axis_test.cpp:95)
==18501== by 0x3F5A43: Catch::TestInvokerAsFunction::invoke() const (catch2.hpp:14054)
==18501== by 0x3F50A2: Catch::TestCase::invoke() const (catch2.hpp:13947)
==18501==
==18501== HEAP SUMMARY:
==18501== in use at exit: 42,110 bytes in 347 blocks
==18501== total heap usage: 4,871 allocs, 4,524 frees, 507,954 bytes allocated
==18501==
==18501== LEAK SUMMARY:
==18501== definitely lost: 64 bytes in 4 blocks
==18501== indirectly lost: 0 bytes in 0 blocks
==18501== possibly lost: 0 bytes in 0 blocks
==18501== still reachable: 42,046 bytes in 343 blocks
==18501== suppressed: 0 bytes in 0 blocks
==18501== Rerun with --leak-check=full to see details of leaked memory
==18501==
==18501== For counts of detected and suppressed errors, rerun with: -v
==18501== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)
不幸的是,Eigen 断言中的 link 让我变得更聪明。
我的问题是:seg 错误是由于不正确地链接到我自己的库或 GTSAM 造成的吗?如果是这样,我该如何解决?如果不是,我是否应该假设我的库中存在仅在第二种情况下才表现出来的错误?
编辑:
重现的最小工作示例:
包括/my_lib.hpp
#pragma once
void f();
src/my_lib.cpp
#include <my_lib.hpp>
#include <unsupported/Eigen/KroneckerProduct>
void f()
{
Eigen::Matrix3d A = Eigen::Matrix3d::Random();
Eigen::Matrix<double, 9, 3> B = Eigen::Matrix<double, 9, 3>::Random();
Eigen::Matrix3d I = Eigen::Matrix3d::Identity();
Eigen::Matrix<double, 9, 3> tmp = Eigen::kroneckerProduct(I, A) * B;
}
测试/unit_test.cpp
#include <my_lib.hpp>
#include <gtsam/base/numericalDerivative.h>
int main()
{
f();
return 0;
}
【问题讨论】:
-
很可能是您的库中的错误。由于您不提供其代码,我们只能猜测。您是否使用 valgrind 检查过测试的第一个变体(包含两个源文件)?
-
valgrind 报告第一个变体没有错误。这是否意味着我们可以排除库错误?
-
“这是否意味着我们可以排除库错误?” - 不,这只是意味着您的库可能有错误,但 valgrind 无法检测到此错误。那么,你想从我们这里得到什么?如果您希望我们帮助您修复错误,您需要提供代码 (minimal reproducible example)。仅当链接两个源文件时您的测试才会失败这一事实可能有助于调试,但 仍然需要代码。
-
对,我已经用一个最小的例子更新了帖子
-
经过进一步检查,我发现 gtsam 包含 Eigen 作为 interface 的一部分。这不是“内部”(仅实现)用法。因此,每当您找到
gtsam包时,也会检测到 Eigen 标头。因此,当您使用find_package(Eigen3)时,您只需要确保它找到与 gtsam 使用的相同的特征。