简体   繁体   English

为什么GCC / Clang在不同情况下的初始化行为不同?

[英]Why GCC/Clang behaves differently on initialization in different cases?

I tried the following versions of codes with both GCC and Clang/LLVM: 我在GCC和Clang / LLVM中尝试了以下版本的代码:

Version 1 版本1

#include <stdio.h>    
main() {
    work();
    return 0;
}
work() {
    int b;
    printf("b: %d \n", b);
}

Version 2 版本2

#include <stdio.h>    
main() {
    work();
    return 0;
}
work() {
    int a = 1;
    int b;
    printf("a: %d b: %d \n", a, b);
}

Version 3 版本3

#include <stdio.h>    
void work() {
    int a = 1;
    int b;
    printf("a: %d b: %d \n", a, b);
}
int main(int argc, char** argv) {
    work();
    return 0;
}

For GCC, 对于GCC,

Version 1 outputs b: 0 . 版本1输出b: 0

Version 2 outputs a: 1 b: 4195728 . 版本2输出a: 1 b: 4195728

Version 3 outputs a: 1 b: 1742650088 . 版本3输出a: 1 b: 1742650088

For Clang (LLVM), 对于Clang (LLVM),

Version 1 outputs b: 0 . 版本1输出b: 0

Version 2 outputs a: 1 b: -1643302816 . 版本2输出a: 1 b: -1643302816

Version 3 outputs a: 1 b: 0 . 版本3输出a: 1 b: 0

I ran the same codes on several machines many times. 我多次在几台机器上运行相同的代码。 The ones produced "0" always produced "0", that is, in these cases, b was initialized. 产生“ 0”的位总是产生“ 0”,即在这种情况下, b被初始化。

Questions: 问题:

  1. What makes the GCC and Clang always produce "0" in version 1? 是什么使GCC和Clang在版本1中始终产生“ 0”?

  2. What makes Clang always produce "0" in Version 3? 是什么使Clang在版本3中始终产生“ 0”?

Reading a variable that is never initialized and for which the address is never taken has undefined behavior. 读取永不初始化且永不使用其地址的变量具有未定义的行为。 That means that a compiler implementor can chose whatever pleases. 这意味着编译器实现者可以随意选择。 So if you'd really interested ask the implementors directly, not us. 因此,如果您真的有兴趣直接询问实施者,而不是我们。 But as Pascal suggests, I don't think that they will be much interested in your question, and I doubt also that you might find anything interesting about that in their documentation. 但是正如Pascal所建议的那样,我认为他们不会对您的问题很感兴趣,并且我还怀疑您是否会在他们的文档中发现任何有趣的东西。 But since these are open source compilers you may look into the sources to see what they are doing. 但是,由于这些是开放源代码编译器,因此您可以查看源代码以查看它们在做什么。

In essence you can't expect anything sensible from your code. 本质上,您不能指望代码中有任何明智的选择。

If you are seriously be interested in your compilers and what they have to tell you, switch on at least some warnings for your code (use -Wall ). 如果您对编译器以及编译器要告诉您的东西很感兴趣,请至少为代码打开一些警告(使用-Wall )。 The first two versions that you have are not even C according to modern standards. 根据现代标准,您拥有的前两个版本甚至都不是C。

You are accessing uninitialized variable b. 您正在访问未初始化的变量b。 The C++ standard does not specify what the value will be when you read it. C ++标准未指定读取值时的值。 It can be different on different runs of the same compiled binary. 在同一编译二进制文件的不同运行中,它可能会有所不同。 It all depends what was at the place of memory where the variable "b" will be. 这完全取决于变量“ b”在内存中的位置。 The compiler won't initialize it to any value. 编译器不会将其初始化为任何值。

In fact I believe this is an "undefined" behavior, which is totally undefined and a compiler, which would format your hard drive or crash the app or crash the OS when this happens would be a valid, standard compliant C++ compiler. 实际上,我相信这是“未定义”的行为,完全是未定义的行为,而编译器将是有效的,符合标准的C ++编译器,它将格式化硬盘或使应用程序崩溃或使OS崩溃。

So in short: Don't read uninitialized variables and never expect what value you read when you do that. 简而言之:不要读取未初始化的变量,也不要期望这样做时会读取什么值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM