Скомпилированная программа на собранном gcc выдает segfault
От: lolovo  
Дата: 06.12.19 09:59
Оценка:
Всем привет!

Имеется штатный древний компилятор gcc4.2.1(freebsd). Была необходима поддержка одной библиотеки, которая вынудила перейти на новую версию gcc, так вот...после долгих танцев с бубном вокруг разных версий gcc , которые не хотели ставиться...с горем пополам собрал gcc-4.9.4 со следующим конфигом:


../gcc-4.9.4/configure --enable-thread=posix --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,lto --with-gmp=/usr/local —
-with-gmp-include=/usr/local/include --with-gmp-lib=/usr/local/lib --with-mpfr=/usr/local --with-mpfr-include=/usr/local/lib/include
--with-mpfr-lib=/usr/local/lib --with-mpc=/usr/local --with-mpc-include=/usr/local/include --with-mpc-lib=/usr/local/lib


перед этим были поставлены все необходимое и даже более, т.к. пробовал разные версии gcc поставить (не все при сборке gcc-4.9.4 используется):


binutils-2.33.1
gmp-6.1.2
mpfr-4.0.2
mpc-1.1.0
isl-0.21
make-4.2
m4-1.4.8
perl-5.30.1
cloog-0.18.0
ppl-1.2


путь PATH был изменен таким образом, чтоб /usr/local/bin был доступен для поиска первым (export PATH=/usr/local/bin:...), т.к. все что собирал из списка выше, все устанавливалось в /usr/local.

После успешной сборки gcc-4.9.4 попробовал протестировать простую программу (make check не делал, т.к. надо собирать для этого другие утилиты и машина не самая быстрая, в общем пропустил шаг):
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <map>
#include <iostream>

int main()
{
        int i=123;
        std::cout<<i<<std::endl; //<--- SegFault 
//      std::map<std::string,int> _A;
//      _A["SSSddd"]=111;
//      printf("%s %d\n",_A.begin()->first.c_str(),_A.begin()->second);        // [1]-->ok
//      std::cout<<_A.begin()->first<<" "<<_A.begin()->second<<std::endl;     // [2]-->SegFault
        return 0;
}


Перед компиляцией настроил LD_LIBRARY_PATH (к слову, его такой переменной окружения изначально не было): export LD_LIBRARY_PATH=/usr/local/bin:$LD_LIBRARY_PATH

Сама компиляция: g++ -g -o k k.cpp

Так вот, выяснилось, что если скомпилировать программу собранным gcc-4.9.4, то она выдает SegFault при std::cout! Старая версия gcc-4.2.1 компилирует нормально.
Причем printf новый gcc-4.9.4 переваривает нормально и в принципе работа с std::map и std::string не приводит к SegFault'у.

Что делаю не так? Чутье подсказывает мне, что проблема либо в изначальной сборке (что скорее всего и не понятно из-за чего, что и где могло пойти не так...ед. момент перед этим успешно собрал 4.5.0, но не проверял с std::cout его и перенес его в /usr/local, потом уже используя его собрал 4.7.0, далее аналогично перенес его в /usr/local и потом аналогично 4.9.0 и 4.9.4... может проблема в этом, что изначально на кривом g++ собирались последующие сборки), либо в том, что что-то при компиляции/линковке самой программы берется из разных мест (хочется больше верить в это, чем в ошибку при сборке самого gcc и понять что я упустил и делаю не то) и как результат валится в кору, причем dbg (правда, он старый, gdb-6.1.1 и с новым DWARF не совместим) говорит следующее:

Error while reading shared library symbols:
Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /usr/local/lib/libstdc++.so.6]
(no debugging symbols found)...Error while reading shared library symbols:
Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /usr/local/lib/libgcc_s.so.1]
(no debugging symbols found)...(no debugging symbols found)...
Program received signal SIGSEGV, Segmentation fault.
0x28103e0e in ?? () from /usr/local/lib/libstdc++.so.6


Если кто сталкивался, прошу помочь, а то машина старая и каждая итерация по сборке занимает уйму времени......
p.s. сейчас пытаюсь собрать 4.9.4 сразу используя рабочий 4.2.1 (хотя ранее пытался собрать 4.9.0 и не получилось).. надеюсь он возьмет все из нужных мест ... PATH вернул в исходное состояние, чтобы все бралось из /usr/bin
и попробую поставить новый gdb, может он что подскажет нового в коре.....
Re: Скомпилированная программа на собранном gcc выдает segfault
От: B0FEE664  
Дата: 06.12.19 13:38
Оценка: +1
Здравствуйте, lolovo, Вы писали:

L> std::cout<<i<<std::endl; //<--- SegFault

