编译时出现了“gcc字符串表溢出错误”。

9

当我尝试从Boost Spirit Qi compiler_tutorial构建一个更加复杂的示例(在模板实例化方面进行了修改)时,我会收到以下错误信息:

 debug\expression.o:-1: error: section .debug_frame$_ZNK5boost5proto3if_INS0_6detail7has_tagINS0_6tagns_3tag7greaterEEENS0_12reverse_foldINS0_1_ENS0_6_stateENS2_18reverse_fold_tree_IS6_NS_6spirit6detail18make_binary_helperINSC_13meta_compilerINSC_2qi6domainEE12meta_grammarEEEEEEESK_E4implIRNSG_4ruleINSC_3lex7lexertl8iteratorINSR_7functorINSR_14position_tokenIN9__gnu_cxx17__normal_iteratorIPKcSsEENS_3mpl6vectorISsN4mpl_2naES13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_EENS12_5bool_ILb0EEEyEENSR_6detail4dataESZ_NS15_ILb1EEES16_EEEEFSt4listIN7client3ast10expressionIdEESaIS1H_EEvENSC_11unused_typeES1L_S1L_EENS_6fusion4consINSG_12literal_charINSC_13char_encoding8standardELb1ELb0EEENS1O_4nil_EEERS1L_EclES1N_RKS1V_S1W_: string table overflow at offset 10000433

命令行:

c:/mingw64/bin/../libexec/gcc/x86_64-w64-mingw32/4.7.2/cc1plus.exe -quiet -v -I c:/libs/boost/include -I ../src/compiler -I c:/libs/boost/include -I . -I c:/libs/Qt-static/mkspecs/win32-g++-x64-4.7.2-corei7-avx-corei7-avx -iprefix c:\mingw64\bin\../lib/gcc/x86_64-w64-mingw32/4.7.2/ -D_REENTRANT -U_REENTRANT -D BOOST_THREAD_POSIX -D BOOST_THREAD_USE_LIB -D UNICODE -D QT_LARGEFILE_SUPPORT -D _DEBUG=1 -D DEBUG=1 -D BOOST_SPIRIT_QI_DEBUG=1 -D BOOST_SPIRIT_NO_PREDEFINED_TERMINALS=1 ../src/compiler/expression.cpp -quiet -dumpbase expression.cpp -m64 -march=corei7-avx -mtune=corei7-avx -mtls-dialect=gnu2 -auxbase-strip debug/expression.o -g -O0 -Wall -Wextra -std=gnu++11 -version -fsignaling-nans -fno-math-errno -frtti -fexceptions -o - |

平台:mingw-builds(x64-4.7.2-release-posix-sjlj-rev5.7z)适用于x64主机和目标(-m64),在x64 Windows 7 HB上符合gcc 4.7.2,并且具有8GB物理内存。

看起来是由于内存不足引起的。

为了避免这个问题,您应该怎么做?我确定这里没有递归模板。


尝试删除-g选项... - Icarus3
气体在一段时间内消耗了449272 kB的物理内存,然后以错误退出。 - Tomilov Anatoliy
2个回答

15
我发现这个问题的唯一答案令人不满意,但是经过进一步的研究,确实使用更高的gcc优化级别是解决这个问题的方法。我想分享一下我学到的东西。
这个问题只适用于以PE/COFF格式编写二进制代码,这也是Windows使用的格式。通过在binutils的源代码中查找,我找到了bfd的coff后端代码中的这段代码片段/注释
/* An inherent limitation of the /nnnnnnn notation used to indicate
the offset of the long name in the string table is that we
cannot address entries beyone the ten million byte boundary.  */
if (string_size >= 10000000)
{
  bfd_set_error (bfd_error_file_too_big);
  (*_bfd_error_handler)
    (_("%B: section %s: string table overflow at offset %ld"),
    abfd, current->name, string_size);
  return FALSE;
}

二进制文件中的字符串表看起来最多可以达到10百万字节,我相信唯一限制它的是节表项格式只为节名称指定了8个字节。如果名称超出了这个限制,它可以指定字符串表中的偏移量。该数字必须用ASCII表示,并以正斜杠开头,仅提供了七个十进制位数,因此有10,000,000的限制。我在Microsoft的PE/COFF规范修订版8.1的第13节中发现了这一点。

