Bob*_*Bob 5 c++ gcc boost qnx qcc
我的编译命令是
C:\work\PROJ-test\QNX_SDK\host\win32\x86/usr/bin/qcc -c -Wc,-frandom-seed="sadfsasafssadsa" -Wc,-MP,-MT,C:/work/PROJ-test/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.o,-MMD,C:/work/PROJ-test/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.d -Vgcc_ntoarmv7le -w9 -shared -O3 -ggdb3 -DBUILD_VERSION= -DPASLOGOPTIONS=0x02 -DPASLOGAPPZONES=31,23,30,9,8,3 -DNS1_5PORT -DBOARD_TYPE=PRODUCTION C:/work/PROJ-test/N_Manag/src/nav_event_rcv.cpp -o C:/work/PROJ-test/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.o
当我连续两次运行此命令时,这两个.obj文件是不同的,而不仅仅是来自时间戳的几个字节.
我们正在切换构建系统,因此我们希望我们的构建与二进制兼容.我的绝大多数目标文件都是二进制相同的.一些使用__DATE__和__TIME__宏的人有几个字节不同但这一个是完全不同的!
我使用了一个elf-dump实用程序,发现两个编译之间截然不同的部分就是这个
[544] .debug_info
PROGBITS 00000000 047d70 1021ed 00 0 0 1
[00000000]:
Run Code Online (Sandbox Code Playgroud)
但我不知道PROGBITS包含什么以及为什么它包含用于连续编译的不同项目.这个网站只是声明这PROGBITS是一个属性,而不是它所指示的内容(以及为什么它对于连续编译而言是不同的).
题
如何生成.obj二元确定性?
思考
不知何故,正在编译的代码实际上正在修改的.debug_info部分.obj.这.cpp使用了一堆boost库; 这可能是原因吗?
UPDATE
我查看了生成的汇编文件,它们是不同的.从某种意义上讲,结果.obj是不同的.
仍然没有理由为什么会发生这种情况.
更新qcc上面
的命令不是执行的实际编译器命令:qcc是编译器"重定向器",它将调用与-V参数匹配的编译器."真正的"编译器调用是这样的:
C:/work/Proj/QNX_SDK/host/win32/x86/usr/lib/gcc/arm-unknown-nto-qnx6.5.0eabi/4.4.2/cc1plus -Wall -O3 -ggdb3 -DBUILD_VERSION= -DPASLOGOPTIONS=0x02 -DPASLOGAPPZONES=31,23,30,9,8,3 -DNS1_5PORT -DBOARD_TYPE=PRODUCTION -quiet -fno-builtin -fpic -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mlittle-endian -nostdinc -nostdinc++ -D__cplusplus -D__QNX__ -D__QNXNTO__ -D__GNUC__=4 -D__GNUC_MINOR__=4 -D__GNUC_PATCHLEVEL__=2 -D__NO_INLINE__ -D__DEPRECATED -D__EXCEPTIONS -D__unix__ -D__unix -D__ELF__ -fpic -DPIC=1 -D__ARM__ -D__arm__ -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -D__LITTLEENDIAN__ -D__ARMEL__ -U__ARMEB__ -frandom-seed=sadfsasafssadsa -MP -MT C:/work/Proj/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.o -MMD C:/work/Proj/N_Manag/src/bld/N_Manag//armle-v7/release/nav_event_rcv.cpp.d -isystem C:/work/Proj/QNX_SDK/target/qnx6/usr/include -isystem C:/work/Proj/QNX_SDK/host/win32/x86/usr/lib/gcc/arm-unknown-nto-qnx6.5.0eabi/4.4.2/include -isystem C:/work/Proj/QNX_SDK/target/qnx6/usr/include/cpp/c -isystem C:/work/Proj/QNX_SDK/target/qnx6/usr/include/cpp C:/work/Proj/N_Manag/src/nav_event_rcv.cpp -dumpbase C:/work/Proj/N_Manag/src/nav_event_rcv.cpp -o C:\work\Proj\nav_event_rcv.s
UPDATE
我认为看看.s装配输出是值得的,因为那里存在重大差异.
记住,我正在使用-frandom-seed.
该.s文件是1.05mil的行,并且它在〜900k行,差异开始.
剩下:
.LASF17345:
.ascii "_ZN5boost6detail7variant21make_initializer_node5app"
.ascii "lyINS_3mpl4pairINS3_INS5_INS3_INS5_INS3_INS5_INS3_I"
.ascii "NS5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_IN"
.ascii "S5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS"
.ascii "5_INS3_INS5_INS3_INS5_INS3_INS5_INS3_INS5_INS1_16in"
.ascii "itializer_rootEN4mpl_4int_ILi0EEEEENS4_6l_iterINS4_"
...
对:
.LASF17764:
.ascii"_ZNKSt8numpunctIcE13decimal_pointEv\000"
.LASF10304:
.ascii"cAlpha0\000"
.LASF10222:
.ascii"usWeek\000"
.LASF14117:
.ascii"_ZN5boost10shared_ptrI27TnRespTravelEstimationEvent"
.ascii"EaSERKS2_\000"
......
它持续了几百个字节.
现在,我仔细研究了我的超越比较,所有差异部分都是由于boost::detail::variant::make_initializer_node.这个boost函数每次都生成不同的代码吗?
解析度
原来这是一个gcc错误.我编译了我.cpp的所有排列,-O<X> -ggdb<Y>并且对于Y> = 2,汇编文件.s和对象.obj是非确定性的.
我不得不删除其他帖子...原因.
通常的罪魁祸首是宏__DATE__,__TIME__,__TIMESTAMP__其中所述编译器扩展到从系统时间计算出的值.
一种可能性是为二进制文件生成的调试信息以非确定性方式写入.例如,当编译器进程中调试信息的内存中布局不确定时,就会发生这种情况.我不知道海湾合作委员会的内部人员.但是我觉得这样的事情会发生
后一种非确定性来源通常被认为是编译器中的一个错误(例如GCC PR65015)
要强制的重现性扩张__DATE__,__TIME__和__TIMESTAMP__宏,一个人模仿和假冒的系统时间(例如,通过使用libfaketime/faketime)编译器.-Wdate-timeGCC 的命令行选项可用于在使用这些预定义宏时发出警告.
为了强制可重复的"随机性"用于GUID和修改,你可以尝试编译-frandom-seed=<somestring>哪里<somestring>是你的构建的唯一字符串(例如,你正在编译的源文件的内容的散列应该这样做).
或者,您可以尝试在没有调试信息的情况下进行编译(例如,没有-ggdbetc标志),或者稍后使用一些条带工具来删除调试信息部分.