Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 是一个C++;编译器是否允许在编译同一程序时发出不同的机器代码?_C++_Compiler Construction_Compilation - Fatal编程技术网

C++ 是一个C++;编译器是否允许在编译同一程序时发出不同的机器代码?

C++ 是一个C++;编译器是否允许在编译同一程序时发出不同的机器代码?,c++,compiler-construction,compilation,C++,Compiler Construction,Compilation,考虑一种情况。我们有一些特定的C++编译器,一组特定的编译器设置和一个特定的C++程序。 我们使用该编译器和这些设置编译特定程序两次,每次都进行“干净编译” 发出的机器代码应该是相同的(我不是指时间戳和其他提示,我是指将要执行的真正代码)还是允许在不同的编译中有所不同?我敢打赌,由于某些元数据编译器写入,每次都会有所不同(例如,c#编译的DLL总是在某些字节中变化,即使我在一行中“构建”了两次而没有任何更改)但是无论如何,我永远不会相信它不会改变。< P> C++标准当然没有说什么来阻止这种情况

考虑一种情况。我们有一些特定的C++编译器,一组特定的编译器设置和一个特定的C++程序。 我们使用该编译器和这些设置编译特定程序两次,每次都进行“干净编译”


发出的机器代码应该是相同的(我不是指时间戳和其他提示,我是指将要执行的真正代码)还是允许在不同的编译中有所不同?

我敢打赌,由于某些元数据编译器写入,每次都会有所不同(例如,c#编译的DLL总是在某些字节中变化,即使我在一行中“构建”了两次而没有任何更改)但是无论如何,我永远不会相信它不会改变。

< P> C++标准当然没有说什么来阻止这种情况发生。然而,实际上,编译器通常是确定性的,所以给定相同的输入,它将产生相同的输出。 真正的问题主要是它认为环境的哪些部分是它的输入——有一些似乎认为构建机器的特性反映了目标的特性,并根据“输入”改变它们的输出在构建环境中是隐式的,而不是显式的,例如通过编译器标志。也就是说,即使这样也相对不常见。标准是输出依赖于显式输入(输入文件、命令行标志等)


顺便说一句,我只能想到一件相当明显的事情,那就是“自发地”改变:一些编译器和/或链接器在其输出文件中嵌入时间戳,因此输出文件的几个字节将从一个版本更改为下一个版本--但这只会出现在文件中嵌入的元数据中,而不会更改生成的实际代码。

不能保证它们是相同的。根据

当我编译和重新编译同一个源代码时,我的可执行文件有时会不同。这正常吗?

是的,默认情况下,~MinGW的GCC不会生成一致的输出,除非您对其进行修补

编辑:发现它似乎解释了如何使它们相同。

根据标准中的假设规则,只要符合程序(例如,没有未定义的行为)不能区分两者之间的区别,编译器可以做任何它想做的事情。换句话说,只要程序产生相同的输出,标准中就没有禁止这一点的限制


从实用的角度来看,我不会使用这样的编译器来构建生产软件。我希望能够重新编译两年前发布的版本(使用相同的编译器,等等)并产生相同的机器代码。我不想担心我不能重现错误的原因是编译器今天决定做一些稍微不同的事情。

尼尔·巴特沃斯(Neil Butterworth)对同一问题给出了答案。IIRC,他解释了为什么即使一切看起来都一样,编译器也能产生不同的输出。我试图这听起来像是一个骗人的问题;)如果编译器在某些情况下使用统计算法,那么是的,它可以生成稍微不同的代码,即使用替代寄存器或代码布局。该标准是否说明了机器代码?不那么,任何保留标准中指定语义的输出都是允许的。Ergo:是的。你的编译器是否设置了随机化函数地址以防止有针对性的缓冲区溢出攻击?对于一个发明了动态优化的非确定性编译器,我会给出什么样的设置。Visual Studio提供了配置文件引导优化。我遵循了链接,但没有解释原因@martin York用另一个链接更新了我的帖子,使它们保持一致。出于许多目的,编译器的输出是完全确定的,即使它不是最优的,也是很有用的。例如,如果一个人正在为一台开源投票机编译代码,那么他应该使用一个开源交叉编译器,无论编译器本身在什么环境下运行,它都将始终产生位相同的输出。如果通过几个独立的方法从源代码引导的编译器版本都生成相同的代码,那么这将非常强烈地暗示编译器没有隐藏任何不在源代码中的“gotchas”。