你实际上无法改变二进制格式,所以我知道的唯一解决方法是让gcc制作一个较小的字符串表。对我来说,-O2解决了这个问题。


但是经过进一步的研究,确实运行gcc以更高的优化级别似乎是解决这个问题的方法 - 那么分割二进制代码(即创建多个共享库)怎么样?优化级别是减少字符串表的唯一因素吗? - Xeverous
我也遇到了这个问题,-O1或-Os对我有所帮助,但是找出确切的优化方案可以解决这个问题将非常有帮助,因此我尝试使用由-O1/-Os启用的所有优化,并惊讶地发现它并没有起作用,我尝试了各种-f标志的组合。总结一下,我没有找到更好的解决方案,我试图找出解决方法耗费了3小时。 - Silver Zachara
显然,微软的编译器也有完全相同的问题,但在那种情况下(对我来说),解决方案是/GL标志:整个程序优化。我尝试过的其他优化标志都是无用的:/O1/O2/Os和其他一些。 - John Perry

7
我曾经遇到同样的问题并找到了解决方案。我使用了许多来自Boost.Spirit2解析器的boost模板类。
我在openSuse 12.2上使用MingW64交叉编译器(gcc 4.7.2)。 MingW32编译相同的文件时没有问题,无论是在发布模式还是调试模式下。
命令:
/usr/bin/x86_64-w64-mingw32-g++ -c -fpermissive -fexceptions -Wall -Wextra -Wno-long-long -Wno-unknown-pragmas -mthreads -Wall -frtti -finline-functions -o file.o file.cpp 输出:
.pdata$_ZN5boost6fusion6detail10linear_anyINS0_13cons_iteratorIKNS0_4consINS_6spirit2qi6kleeneINS6_10char_classINS5_3tag9char_codeINS9_5spaceENS5_13char_encoding8standardEEEEEEENS4_INS6_11alternativeINS4_INS6_6actionINSI_INSI_INS6_8sequenceINS4_INSI_INS6_14literal_stringIRA11_KcLb1EEENS_7phoenix5actorINSP_9compositeINSP_6detail13function_evalILi2EEENS0_6vectorINSP_5valueINSP_3stl9push_backEEENSP_9referenceISsEENSW_IcEENS0_5void_ES13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_EEEEEEEENS4_INS6_16lexeme_directiveINS7_INSI_INS6_10differenceINS8_INSA_INS9_5char_ESD_EEEENS6_10eol_parserEEENSQ_INSR_ISU_NSV_ISZ_S11_NS5_8argumentILi0EEES13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_EEEEEEEENS4_ISG_NS0_3nilEEEEEEEEEEENS4_INS6_4plusINSI_INS6_9referenceIKNS6_4ruleIN9__gnu_cxx17__normal_iteratorIPSL_SsEEFN7dynardo9structure11SimplexDataEvENS_5proto7exprns_4exprINS2A_6tagns_3tag8terminalENS2A_7argsns_4termINSA_INS9_5blankESD_EEEELl0EEENS5_11unused_typeES2M_EEEENSQ_INSR_ISU_NSV_INSW_INSS_19member_function_ptrILi1EvM11My_PushbackINS27_20SimplexDataContainerEEFvRKS28_EEEEENSW_IPS2T_EES1G_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_EEEEEEEEEES1T_EEEEEEEEEEEENSQ_INSR_ISU_NSV_INSW_INSX_6insertEEENS10_ISt3mapISsS2S_St4lessISsESaISt4pairIKSsS2S_EEEEENS10_IS3I_ISsS2S_EEES13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_EEEEEEEENSQ_INSR_INST_ILi1EEENSV_INSW_INSX_5clearEEES11_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_EEEEEEEENSQ_INSR_IS3U_NSV_IS3W_NS10_IS2S_EES13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S13_S

看起来缺少优化选项是问题所在。添加-O1或-O2

/usr/bin/x86_64-w64-mingw32-g++ -c -fpermissive -fexceptions -Wall -Wextra -Wno-long-long -Wno-unknown-pragmas -mthreads -Wall -frtti -O1 -g -o file.o file.cpp

对我来说解决了问题,甚至允许调试选项(-g)!


我曾经遇到过同样的问题,加入这些标志解决了它。感谢分享。 - LeXela-ED

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接