Free Pascal/C++ project crashes in cout::sentry

你。 提交于 2019-12-10 18:51:16

问题


I have a mixed Free Pascal/C++ project. Debian 5.0 ("Lenny") on i386, FPC 2.4.4. When I run the program, it crashes on the first cout<< call. Funnily, it used to work for some time; some OS update probably broke it. Here's the issue isolated:

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

Make, run, segfault. Tried on a brand new Debian VM - same result.

The crash takes place within basic_fstream::sentry::sentry(). They claim this crash location is consistent with the global cout object not being initialized. That's strange - I thought using initc from the Pascal side makes sure global C++ variables are initialized.

Any ideas, please? Could it be somehow the version of libstdc++ I'm linking against (it's libstdc++.so.6.0.10)?

EDIT: it gets weirder and weirder. I run the same binary (p) on a CentOS 5.3 box - it works as advertised. So probably it's about shared lib versions... I'll go gather some more stats on different Linuces.

EDIT2: one thing I noticed: when I do ldd p on my Debian box, here's what I get:

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)

And when I do the same on the CentOS box where it works:

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)

So all C libraries (just not the C++ one) are coming from i686/cmov directory. The Debian machine also has /lib/libc.so.6, and it's different from the one in cmov. What's the deal with that cmov directory? And why two different copies of libc with the same name?

EDIT: even on CentOS, the global constructors are not called - just tested with an ad-hoc global object. It just does not crash in sentry() for some reason. Looks like this is a FPC issue after all. There's a bug report in FPC regarding this behavior.


回答1:


Indeed, I tried explicitely linking to a static c.o (with all the various versions of libstdc++.so I could find on my box) and I get the same kind of failure:

Runtime error 216 at $00007F3B9C9EFAD1
  $00007F3B9C9EFAD1

I will try on an older installation shortly. Update Can't make linking c.o work on Maverick either (gcc 4.4.5 and fpc 2.4.0-2ubuntu1.10.10).

I made it work on my Natty box only after changing to dynamic linking:

In p.pas:

{$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



回答2:


Initc should cause FPC to switch startup code to a form that calls glibc initializers that then should init C++ via the usual ctor/dtor mechanisms.

Note that initc does NOT switch Pascal memory management to use libmalloc. The pascal code will use its own suballocator, which bases directly on mmap(2)

Since your problems also seem to be memory allocation related, try to use unit "cmem" instead of initc to force the pascal runtime to use libmalloc part of glibc for memory management.




回答3:


Specifically for cout (as well as other global streams), adding the following line to the C++ entry point helps:

std::ios_base::Init();

The larger problem still exists - arbitrary global C++ objects are not constructed.



来源:https://stackoverflow.com/questions/8174998/free-pascal-c-project-crashes-in-coutsentry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!