2012-11-16 8 views
8

Mam problem z moim kodem, który ma kilka bardzo dziwnych objawów.Ten sam kod programu z tym samym kompilatorem prowadzi do różnych plików binarnych

  1. kod jest kompilowany na moim komputerze z następujących wersjach:

    się. Wersja GCC: 4.4.2

    b. CMAKE verson: 2.8.7

    c. QNX (system operacyjny) wersja: 6.5.0

I kod ma segfault jednocześnie zwalniając trochę pamięci i wyjście z funkcji (nie umierają na każdym kodzie, tylko na wyjście z funkcji).

Dziwne rzeczy na ten temat to:

  1. Kod robi to w trybie zwolnienia, ale nie w trybie debug:

    się. Kod jest gwintowany, więc oznacza to stan wyścigu.

    b. Nie mogę debugować, umieszczając go w trybie debugowania.

  2. Kod, który jest kompilowany na maszynie z tymi samymi wersjami, nie ma tego problemu.

    a. Dziwne jest to, że kod działa, ale także, że plik binarny utworzony z kompilacji na swoim komputerze, który jest taki sam, jest o około 6mB większy.

Teraz irytująco nie mogę opublikować kodu, ponieważ jest on zbyt duży, a także do pracy. Ale czy ktoś może wskazać mi drogę do naprawienia tego.

Ponieważ używam QNX jestem ograniczony do moich narzędzi do debugowania, nie mogę używać Valgrind i ponieważ nie jest on obsługiwany w QNX, GDB tak naprawdę nie pomaga.

Szukam każdego, kto miał podobny/ten sam problem i co było przyczyną i jak to naprawili.

EDIT:

Sooo ... dowiedziałem się, co to było, ale im jeszcze trochę mylić o tym, jak to się stało.

Kod winowajcą był następujący:

Eigen::VectorXd msBb = data.modelSearcher->getMinimumBoundingBox(); 

gdzie definicja getMinimumBoundingBox to:

Eigen::VectorXd ModelSearcher::getMinimumBoundingBox(); 

i zwraca VectorXd który jest zawsze zainicjowany jako VectorXd output(6, 1). Więc od razu pomyślałem, prawo to musi być ponieważ VectorXd nie jest zainicjowany, ale zmieniając go w ten sposób:

Eigen::VectorXd msBb(6, 1); msBb = data.modelSearcher->getMinimumBoundingBox(); 

Ale to nie działa.W rzeczywistości miałem to naprawić zmieniając definicję funkcji do tego:

void ModelSearcher::getMinimumBoundingBox(Eigen::MatrixXd& input); 

i wezwanie do tego

Eigen::VectorXd msBb(6, 1); data.modelSearcher->getMinimumBoundingBox(msBb); 

Więc teraz nowe pytanie:

Co się piekło? Dlaczego pierwsza zmiana nie zadziałała, ale druga, dlaczego muszę przejść przez referencję? Aha, i wielkie pytanie, jak do cholery to nie pękło, kiedy mój współpracownik go skompilował i uruchomiłem? Jest to prosty błąd pamięci, na pewno nie powinien zależeć od tego, który komputer go skompiluje, zwłaszcza, że ​​kompilator i wszystkie inne ważne rzeczy są takie same !!?

Dzięki za pomoc dla facetów.

+2

Brzmi jak problem z pamięcią - valgrind w trybie debugowania jest nadal wart wypróbowania - to pomoże zdecydować, czy to pamięć, czy nie. – John3136

+2

"1. Kod wykonuje to w trybie zwolnienia, ale nie w trybie debugowania:" - jest to niezbyt częsty objaw problemu z pamięcią (ze względu na różnice w śladzie) –

+0

@ John3136 Niestety nie mogę używać valgrind, ponieważ korzystam z QNX, który ma bez wsparcia. Mogę spróbować zabrać tę funkcję do Linuksa (ubuntu lub Fedora), ale to zajmie całe wieki, więc najpierw chcę wypróbować inne rzeczy. –

Odpowiedz

7

... binarny stworzony z kompilacji na swojej maszynie, która jest taka sama, to około 6MB większy

Warto dowiedzieć się, jaka jest różnica (nawet jeśli jest to tylko przypadek, że jego budowę skóry, podczas gdy twoje eksponuje, prawdziwy błąd):

  • dwukrotnie sprawdzić jesteś kompilacji dokładnie ten sam kod (bez un-popełnione lokalnych zmian, żadnych dodatkowych nagłówków w obejmować wyszukiwania ścieżki, itp)
    • potrójne sprawdzenie przez dodanie przełącznika -E do argumentów gcc w cmake, więc wstępnie przetworzy pliki z tą samą ścieżką dołączania co zwykła kompilacja; diff pre-procesor wyjściowy
  • porównać wyjście z nm lub objdump lub cokolwiek trzeba dla dwóch powiązanych ze sobą plików wykonywalnych: jeśli jakiś system lub 3rd strona biblioteki jest inna wersja w jednym pudełku, może pokazać się tutaj
  • porównać wyjście z ldd jeśli jest dynamicznie połączone, upewnij się, że są one zarówno coraz te same wersje bibliotek
    • porównać wersje bibliotek to faktycznie dostaje na starcie też, jeśli to możliwe.Mam nadzieję, że można to zrobić jedną: metę pldd, porównaj .so wpisy w /proc/pid/map, należy uruchomić proces pod strace/dtrace/truss i porównanie aktywności Linker runtime

Jak dla kodu .. . jeśli to nie działa:

Eigen::VectorXd ModelSearcher::getMinimumBoundingBox(); 
// ... 
Eigen::VectorXd msBb(6, 1); msBb = data.modelSearcher->getMinimumBoundingBox(); 

i to robi:

void ModelSearcher::getMinimumBoundingBox(Eigen::MatrixXd& input); 
// ... 
Eigen::VectorXd msBb(6, 1); data.modelSearcher->getMinimumBoundingBox(msBb); 

Prawdopodobnie masz problem z operatorem przypisania. Jeśli robi płytką kopię i jest dynamicznie alokowana pamięć w wektorze, skończysz z dwoma wektorami mającymi ten sam wskaźnik, a one będą oba.

Należy zauważyć, że jeśli operator nie jest w ogóle zdefiniowany, domyślną opcją jest wykonanie tej płytkiej kopii.

+0

+1 do sprawdzania/porównywania danych wyjściowych. – Macke

+0

Świetna odpowiedź, Druga część wyjaśnia problem z błędem pamięci. Zajrzę do pierwszej części i zobaczę, co znajdę. –

0

Mówiłeś, że trzeba zmienić:

void ModelSearcher::getMinimumBoundingBox(Eigen::MatrixXd& input); 

Co to było wcześniej?

Gdyby to było:

void ModelSearcher::getMinimumBoundingBox(Eigen::MatrixXd input); 

i konstruktorzy copy/operatory przypisania nie były realizowane właściwie to może być przyczyną problemu.

Proszę sprawdzić, w jaki sposób oba są zaimplementowane. Oto some info, które mogą pomóc.

+0

To mówi w pytaniu, co było wcześniej. To nie jest problem. Dzięki za pomoc. –

+0

To musi być. Nie przestrzegałeś zasady trzech. –

+0

@LightnessRacesinOrbit Nie, nie było, to nie było wcześniejsze wejście. –

Powiązane problemy