Проблема с использованием std :: vector с классом / структурой, содержащим собственные типы, определенные в отдельном файле

РЕДАКТИРОВАТЬ >> Заключение, конфликтующие версии 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.

В любом случае спасибо за помощь. Работа над этим помогла мне понять.

Этот рассказ вряд ли будет полным. Пожалуйста, разместите минимальный воспроизводимый пример. Это означает два отдельных набора файлов сборный (полный, полный, без директив #include или других «мелких» частей), которые воспроизводят проблему.

n. 1.8e9-where's-my-share m. 12.09.2018 13:24

Если test_vector.size() возвращает 12, а не 10, значит, у вас серьезная проблема с памятью, вероятно, запись вне пределов. Запустите вашу программу в valgrind, чтобы найти причину проблемы.

ggael 12.09.2018 13:34

n.m: вы правы, похоже, что включение заголовков gtsam вызывает путаницу с версией Eigen - поэтому я буду продолжать попытки правильно настроить,

sfttokyo 13.09.2018 05:15

ggael: Я запустил valgrind, результаты в оригинале, спасибо за подсказку

sfttokyo 13.09.2018 05:16
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
257
0

Другие вопросы по теме