L>Error while reading shared library symbols:
L>Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /usr/local/lib/libstdc++.so.6]
L>Dwarf Error: wrong version in compilation unit header (is 4, should be 2) [in module /usr/local/lib/libgcc_s.so.1]

L>Если кто сталкивался, прошу помочь, а то машина старая и каждая итерация по сборке занимает уйму времени......


Я не сталкивался и собрать gcc из исходников ни разу не сподобился, но имею подозрение, что библиотека libstdc++.so.6 собрана не с теми исходниками стандартной библиотеки, что само приложение. В этом случае использование std::cout вполне может ронять приложение.

Попробуйте слинковать статически:
g++ -static -g -o k k.cpp
И каждый день — без права на ошибку...
Re[2]: Скомпилированная программа на собранном gcc выдает segfault
От: lolovo  
Дата: 06.12.19 15:08
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Попробуйте слинковать статически:

BFE>g++ -static -g -o k k.cpp

тот же результат

BFE>Я не сталкивался и собрать gcc из исходников ни разу не сподобился, но имею подозрение, что библиотека libstdc++.so.6 собрана не с теми исходниками стандартной библиотеки, что само приложение. В этом случае использование std::cout вполне может ронять приложение.


После продолжительной возни решил по новой все откомпилировать (gmp, mpfr, mpc, isl) и начал проверять каждую библиотеку.... gmp всегда все тесты проходил, но вот обнаружилось то, что mpfr все провалил.... при непосредственной связке с gmp-6.0.1...пришлось делать даунгрейд, а точнее строго по версиям для конкретной версии gcc... в итоге пришлось поставить gmp-4.3.2 , к нему строго mpfr-2.4.2 (т.к. выше версии не проходили тесты), далее mpc-0.8.1... ну и isl-0.14 , т.к. решил собрать gcc-5.1.0 раз уж на то пошло....а он цеплял isl при конфиге, опций принудительного отключения isl не нашел, поэтому решил собрать совместимую версию с gcc.. теперь жду когда соберется gcc и соберется ли.... отпишусь по результату. Пока лишь думаю, что mpfr, который не проходил тесты и был причиной....
Re[3]: Скомпилированная программа на собранном gcc выдает se
От: lolovo  
Дата: 06.12.19 19:58
Оценка:
L>... отпишусь по результату. Пока лишь думаю, что mpfr, который не проходил тесты и был причиной....

В общем, собрал gcc-5.1.0 (до этого не собиралось, видать из-за несовместимой связки gmp/mpfr/mpc/isl), проверил через make check gmp/mpfr/mpc/isl — все тесты пройдены. Думал сейчас наконец-то заработает все, но нет... результат тот же.... уже не знаю о чем и думать........в общем, какая-то черная магия ....и самое смешное, результат, который преследовал (подключить библиотеку, написанную на C++11) не оправдал ожиданий....лезут те же ошибки при компиляции (/usr/local/bin/g++ -I/usr/local/include -L/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib -lstdc++ -std=c++11 -g -o k k.cpp):

...
error: 'to_string' is not a member of 'std'
...
error: 'stoi' is not a member of 'std'
...


Проще наверное найти библиотеку на старом Си/Си++ , чем побороть компилятор....
Отредактировано 06.12.2019 19:59 lolovo . Предыдущая версия .
Re[4]: Скомпилированная программа на собранном gcc выдает se
От: lolovo  
Дата: 06.12.19 21:34
Оценка:
при компиляции с флагами -Wl,--trace, удалось увидеть, что общими файлами являются:


/usr/lib/crt1.o
/usr/lib/crti.o
/usr/lib/libm.so
/usr/lib/libc.so
/usr/lib/crtn.o


что примечательно, почему-то crtbegin и crtend при этом разные (не знаю должны ли, если выше crt* общие?):

при компиляции старым:

/usr/lib/crtbegin.o
/usr/lib/crtend.o


при компиляции новым:

/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/crtbegin.o
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/crtend.o


еще один момент, который режет глаз...у старого компилятора вывод четко на *.so, у нового же libgcc.a и libgcc_s.so:

-lstdc++ (/usr/lib/libstdc++.so)
-lm (/usr/lib/libm.so)
-lgcc_s (/usr/lib/libgcc_s.so)
-lc (/usr/lib/libc.so)
-lgcc_s (/usr/lib/libgcc_s.so)


у нового:

/usr/local/lib/libstdc++.so
..
/usr/local/lib/libgcc_s.so
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/libgcc.a
..


Должно ли так быть?

Полные данные вывода + параметры компиляции старым компилятором и новым соответственно:

/usr/bin/g++ -I/usr/include -L/usr/lib -Wl,-rpath -Wl,/usr/lib -Wl,--trace -g -o k k.cpp

