自由 Pascal/C++项目在 cout::sentry 中崩溃

发布于 2024-12-17 05:49:44 字数 2001 浏览 6 评论 0原文

我有一个混合的 Free Pascal/C++ 项目。 i386 上的 Debian 5.0(“Lenny”),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

Make,run,segfault。尝试了全新的 Debian VM - 相同的结果。

崩溃发生在 basic_fstream::sentry::sentry() 内。他们声称此崩溃位置与未初始化的全局 cout 对象一致。这很奇怪 - 我认为从 Pascal 端使用 initc 可以确保全局 C++ 变量被初始化。

有什么想法吗?它是否可能是我链接的 libstdc++ 版本(它是 libstdc++.so.6.0.10)?

编辑:它变得越来越奇怪。我在 CentOS 5.3 机器上运行相同的二进制文件 (p) - 它的工作原理与宣传的一样。所以可能与共享库版本有关...我将收集更多关于不同 Linux 的统计信息。

EDIT2:我注意到一件事:当我在 Debian 机器上执行 ldd p 时,这就是我得到的结果:

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 上,也不会调用全局构造函数 - 只是使用临时全局对象进行测试。由于某种原因,它只是不会在哨兵()中崩溃。看来这毕竟是FPC的问题。 FPC 中有一个关于此行为的错误报告

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

∞觅青森が 2024-12-24 05:49:44

事实上,我尝试明确链接到静态 co(包含所有不同版本的 libstdc++.so 我可以在我的盒子上找到),但我遇到了同样的失败:

Runtime error 216 at $00007F3B9C9EFAD1
  $00007F3B9C9EFAD1

我很快就会尝试旧的安装。 更新 也无法在 Maverick 上进行链接协作(gcc 4.4.5 和 fpc 2.4.0-2ubuntu1.10.10)。

我只在更改为动态链接后才使其在我的 Natty 盒子上工作:

在 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

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
鼻尖触碰 2024-12-24 05:49:44

Initc 应该使 FPC 将启动代码切换为调用 glibc 初始化器的形式,然后该初始化器应该通过通常的 ctor/dtor 机制初始化 C++。

请注意,initc 不会将 Pascal 内存管理切换为使用 libmalloc。 pascal代码将使用它自己的子分配器,它直接基于mmap(2)

由于您的问题似乎也与内存分配相关,请尝试使用单元“cmem”而不是initc来强制pascal运行时使用glibc的libmalloc部分内存管理。

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.

瞳孔里扚悲伤 2024-12-24 05:49:44

特别是对于 cout(以及其他全局流),将以下行添加到 C++ 入口点会有所帮助:

std::ios_base::Init();

更大的问题仍然存在 - 不会构造任意全局 C++ 对象。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文