РЕДАКТИРОВАТЬ >> Заключение, конфликтующие версии Eigen из-за дрянной локальной конфигурации? <<
Я пытаюсь определить структуру, содержащую Eigen :: Matrix. Когда я использую std :: vector и заполняю массив какой-то функцией, происходят странные вещи.
РЕДАКТИРОВАТЬ >> полный исходный код ниже <<
Когда я определяю все в одном файле, как и выше, проблем нет. Вектор заполняется и возвращается правильно, вызов size () для доступа к результирующему вектору в порядке. (размер () = 10).
Когда я определяю типы и функции в отдельных файлах .h и .cpp для основного и делаю то же самое, возвращаемые данные сдвигаются так, что size () возвращает 12.
Глядя на элементы матрицы, я могу заметить, что данные сдвигаются на 1 элемент вправо для каждого объекта в векторе.
Единственный способ заставить его работать, когда он определен в отдельном файле, - это объявить матрицу как
Eigen::Matrix<float, 4, 4, Eigen::DontAlign> tf
но я полагаю, что в дальнейшем это плохо скажется на эффективности. Есть идеи, в чем проблема? Я предполагаю, что это связано с выравниванием матрицы при распределении, но почему это проблема при компиляции / связывании из разных исходных файлов?
Ubuntu 16.04 gcc 5.4.0 C++ стандарт 11 Eigen 3.2.1 (предоставляется пакетом GTSAM slam)
РЕДАКТИРОВАТЬ - >>>>
полный исходный код:
key_frames.h
#ifndef __KEY_FRAMES_H__
#define __KEY_FRAMES_H__
#include <Eigen/Dense>
struct test_t {
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
Eigen::Matrix<float, 4, 4> tf;
int key;
};
void load_test_v(std::vector<test_t,
Eigen::aligned_allocator<test_t> > & test_vector);
#endif
key_frames.cc
#include <vector>
#include "key_frames.h"
void load_test_v(std::vector<test_t,
Eigen::aligned_allocator<test_t> > & test_vector){
for (int i = 0; i < 10; i++) {
test_t tt;
tt.tf = Eigen::Matrix4f::Random();
tt.key = i;
test_vector.push_back(tt);
}
}
opt_key_frames.cc
#include <iostream>
#include <gtsam/geometry/Pose2.h>
#include "key_frames.h"
int main(int argc, const char** argv) {
std::vector<test_t,
Eigen::aligned_allocator<test_t> > test_vector;
test_vector.clear();
std::cout << "size of test vector " << test_vector.size() << "\n";
load_test_v(test_vector);
std::cout << "size of test vector " << test_vector.size() << "\n";
}
Это минимально воспроизводимый источник. Для сборки ссылаюсь на библиотеки gtsam. Интересно, если я уберу
#include <gtsam/geometry/Pose2.h>
код работает (size () возвращает 10). Также, если я скопирую точный код и сделаю файл в другой каталог, он будет работать.
вывод из valgrid:
--14269-- REDIR: 0x5c0abb0 (libc.so.6:bcmp) redirected to 0x4a28770 (_vgnU_ifunc_wrapper)
--14269-- REDIR: 0x5cea430 (libc.so.6:__memcmp_sse4_1) redirected to 0x4c33780 (__memcmp_sse4_1)
size of test vector 0
--14269-- REDIR: 0x5c03600 (libc.so.6:posix_memalign) redirected to 0x4c2fd12 (posix_memalign)
size of test vector 12
==14269==
==14269== HEAP SUMMARY:
==14269== in use at exit: 72,736 bytes in 2 blocks
==14269== total heap usage: 259 allocs, 257 frees, 98,174 bytes allocated
==14269==
==14269== Searching for pointers to 2 not-freed blocks
==14269== Checked 2,634,840 bytes
==14269==
==14269== LEAK SUMMARY:
==14269== definitely lost: 0 bytes in 0 blocks
==14269== indirectly lost: 0 bytes in 0 blocks
==14269== possibly lost: 0 bytes in 0 blocks
==14269== still reachable: 72,736 bytes in 2 blocks
==14269== suppressed: 0 bytes in 0 blocks
==14269== Reachable blocks (those to which a pointer was found) are not shown.
если удалить gtsam, включите:
--14359-- REDIR: 0x54613b0 (libc.so.6:__GI_mempcpy) redirected to 0x4c34a90 (__GI_mempcpy)
size of test vector 0
--14359-- REDIR: 0x5459600 (libc.so.6:posix_memalign) redirected to 0x4c2fd12 (posix_memalign)
--14359-- REDIR: 0x54564f0 (libc.so.6:free) redirected to 0x4c2ec69 (free)
size of test vector 10
==14359==
Так что там что-то меняется.
Вывод: моя установка испорчена. Я подозреваю, что включение Eigen / Dense нацелено на установку Eigen3.3 в масштабе всей системы. Хотя GTSam использует Eigen 3.2, поставляемый с пакетом, и по какой-то причине моя локальная установка сбивает их с толку, тогда как когда я запускаю код в другом каталоге, используется только GTSam Eigen.
В любом случае спасибо за помощь. Работа над этим помогла мне понять.
Если test_vector.size()
возвращает 12, а не 10, значит, у вас серьезная проблема с памятью, вероятно, запись вне пределов. Запустите вашу программу в valgrind
, чтобы найти причину проблемы.
n.m: вы правы, похоже, что включение заголовков gtsam вызывает путаницу с версией Eigen - поэтому я буду продолжать попытки правильно настроить,
ggael: Я запустил valgrind, результаты в оригинале, спасибо за подсказку
Этот рассказ вряд ли будет полным. Пожалуйста, разместите минимальный воспроизводимый пример. Это означает два отдельных набора файлов сборный (полный, полный, без директив
#include
или других «мелких» частей), которые воспроизводят проблему.