/usr/bin/ld: mode elf_i386_fbsd
/usr/lib/crt1.o
/usr/lib/crti.o
/usr/lib/crtbegin.o
/var/tmp//ccEH2fSo.o
-lstdc++ (/usr/lib/libstdc++.so)
-lm (/usr/lib/libm.so)
-lgcc_s (/usr/lib/libgcc_s.so)
-lc (/usr/lib/libc.so)
-lgcc_s (/usr/lib/libgcc_s.so)
/usr/lib/crtend.o
/usr/lib/crtn.o

/usr/local/bin/g++ -I/usr/local/include -L/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib -Wl,--trace -g -o k k.cpp

/usr/lib/crt1.o
/usr/lib/crti.o
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/crtbegin.o
/var/tmp//cchDb3mX.o
/usr/local/lib/libstdc++.so
/usr/lib/libm.so
/usr/local/lib/libgcc_s.so
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/libgcc.a
/usr/lib/libc.so
/usr/local/lib/libgcc_s.so
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/libgcc.a
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/crtend.o
/usr/lib/crtn.o

Re[5]: Скомпилированная программа на собранном gcc выдает se
От: lolovo  
Дата: 06.12.19 22:05
Оценка:
и пожалуй еще изыскания...при компиляции при помощи старого и нового g++ readelf -s -d -S выдает непонятные мне отличия по std::cout:

в старом он находится в .symtab:

Symbol table '.symtab' contains 105 entries:
74: 08049f58 140 OBJECT GLOBAL DEFAULT 24 _ZSt4cout@@GLIBCXX_3.4


в новом он находится в .dynsym:

Symbol table '.dynsym' contains 18 entries:
9: 08049d80 140 OBJECT GLOBAL DEFAULT 25 _ZSt4cout@GLIBCXX_3.4 (2)


при этом используются разные соответствующие libstdc++.so, в старом варианте _ZSt4cout из /usr/lib/libstdc++.so, в новом — из /usr/local/lib/libstdc++.so

как это понимать не понятно...


upd: и пожалуй кульминация, в которой пожалуй все кроется......


readelf -s -d -S /usr/local/lib/libstdc++.so|grep cout
736: 00175ee0 144 OBJECT GLOBAL DEFAULT 28 _ZSt5wcout@@GLIBCXX_3.4
4084: 00176160 140 OBJECT GLOBAL DEFAULT 28 _ZSt4cout@@GLIBCXX_3.4
2448: 00175ee0 144 OBJECT GLOBAL DEFAULT 28 _ZSt5wcout
5796: 00176160 140 OBJECT GLOBAL DEFAULT 28 _ZSt4cout
readelf -s -d -S /usr/lib/libstdc++.so|grep cout
2868: 000eec00 144 OBJECT GLOBAL DEFAULT 24 _ZSt5wcout@@GLIBCXX_3.4
2902: 000ee980 140 OBJECT GLOBAL DEFAULT 24 _ZSt4cout@@GLIBCXX_3.4


Кто-нибудь может сделать вывод readelf'ом ^^^ у себя libstdc++.so ??? Такое задвоение вообще нормально? Может в этом собака зарыта?
Отредактировано 06.12.2019 22:10 lolovo . Предыдущая версия .
Re[5]: Скомпилированная программа на собранном gcc выдает se
От: B0FEE664  
Дата: 09.12.19 10:07
Оценка:
Здравствуйте, lolovo, Вы писали:

L>Полные данные вывода + параметры компиляции старым компилятором и новым соответственно:

L>
/usr/local/bin/g++ -I/usr/local/include -L/usr/local/lib -Wl,-rpath -Wl,/usr/local/lib -Wl,--trace -g -o k k.cpp

/usr/lib/crt1.o
/usr/lib/crti.o
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/crtbegin.o
/var/tmp//cchDb3mX.o
/usr/local/lib/libstdc++.so
/usr/lib/libm.so
/usr/local/lib/libgcc_s.so
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/libgcc.a
/usr/lib/libc.so
/usr/local/lib/libgcc_s.so
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/libgcc.a
/usr/local/lib/gcc/i386-unknown-freebsd/5.1.0/crtend.o
/usr/lib/crtn.oL>


Мне так кажется, что надо задать --sysroot параметер, а то у вас используются библиотеки от разных версий, если я правильно понял.


Повторюсь, что я никогда не собирал gcc, поэтому ниже изложенное — теоретические измышления.
Я всегда думал, что версия компилируемой std:: библиотеки должна соответствовать версии компилятора, так как писатели библиотеки закладываются (имеют право по стандарту) на особенности конкретной версии компилятора. Поэтому компилировать старую версию библиотеки новой версией компилятора — не лучшая идея. Вы уверены, что исходники std библиотеки соответствуют версии компилятора?
И каждый день — без права на ошибку...
Re[6]: Скомпилированная программа на собранном gcc выдает se
От: lolovo  
Дата: 09.12.19 20:53
Оценка: 1 (1)
Здравствуйте, B0FEE664, Вы писали:

BFE>Мне так кажется, что надо задать --sysroot параметер, а то у вас используются библиотеки от разных версий, если я правильно понял.


я пробовал --sysroot, результата нужного не было.

BFE>Повторюсь, что я никогда не собирал gcc, поэтому ниже изложенное — теоретические измышления.

BFE>Я всегда думал, что версия компилируемой std:: библиотеки должна соответствовать версии компилятора, так как писатели библиотеки закладываются (имеют право по стандарту) на особенности конкретной версии компилятора. Поэтому компилировать старую версию библиотеки новой версией компилятора — не лучшая идея. Вы уверены, что исходники std библиотеки соответствуют версии компилятора?

Я решил для себя проблему следующим образом: Почистил все руками от предыдущих установок в /usr/local/bin lib libexec include, т.к. понял, что make install — зло. По-новому пересобрал компоненты-библиотеки gmp,mpfr,mpc для gcc-5.1.0, проверил их чз make check и установил их по умолчанию в /usr/local (make install). Далее уже пересобрал gcc-5.1.0, задав ему отдельную директорию установки через --prefix. Это избавило меня от SegFault'a с std::cout... такое решение было проще, чем искать почему и из-за чего все наперекосяк. При этом пришлось еще пободаться непосредственно с библиотекой, ради которой все эти мучены были пройдены и добавить флаги при компиляции, чтобы не было ругани на std::to_string при компиляции и линковке — "-D_GLIBCXX_USE_CXX11_ABI=0 -D_GLIBCXX_USE_C99". До конца ругань эти флаги не убрали, при линковке шла ругань на отсутствие std::out_of_range и std::domain_error. Пришлось их руками убрать из библиотеки, оставив просто "throw;". Именно так удалось заставить работать библиотеку, написанную якобы на C++11, компилятором, якобы поддерживающим C++11 ...

Пробовал еще ставить 6.1, 7.1... там лезет ошибка при сборке — "fatal error: xlocale.h: No such file or directory". Закрадываются мысли, что здесь уже системные библиотеки не тянут. В интернете где-то были решения по разрешению проблемы путем отключения данной фичи в целом, но я решил остановиться на 5.1 )
Отредактировано 09.12.2019 21:05 lolovo . Предыдущая версия . Еще …
Отредактировано 09.12.2019 20:58 lolovo . Предыдущая версия .
Re: Скомпилированная программа на собранном gcc выдает segfault
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 22.12.19 08:41
Оценка:
Здравствуйте, lolovo, Вы писали:

L>Всем привет!


L>Имеется штатный древний компилятор gcc4.2.1(freebsd). Была необходима поддержка одной библиотеки, которая вынудила перейти на новую версию gcc, так вот...после долгих танцев с бубном вокруг разных версий gcc , которые не хотели ставиться...с горем пополам собрал gcc-4.9.4 со следующим конфигом:


Что-то сразу непонятно. Какая версия freebsd? Почему не из порта, где эти проблемы решены? Для данной версии фряхи нет порта? Тогда можно сделать мерж, но учесть все грабли, которые там уже отработаны.

L>путь PATH был изменен таким образом, чтоб /usr/local/bin был доступен для поиска первым (export PATH=/usr/local/bin:...), т.к. все что собирал из списка выше, все устанавливалось в /usr/local.


/usr/local во фряхе это для портов. Если у вас самосбор, надо было складывать куда-то ещё. Завести какой-нибудь /opt/gcc-new и творить в нём что хотите.

L>Перед компиляцией настроил LD_LIBRARY_PATH (к слову, его такой переменной окружения изначально не было):


Обычно, да, её и нет — ибо незачем.

L>Что делаю не так? Чутье подсказывает мне, что проблема либо в изначальной сборке (что скорее всего и не понятно из-за чего, что и где могло пойти не так...ед. момент перед этим успешно собрал 4.5.0, но не проверял с std::cout его и перенес его в /usr/local, потом уже используя его собрал 4.7.0, далее аналогично перенес его в /usr/local и потом аналогично 4.9.0 и 4.9.4... может проблема в этом, что изначально на кривом g++ собирались последующие сборки),


Вполне может. Соберите на исходном, должно работать и сейчас (в currentʼе тоже gcc 4.2, хотя по умолчанию у них достаточно свежий clang).

L>Если кто сталкивался, прошу помочь, а то машина старая и каждая итерация по сборке занимает уйму времени......


Тут можно в виртуалке повторять сборку и копировать только результат. Фряха позволяет такое делать и в jailʼах.
The God is real, unless declared integer.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.