【发布时间】:2011-11-17 22:02:41
【问题描述】:
我有一个混合的 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";
}
生成文件:
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 对象一致。这很奇怪 - 我认为从 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 上,也不会调用全局构造函数 - 只是使用临时全局对象进行测试。由于某种原因,它只是不会在 sentry() 中崩溃。看起来这毕竟是一个 FPC 问题。 FPC 中有一个关于此行为的bug report。
【问题讨论】:
-
这可能与调用约定有关吗?如果添加
__stdcall会怎样? -
以前这样有效吗?闻起来像 C++ 运行时未初始化(例如,未调用全局 ctors/dtors)。你在使用 GNU 链接器吗?这更多是链接器而不是编译器的问题,并且您还没有提供正在使用的链接命令...
-
@KerrekSB
cdecl看起来就在这里,无论如何,它对没有参数的 void 函数有什么影响? -
我在任何文档中都看不到任何表明
initc初始化 C++ 运行时的内容。您有此类文档的链接吗? -
通常
iostream使用一些技巧来确保即使对于来自静态对象构造函数的输出也正确初始化流(通常由于翻译单元之间未定义静态初始化顺序而无法保证这一点)。也许这些技巧与 FreePascal 的初始化不兼容。
标签: c++ g++ freepascal libstdc++