I am using g++ on Ubuntu 10.10(64-bit) if the OS is at all relevant for the matter.
I saw something strange so i decided to check and for some reason this code
#include <iostream>
int main()
{
int a;
std::cout << a << std::endl;
return 0;
}
always prints 0. Obviously g++ does auto initialization of uninitialized variables to their corresponding null-value. The thing is I want to turn that feature off, or at least make g++ show warning about using uninitialized variables, since this way my code won't work well when compiled on VS for instance. Besides I'm pretty sure the C++ standard states that a variable which isn't implicitly initialized with some value has an undefined value amongst all it's possible values, which should in fact be different with every execution of the program, since different parts of the operating memory are used every time it's executed.
Explicit question: Is there a way to make g++ show warnings for uninitialized variables?
GCC does not initialize uninitialized variables to 0. It's just a case that a is 0.
If what you want to do is to receive warnings when you use uninitialized variables you could use GCC option -Wuninitialized (also included by -Wall).
However it can't statically spot any possible usage of uninitialized variables: you'll need some run time tools to spot that, and there's valgrind for this.
You might also try to use a tool like cppcheck. In general, in well written C++ there is rarely a reason to declare a variable without initializing it.
Related
I just found this line of code within a function, which puzzles me. Can this make sense in any context or it is undefined behavior?
char * acFilename = acFilename;
EDIT: The compiler complains with Warning C4700, that I am using an uninitialized variable.
At block scope, in C++, this is undefined behaviour, as the right-hand side reads the variable the variable before it has been initialized (C++14 [dcl.init]/12).
At block scope, in C11, this could either be undefined behaviour or behave as an uninitialized variable, depending on various details of the implementation and the rest of the function, see here for detailed analysis.
At namespace scope, in C++, it is OK well-defined and makes a null pointer. This is because all static variables are zero-initialized before their initializers are considered. (C++14 [basic.start.init]/2).
At file scope in C, it is a constraint violation; static variables must have a constant expression as initializer, and the value of a variable cannot be a constant expression.
No this code does not make any sense. It's probably a typo, maybe somebody meant to use
char* acFilename = ::acFilename;
or
char* acFilename = m_acFilename;
or something else.
As it stands, it's confusing and unhelpful at best, probably a bug because somebody meant to use a different variable.
I've seen this before. Since gcc is quite trigger happy with its uninitialized variable warnings this is a trick to silence those warnings. Not sure if it's intentional design choice by gcc or the compiler just being stupid, but I've seen people do this on purpose to make gcc shut up (and in the process break the warning that might be correct in the future).
I would just replace it with an initialization to NULL. This is a bad habit, doesn't work on other compilers and a NULL can't be less correct than an indeterminate value and undefined behavior.
Just to demonstrate how this works (and also because I wanted to know if newer gcc versions still do this):
$ cat foo.c
int
foobar(void)
{
int foo;
return foo + foo;
}
$ cc -c -Wall -O2 foo.c
foo.c: In function ‘foobar’:
foo.c:6:13: warning: ‘foo’ is used uninitialized in this function [-Wuninitialized]
return foo + foo;
~~~~^~~~~
$ ed foo.c
[...]
$ cc -c -Wall -O2 foo.c
$ cat foo.c
int
foobar(void)
{
int foo = foo;
return foo + foo;
}
$ cc -c -Wall -O2 foo.c
$ cc -v
[...]
gcc version 6.2.0 20161005 (Ubuntu 6.2.0-5ubuntu12)
$
At some locations within a program, it may be possible for a variable to be in either of the following conditions:
Inputs that have been received have caused the variable to be written, and will also cause code to use its value in future.
Inputs that have been received have caused the variable not to be written, but will also cause code not to make any use of its value.
Some compilers will squawk if they see that there exist inputs which would cause a variable to not to get written, and there exist inputs which would cause the variable to be read. Even if the only input which would cause the variable to get read would also cause it to get written, the compilers may not realize that. While it would be possible to silence the compiler's complaints by unconditionally initializing the variable, machine code which initializes the variable with a value which can never actually get used would serve no functional purpose. A source code construct which would silence the compiler's complaints but not result in the compiler generating useless machine code may thus be preferable to one which would need to generate useless machine code. On some compilers, a self-initializing declaration may serve such a purpose.
If a type has trap representations, there may be no practical alternative to writing an initialization that a compiler will likely turn into useless machine code, but if a type doesn't have trap representations there is no particular reason why a quality compiler should force programmers to ask for useless code they don't want and don't need. Rather than try to have different rules for platforms where various types do and don't have trap representations, however, the authors of the Standard defer to implementers' judgments as to what sorts of behavior would be sensible on for a particular target platform and application field.
If on some platform a compiler couldn't allow programmers to omit initialization for variables which are copied but otherwise unused without having to generate likely-redundant initializations itself, it would make sense to require the programmer to include initializations in all situations that could actually occur. On another platform where copying a meaningless value would simply cause the destination to hold a meaningless value, however, it would generally make more sense to allow a programmer to omit initialization in cases where none of the copies would ever end up getting used for any real purpose. The authors of the Standard make no effort to specify what would make sense in any particular case, because they expect that people writing implementations should be capable of exercising good judgment.
The best approach for dealing with this situation would probably be to write a macro which accepts a variable, and whose expansion will initialize the variable to zero (for implementations whose authors judge that there is more value in allowing the compilers to jump the rails when an uninitialized variable is copied, even if none of the copies are really "used" for anything, than there would be in guaranteeing that the mere act of copying a variable will have no side-effects) or else do nothing (when using an implementation which will stay on the rails even without the useless initialization).
I know that Visual Studio under debugging options will fill memory with a known value.
Does g++ (any version, but gcc 4.1.2 is most interesting) have any options that would
fill an uninitialized local POD structure with recognizable values?
struct something{ int a; int b; };
void foo() {
something uninitialized;
bar(uninitialized.b);
}
I expect uninitialized.b to be unpredictable randomness; clearly a bug and easily
found if optimization and warnings are turned on. But compiled with -g only, no
warning. A colleague had a case where code similar to this worked because it
coincidentally had a valid value; when the compiler upgraded, it started failing.
He thought it was because the new compiler was inserting known values into the structure
(much the way that VS fills 0xCC). In my own experience, it was just different
random values that didn't happen to be valid.
But now I'm curious -- is there any setting of g++ that would make it fill
memory that the standard would otherwise say should be uninitialized?
Any C++ comiler can initialize any POD type to its "zero" value using the syntax:
int i = int();
float f = float();
MyStruct mys = MyStruct();
// and generally:
T t = T();
If you want to talk about debugging that's something else...
(By the way, I think VS had all uninitialized memory initialized to 0xCC when in "debug mode, so that no matter where you jump (e.g. call a bad function pointer) that's doesn't happen to be actual program code/data int3 is raised.)
I don't think such option/feature exists in gcc/g++.
For instance, all global (and static) variables reside in the .bss section, which is always initialised to zeroes. However, uninitialised ones are put in a special section within the .bss, for sake of compatibility.
If you want the them to be zeroed too, you can pass -fno-common argument to the compiler. Or, if you need it on a per-variable basis, use __attribute__ ((nocommon)).
For heap, it's possible to write your own allocator to accomplish what you described. But for stack, I don't think there's an easy solution.
I don't believe g++ will detect all cases like this, but Valgrind certainly will.
I understand that local variables are not initialised automatically in C++, so before using them, you should always assign a value to them. However, at least in simple cases, the compiler should warn you in case you forget it. I'm more or less relying on and referring to this article.
Given this program, I'd assume to get a warning when sending x to std::cout...
#include <iostream>
int main(int argc, const char * argv[])
{
int x;
std::cout << x;
return 0;
}
...but no warning pops up. If, however, I run the static analyzer, I do get the expected warning: Function call argument is an uninitialized value.
I compile & run using Xcode 5.1 with the Apple LLVM 5.1 compiler. I use the standard build settings from Xcode's command line project template (C++), the language dialects are set to GNU99 (for C) and GNU++11 (C++).
The Uninitialized Variables option is set to Yes (Aggressive) (-Wconditional-uninitialized). Switching to just Yes (-Wuninitialized) raises the warning: Variable 'x' is uninitialized when used here. Question Part 1: Why does the warning not show with the default setting (-Wconditional-uninitialized)? The documentation in Xcode suggests that the aggressive option finds more issues:
You can toggle between the normal uninitialized value checking or the more aggressive (conservative) checking which finds more issues but the checking is much stricter.
Strangely enough, when I run the program, the value is always set to 0, so for some reason, it seems to be initialised. Question Part 2: Why is that?
Why not the warning?
Using clang with -Wall on my system correctly warns about the error. Apparently, the default settings do not include -Wall (may be to avoid generating warnings with correct code that was written before some of the warnings were introduced).
In general, you're however going to be in trouble if you rely on the compiler to help you with sloppy programming. Typing in code without thinking carefully and hoping the compiler will tell you all mistakes is bad in any language but a true total disaster with C++. The main philosophy of C++ is simply that the programmer doesn't make any error, so just don't make them ;-)
Think carefully and also always work with -Wall if you can.
Why is initialized?
Apparently, you've not understood what is the meaning of "undefined behavior". It doesn't mean the program crashes, it doesn't mean it will do anything funny. It means it can do anything and normally the programs do whatever will create the most problems for you in the future.
Often this most dangerous behavior is to make it look as if everything is fine (e.g. that your variable is indeed initialized). The bad values will only show once you put that code in production or only when you show your program running in front of a vast audience. At that point, the value will be different and the video of your public crash will go viral on youtube, your wife will change the door locks and even your parents will not answer your phone calls.
Just initialize your variables; it's better :-)
It's necessary but enough to turn on -Wall to make our code safe.
e.g. The following code, under MacOS's g++(it's clang) will print out 0, but it is definitely a UB:
#include <stdio.h>
#include <iostream>
using namespace std;
class Blob {
public:
int age;
void hello() { printf("hello\n"); }
};
int main() {
Blob a;
//a.hello();
cout << a.age << endl;
return 0;
}
I am new to C++ (just starting). I come from a Java background and I was trying out the following piece of code that would sum the numbers between 1 and 10 (inclusive) and then print out the sum:
/*
* File: main.cpp
* Author: omarestrella
*
* Created on June 7, 2010, 8:02 PM
*/
#include <cstdlib>
#include <iostream>
using namespace std;
int main() {
int sum;
for(int x = 1; x <= 10; x++) {
sum += x;
}
cout << "The sum is: " << sum << endl;
return 0;
}
When I ran it it kept printing 32822 for the sum. I knew the answer was supposed to be 55 and realized that its print the max value for a short (32767) plus 55. Changing
int sum;
to
int sum = 0;
would work (as it should, since the variable needs to be initialized!). Why does this behavior happen, though? Why doesnt the compiler warn you about something like this? I know Java screams at you when something isnt initialized.
Thank you.
Edit:
Im using g++. Here is the output from g++ --version:
Im on Mac OS X and am using g++.
nom24837c:~ omarestrella$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646)
Reading from an uninitialized variable results in undefined behavior and the compiler isn't required to diagnose the error.
Note that most modern compilers will warn you if you attempt to read an uninitialized variable. With gcc you can use the -Wuninitialized flag to enable that warning; Visual C++ will warn even at warning level 1.
Because it's not part of the C++ standard. The variable will just take whatever value is currently sitting in the memory it's assigned. This saves operations which can sometimes be unnecessary because the variable will be assigned a value later.
It's interesting to note and very important for Java/.Net programmers to note when switching to C/C++. A program written in C++ is native and machine-level. It is not running on a VM or a some other sort of framework. It is a collection of raw operations (for the most part). You do not have a virtual machine running in the background checking you variables and catching exceptions or segfaults for you. This is a big difference which can lead to a lot of confusion in the way C++ handles variables and memory, as opposed to Java or a .Net language. Hell, in .Net all your integers are implicitly initialised to 0!
Consider this code fragment:
int x;
if ( some_complicated_condition ) {
x = foo;
} else if ( another_condition ) {
// ...
if ( yet_another_condition ) x = bar;
} else {
return;
}
printf("%d\n",x);
Is x used uninitialized? How do you know? What if there are preconditions to the code?
These are hard questions to answer automatically, and enforcing initialization might be inefficient in some small way.
In point of fact modern compilers do a pretty good job of static analysis and can often tell if a variable is or might be used uninitialized, and they generally warn you in that case (at least if you turn the warning level up high enough). But c++ follows closely on the c tradition of expecting the programmer to know what he or she is doing.
It's how the spec is defined--that uninitialized variables have no guarantee's, and I believe the reason is that it has to do with optimizations (though I may be wrong here...)
Many compilers will warn you, depending on the warning level used. I know by default VC++ 2010 warns for this case.
What compiler are you using? There is surely a warning level you can turn on via command-line switch that would warn you of this. Try compiling with /W3 or /W4 on Windows and you'll get 4700 or 6001.
This is because C++ was designed as a superset of C, to allow easy upgrading of existing code. C works that way because it dates back to the 70s when CPU cycles were rare and precious things, so weren't wasted initialising variables when it might not be necessary (also, programmers were trusted to know that they'd have to do it themselves).
Obviously that wasn't really the case once Java appeared, so they found it a better tradeoff to spend a few CPU cycles to avoid that class of bugs. As others have noted though, modern C or C++ compilers will normally have warnings for this kind of thing.
Because C developers care about speed. Uselessly initializing a variable is a crime against performance.
Detecting an uninitialized variable is a Quality-of-Implementation (QoI) issue. It is not mandatory, since the language standard does not require it.
Most compilers I know will actually warn you about the potential problem with an initialized variable at compile-time. On top of that, compilers like MS Visual Studio 2005 will actually trap the use of an uninitialized variable during run-time in debug builds.
So, what compiler are you using?
Well, it depends on what compiler you use. Use a smart one. :)
http://msdn.microsoft.com/en-us/library/axhfhh6x.aspx
Initialising variables is one of the most important tenets of C/C++. Any types without a constructor should be initialised, period. The reason for compiler not enforcing this is largely historical. It stems from the fact sometimes it's not necessary to init something and it would be wasteful to do so.
These days this sort of optimisation is best left to compiler and it's a good habit to always initialise everything. You can get the compiler to generate a warning for you as others suggested. Also you can make it treat warnings as errors to further simulate javac behaviour.
C++ is not a pure object oriented programming language.
In C++ there is no implicit way of memory management and variable initialization.
If a variable is not initialized in C++ then it may take any value at runtime because the compiler does not understand such internal errors in C++.
I know that Visual Studio under debugging options will fill memory with a known value.
Does g++ (any version, but gcc 4.1.2 is most interesting) have any options that would
fill an uninitialized local POD structure with recognizable values?
struct something{ int a; int b; };
void foo() {
something uninitialized;
bar(uninitialized.b);
}
I expect uninitialized.b to be unpredictable randomness; clearly a bug and easily
found if optimization and warnings are turned on. But compiled with -g only, no
warning. A colleague had a case where code similar to this worked because it
coincidentally had a valid value; when the compiler upgraded, it started failing.
He thought it was because the new compiler was inserting known values into the structure
(much the way that VS fills 0xCC). In my own experience, it was just different
random values that didn't happen to be valid.
But now I'm curious -- is there any setting of g++ that would make it fill
memory that the standard would otherwise say should be uninitialized?
Any C++ comiler can initialize any POD type to its "zero" value using the syntax:
int i = int();
float f = float();
MyStruct mys = MyStruct();
// and generally:
T t = T();
If you want to talk about debugging that's something else...
(By the way, I think VS had all uninitialized memory initialized to 0xCC when in "debug mode, so that no matter where you jump (e.g. call a bad function pointer) that's doesn't happen to be actual program code/data int3 is raised.)
I don't think such option/feature exists in gcc/g++.
For instance, all global (and static) variables reside in the .bss section, which is always initialised to zeroes. However, uninitialised ones are put in a special section within the .bss, for sake of compatibility.
If you want the them to be zeroed too, you can pass -fno-common argument to the compiler. Or, if you need it on a per-variable basis, use __attribute__ ((nocommon)).
For heap, it's possible to write your own allocator to accomplish what you described. But for stack, I don't think there's an easy solution.
I don't believe g++ will detect all cases like this, but Valgrind certainly will.