3

我有一个混合的 Free Pascal/C++ 项目。i386 上的 Debian 5.0(“Lenny”),FPC 2.4.4。cout<<当我运行程序时,它在第一次调用时崩溃。有趣的是,它曾经工作了一段时间。一些操作系统更新可能会破坏它。这是孤立的问题:

帕斯:

{$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";
}

生成文件:

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)?

编辑:它变得越来越奇怪。我在 CentOS 5.3 机器上运行相同的二进制文件 ( p) - 它像宣传的那样工作。所以可能是关于共享库版本......我会去收集更多关于不同 Linux 的统计数据。

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.6cmov. 那个cmov目录是怎么回事?为什么有两个同名的 libc 副本?

编辑:即使在 CentOS 上,也不会调用全局构造函数 - 只是使用临时全局对象进行测试。由于某种原因,它只是不会在 sentry() 中崩溃。看起来这毕竟是一个 FPC 问题。FPC 中有关于此行为的错误报告

4

3 回答 3

3

确实,我尝试明确链接到静态 co(使用所有各种版本的 libstdc++。所以我可以在我的盒子上找到)并且我得到了同样的失败:

Runtime error 216 at $00007F3B9C9EFAD1
  $00007F3B9C9EFAD1

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

只有在更改为动态链接后,我才让它在我的 Natty 盒子上工作:

在 p.pas 中:

{$L c.so}

生成文件

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

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

$ LD_LIBRARY_PATH=$PWD
$ ./p
Hello world
于 2011-11-17T22:53:49.180 回答
0

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

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

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

于 2011-11-18T08:07:19.690 回答
0

专门针对cout(以及其他全局流),将以下行添加到 C++ 入口点有助于:

std::ios_base::Init();

更大的问题仍然存在——没有构造任意的全局 C++ 对象。

于 2011-11-18T20:39:31.520 回答