Ошибка сегмента в модульных тестах, когда исходные файлы библиотеки компилируются отдельно - PullRequest
1 голос
/ 03 мая 2020

Я пишу небольшую библиотеку и до сих пор добавлял исходный файл библиотеки напрямую с модульным тестом в команду add_executable, аналогично приведенному ниже:

CMakeLists.txt (Результирующий исполняемый файл ОК)

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, к сожалению, не делает меня мудрее.

Мой вопрос: является ли ошибка сегмента результатом неправильной связи с моей собственной библиотекой или GTSAM? Если так, как я могу это исправить? Если нет, то должен ли я считать, что в моей библиотеке есть ошибка, которая проявляется только во втором случае?

РЕДАКТИРОВАТЬ:

Минимальный рабочий пример для воспроизведения:

include /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;
}

test / unit_test. cpp

#include <my_lib.hpp>
#include <gtsam/base/numericalDerivative.h>

int main()
{
  f();
  return 0;
}

1 Ответ

1 голос
/ 04 мая 2020

Ваша библиотека использует библиотеку Eigen3, которая также является частью библиотеки gtsam, используемой в тестах. Вам необходимо убедиться, что в обоих случаях используется одна и та же библиотека 1002 * Eigen3, в противном случае возможны незначительные ошибки (например, наблюдаемые вами).


Технически, ваша библиотека и gtsam на основе теста отдельные файлы объектов , поэтому они компилируются независимо, и оба они правильны .

Это компоновщик , который может выполнять нежелательные оптимизации, такие как объединение функций из этих объектных файлов. Например, если эти функции имеют одинаковое имя. Если вы найдете способ запретить такого рода оптимизации для компоновщика, тогда приведенный тест может работать правильно даже в случае несовместимых библиотек Eigen3, используемых для вашей библиотеки в gtsam.

Тем не менее, отключение оптимизации компоновщика является очень тонким способом с точки зрения стабильности вашего проекта. Используйте этот способ только в качестве крайней меры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...