【问题标题】:gcc 4.8.1: combining c code with c++11 codegcc 4.8.1:将 c 代码与 c++11 代码相结合
【发布时间】:2013-10-03 07:11:04
【问题描述】:

我没有花太多精力去发现原因,但是 gcc 4.8.1 给我编译结合 c 和 c++ 以及 c++11 中的一些新东西的旧源代码带来了很多麻烦

我已经设法在这段代码中找出问题:

# include <argp.h>
# include <algorithm>

g++ -std=c++0x -c -o test-temp.o test-temp.C 4.6.3 版、ubuntu 12.04 编译良好​​p>

相比之下,在 4.8.1 版本中,同样的命令行会抛出很多错误:

In file included from /home/lrleon/GCC/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/include/x86intrin.h:30:0,
                 from /home/lrleon/GCC/include/c++/4.8.1/bits/opt_random.h:33,
                 from /home/lrleon/GCC/include/c++/4.8.1/random:51,
                 from /home/lrleon/GCC/include/c++/4.8.1/bits/stl_algo.h:65,
                 from /home/lrleon/GCC/include/c++/4.8.1/algorithm:62,
                 from test-temp.C:4:
/home/lrleon/GCC/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/include/mmintrin.h: In function ‘__m64 _mm_cvtsi32_si64(int)’:
/home/lrleon/GCC/lib/gcc/x86_64-unknown-linux-gnu/4.8.1/include/mmintrin.h:61:54: error: can’t convert between vector values of different size
   return (__m64) __builtin_ia32_vec_init_v2si (__i, 0);
                                                      ^

...还有更多。

如果我执行也会发生同样的情况

g++ -std=c++11 -c -o test-temp.o test-temp.C ;再次,版本 4.8.1

但是,如果我交换标题行,那就是

# include <algorithm>
# include <argp.h>

然后一切编译正常。

有人启发我了解发生了什么?

【问题讨论】:

  • 你的代码中是否使用了任何 stl 容器?
  • 能否提供输出:g++ -E -dM -&lt;/dev/null | grep 'SSE\|MMX'
  • 嗨@Brett。输出为#define __MMX__ 1 #define __SSE2_MATH__ 1 #define __SSE_MATH__ 1 #define __SSE2__ 1 #define __SSE__ 1
  • @lrleon - 它似乎确实指向一个错误; &lt;bits/opt_random.h&gt; 中的模板代码在 #ifdef __SSE3__ 块内,但 &lt;x86intrin.h&gt;,因此 &lt;mmintrin.h&gt;,标题仍然包括在内 - 正如其他人指出的那样,缺少 #extern "C" 范围。如果您的标头顺序破解有效,您可能只需要在代码中添加注释并等待 gcc 4.9 :)
  • @lrleon - 但是,所有内部函数都具有 __always_inline__ 属性,因此 extern "C" 应该无关紧要。我认为您应该冒着“烦人”的风险再次报告问题,因为似乎很长时间没有采取任何行动。

标签: c gcc c++11


【解决方案1】:

这是一个已知的错误,显然某些标头在正确的位置缺少 extern "C" 声明:

我也刚刚在 Windows 上使用 GCC 4.7.2 遇到了这个问题。似乎所有 intrin.h 标头都缺少 extern "C" 部分。由于函数始终是内联的,因此符号永远不会出现在任何地方,这在以前不是问题。但是现在另一个头文件第二次声明了这些函数,必须做一些事情。

【讨论】:

  • 感谢您的帮助@Zeta。我已经阅读了错误报告,好吧,我会看看我是否能找到解决这个问题的方法
【解决方案2】:

想到两件事:

1) 标题中缺少extern "C",这种情况并不罕见。

2) 数据对齐有问题。可能您正在使用 STL 容器来存储 SSE 类型,这不能保证这些类型的对齐。在这种情况下,您应该实现自定义分配器,它将使用 alligned_malloc。但我认为在这种情况下它应该编译得很好,但是在运行时给你段错误。但是谁知道编译器现在可以检测到什么:)

以下是您可能想阅读的关于该主题的内容:About memory alignmentAbout custom allocators

附言你的一段代码会很好

【讨论】:

  • 感谢@Stan 的帮助。我将对此问题进行更多研究。我可以完美地给你一段我的真实代码。为此,我需要您的坐标,因为它有些大。但是请注意,只有上面两行代码才能触发错误
  • lrleon,如果只是那两行代码,那么我确定它在标题中缺少 extern "C" 语句,正如 Zeta 已经说过的那样。
【解决方案3】:

我遇到了同样的问题。因为真的很烦人,所以我把它砍成&lt;argp.h&gt;

这是触发 ubuntu 14.04 / gcc 4.8.2 错误的代码(在标准 gcc 标头 argp.h 中):

/* This feature is available in gcc versions 2.5 and later.  */
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
#  define __attribute__(Spec) /* empty */
# endif

这可能是为了使标头与旧的 gcc 和严格的 ANSI C++ 定义兼容。问题是 --std=c++11 设置了__STRICT_ANSI__宏。

我评论了#define __attribute__(spec) 并且编译工作正常!

由于注释系统标头不切实际,解决方法是使用g++ --std=gnu++11 而不是g++ --std=c++11,因为它没有定义__STRICT_ANSI__。它在我的情况下有效。

这似乎是 gcc 中的一个错误。

【讨论】:

  • 我不会将此称为 GCC 中的错误。 #defining attribute 为空是个坏主意:GCC 使用 attribute 机制来提供某些扩展(例如用于矢量化),并通过禁用所有 attribute 声明您正在干扰 GCC 的内部结构。
  • @Erik:你误解了(或者我解释得不好:-))。这是将 attribute 重新定义为空的标准 gcc 标头。我同意这是一件坏事,这就是我称之为错误的原因:-) 包含的标准头文件的顺序不应导致编译失败!
  • @neuro:好的——我同意。
猜你喜欢
  • 2015-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-03
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多