#include <iostream>
int main(int argc, char** args) {
int foo = foo + 4;
std::cout << foo << std::endl;
}
And a follow up question, is there a compiler flag to stop this sort of thing? I found -Wall works sometimes, better would be to prevent it entirely.
还有一个跟进问题,是否有一个编译器标志来阻止这种事情?我发现-Wall有时会工作,最好是完全防止它。
My compiler:
g++ -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
5 个解决方案
#1
31
No there is no guaranteed way to stop this sort of thing. It is an integral part of C++ and C that the variable's name is visible in its initializer. It allows you to do such things as
没有任何保证的方法可以阻止这种事情。它是C ++和C的组成部分,变量的名称在其初始化程序中可见。它允许你做这样的事情
T *t = malloc(sizeof(*t));
There is an issue report on the C++ issues list to require diagnostics in simple cases, but currently compilers are not required to diagnose your case.
有关C ++问题列表的问题报告要求在简单情况下进行诊断,但目前编译器不需要诊断您的案例。
It's also valid in a different context.
它在不同的环境中也有效。
Edit: To clarify - the behavior of your snippet is undefined: You are reading the value of a not initialized variable. That compilers are not required to diagnose this does not mean that behavior is defined.
编辑:澄清 - 您的代码段的行为未定义:您正在读取未初始化变量的值。编译器不需要诊断这并不意味着定义了行为。
#2
6
int foo = foo + 4;
This is undefined behavior. Some compilers zero out automatically the space for local variables when others may not, so foo might contain stack's rubbish
这是未定义的行为。当其他编译器可能没有时,一些编译器会自动将空间置零,因此foo可能包含堆栈的垃圾
#3
3
I can bet this means undefined behaviour.
我敢打赌这意味着未定义的行为。
Edit: see the citation from answer to another question.
编辑:请参阅另一个问题的答案引文。
Edit: most probably, the value in the RHS is taken from uninitialized memory location in the stack, 4 is added to it and the result is used for initialization.
编辑:最有可能的是,RHS中的值取自堆栈中未初始化的内存位置,添加了4,结果用于初始化。
#4
2
To get a warning from gcc for this particular code, you need -Wuninitialized
(-Wall
includes this) and -O
(or any optimization level above 0).
要从gcc获取此特定代码的警告,您需要-Wuninitialized(-Wall包括此)和-O(或任何高于0的优化级别)。
The reason is that gcc can't diagnose use of uninitialized variables unless it does data flow analysis, and it doesn't do data flow analysis when optimization is disabled. And optimization is disabled by default.
原因是gcc不能诊断未初始化变量的使用,除非它进行数据流分析,并且在禁用优化时不进行数据流分析。默认情况下禁用优化。
#5
0
I would expect any half-way decent compiler to issue a warning for int foo = foo + 4; in its default configuration. Good ones will have options to reject it entirely as "use of uninitialised variable" and/or to accept any specific occurence of it where the programmer understands exactly what's going on and isn't concerned about unexpected behaviour.
我希望任何中途正常的编译器都会发出int foo = foo + 4的警告;在其默认配置中。好的人可以选择完全拒绝它作为“使用未初始化的变量”和/或接受任何特定的事件发生在程序员确切知道发生了什么并且不关心意外行为的情况下。
I for example often used to write int toggle = toggle ^ 1 back in the days when compilers weren't so fussy, if all I wanted was a toggling switch where I didn't care whether it started TRUE or FALSE. Nowadays I'd probably write static bool toggle=TRUE; toggle=^toggle
例如,我常常在编译器不那么繁琐的时候写int toggle = toggle ^ 1,如果我想要的只是一个切换开关,我不关心它是否开始为TRUE或FALSE。现在我可能会写静态bool toggle = TRUE;肘节= ^肘节
#1
31
No there is no guaranteed way to stop this sort of thing. It is an integral part of C++ and C that the variable's name is visible in its initializer. It allows you to do such things as
没有任何保证的方法可以阻止这种事情。它是C ++和C的组成部分,变量的名称在其初始化程序中可见。它允许你做这样的事情
T *t = malloc(sizeof(*t));
There is an issue report on the C++ issues list to require diagnostics in simple cases, but currently compilers are not required to diagnose your case.
有关C ++问题列表的问题报告要求在简单情况下进行诊断,但目前编译器不需要诊断您的案例。
It's also valid in a different context.
它在不同的环境中也有效。
Edit: To clarify - the behavior of your snippet is undefined: You are reading the value of a not initialized variable. That compilers are not required to diagnose this does not mean that behavior is defined.
编辑:澄清 - 您的代码段的行为未定义:您正在读取未初始化变量的值。编译器不需要诊断这并不意味着定义了行为。
#2
6
int foo = foo + 4;
This is undefined behavior. Some compilers zero out automatically the space for local variables when others may not, so foo might contain stack's rubbish
这是未定义的行为。当其他编译器可能没有时,一些编译器会自动将空间置零,因此foo可能包含堆栈的垃圾
#3
3
I can bet this means undefined behaviour.
我敢打赌这意味着未定义的行为。
Edit: see the citation from answer to another question.
编辑:请参阅另一个问题的答案引文。
Edit: most probably, the value in the RHS is taken from uninitialized memory location in the stack, 4 is added to it and the result is used for initialization.
编辑:最有可能的是,RHS中的值取自堆栈中未初始化的内存位置,添加了4,结果用于初始化。
#4
2
To get a warning from gcc for this particular code, you need -Wuninitialized
(-Wall
includes this) and -O
(or any optimization level above 0).
要从gcc获取此特定代码的警告,您需要-Wuninitialized(-Wall包括此)和-O(或任何高于0的优化级别)。
The reason is that gcc can't diagnose use of uninitialized variables unless it does data flow analysis, and it doesn't do data flow analysis when optimization is disabled. And optimization is disabled by default.
原因是gcc不能诊断未初始化变量的使用,除非它进行数据流分析,并且在禁用优化时不进行数据流分析。默认情况下禁用优化。
#5
0
I would expect any half-way decent compiler to issue a warning for int foo = foo + 4; in its default configuration. Good ones will have options to reject it entirely as "use of uninitialised variable" and/or to accept any specific occurence of it where the programmer understands exactly what's going on and isn't concerned about unexpected behaviour.
我希望任何中途正常的编译器都会发出int foo = foo + 4的警告;在其默认配置中。好的人可以选择完全拒绝它作为“使用未初始化的变量”和/或接受任何特定的事件发生在程序员确切知道发生了什么并且不关心意外行为的情况下。
I for example often used to write int toggle = toggle ^ 1 back in the days when compilers weren't so fussy, if all I wanted was a toggling switch where I didn't care whether it started TRUE or FALSE. Nowadays I'd probably write static bool toggle=TRUE; toggle=^toggle
例如,我常常在编译器不那么繁琐的时候写int toggle = toggle ^ 1,如果我想要的只是一个切换开关,我不关心它是否开始为TRUE或FALSE。现在我可能会写静态bool toggle = TRUE;肘节= ^肘节