В Cout :: sentry происходит сбой бесплатного проекта Pascal / C ++ - PullRequest
3 голосов
/ 18 ноября 2011

У меня смешанный проект Free Pascal / C ++. Debian 5.0 ("Lenny") на i386, FPC 2.4.4. Когда я запускаю программу, она падает при первом вызове cout<<. Как ни странно, раньше он работал некоторое время; какое-то обновление ОС, вероятно, сломало его. Вот проблема изолирована:

p.pas:

{$L c.o}    
program p;
uses initc;
procedure Hello; cdecl; external name 'Hello';

begin
     Hello;
end.     

c.cpp:

#include <iostream>
//void * __dso_handle; //You might need to uncomment that
extern "C" void Hello()
{
    std::cout << "Hello world";
}

Makefile:

p : c.o p.pas Makefile
    fpc p.pas -k-lstdc++

c.o : c.cpp
    g++ -c c.cpp

Сделать, запустить, сегфо. Пробовал на новой Debian VM - тот же результат.

Сбой происходит в basic_fstream :: sentry :: sentry (). Они утверждают, что это место падения соответствует глобальному объекту cout, который не инициализируется. Это странно - я думал, что использование initc со стороны Pascal гарантирует, что глобальные переменные C ++ инициализируются.

Есть идеи, пожалуйста? Может ли это быть версия libstdc ++, на которую я ссылаюсь (это libstdc ++. So.6.0.10)?

РЕДАКТИРОВАТЬ: становится все страннее и страннее. Я запускаю тот же двоичный файл (p) на коробке CentOS 5.3 - он работает как рекламируется. Так что, вероятно, речь идет о версиях с общей библиотекой ... Я пойду соберу еще статистику по разным линуксам.

EDIT2: я заметил одну вещь: когда я делаю ldd p на своей коробке Debian, вот что я получаю:

linux-gate.so.1 =>  (0xb77a6000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb76a6000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb754b000)
libm.so.6 => /lib/i686/cmov/libm.so.6 (0xb7524000)
/lib/ld-linux.so.2 (0xb77a7000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7517000)

И когда я делаю то же самое на коробке CentOS, где она работает:

libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb7ec2000)
libc.so.6 => /lib/libc.so.6 (0xb7d69000)
libm.so.6 => /lib/libm.so.6 (0xb7d40000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7d34000)
/lib/ld-linux.so.2 (0xb7fb7000)

Таким образом, все библиотеки C (только не C ++) происходят из каталога i686/cmov. Машина Debian также имеет /lib/libc.so.6, и она отличается от машины в cmov. Что за дело с этим каталогом cmov? И почему две разные копии libc с одинаковыми именами?

РЕДАКТИРОВАТЬ: даже в CentOS глобальные конструкторы не вызываются - просто тестируются с помощью специального глобального объекта. По какой-то причине он не падает в sentry (). Похоже, это проблема с FPC. В FPC есть сообщение об ошибке относительно этого поведения.

Ответы [ 3 ]

3 голосов
/ 18 ноября 2011

Действительно, я попытался явно связать со статическим co (со всеми различными версиями libstdc ++. Чтобы я мог найти его на своем ящике), и я получаю такой же сбой:

Runtime error 216 at $00007F3B9C9EFAD1
  $00007F3B9C9EFAD1

Я будупопробуйте более старую установку в ближайшее время. Обновление Также не могу заставить работать со ссылками на Maverick (gcc 4.4.5 и fpc 2.4.0-2ubuntu1.10.10).

Я заставил его работать на моей коробке Natty только после изменениядля динамического связывания:

В ppas:

{$L c.so}

Makefile

p : c.so p.pas Makefile
    fpc p.pas

c.so : c.cpp
    g++ -shared -fPIC c.cpp -o $@

Run

$ LD_LIBRARY_PATH=$PWD
$ ./p
Hello world
0 голосов
/ 19 ноября 2011

Специально для cout (как и для других глобальных потоков) помогает добавление следующей строки в точку входа C ++:

std::ios_base::Init();

Большая проблема все еще существует - произвольные глобальные объекты C ++ не создаются.

0 голосов
/ 18 ноября 2011

Initc должен заставить FPC переключать код запуска в форму, которая вызывает инициализаторы glibc, которые затем должны запускать C ++ с помощью обычных механизмов ctor / dtor.

Обратите внимание, что initc НЕ переключает управление памятью Pascal на использование libmalloc. Паскаль-код будет использовать собственный субраспределитель, основанный непосредственно на mmap (2)

Поскольку ваши проблемы, похоже, также связаны с выделением памяти, попробуйте использовать модуль "cmem" вместо initc, чтобы заставить время выполнения паскаля использовать libmalloc часть glibc для управления памятью.

...