Let's look at the following piece of code which I unintentionally wrote:
void test (){
for (int i = 1; i <=5; ++i){
float newNum;
newNum +=i;
cout << newNum << " ";
}
}
Now, this is what I happened in my head:
I have always been thinking that float newNum would create a new variable newNum with a brand-new value for each iteration since the line is put inside the loop. And since float newNum doesn't throw a compile error, C++ must be assigning some default value (huhm, must be 0). I then expected the output to be "1 2 3 4 5". What was printed was "1 3 6 10 15".
Please help me know what's wrong with my expectation that float newNum would create a new variable for each iteration?
Btw, in Java, this piece of code won't compile due to newNum not initialized and that's probably better for me since I would know I need to set it to 0 to get the expected output.
Since newNum is not initialized explicitly, it will have a random value (determined by the garbage data contained in the memory block it is allocated to), at least on the first iteration.
On subsequent iterations, it may have its earlier values reused (as the compiler may allocate it repeatedly to the same memory location - this is entirely up to the compiler's discretion). Judging from the output, this is what actually happened here: in the first iteration newNum had the value 0 (by pure chance), then 1, 3, 6 and 10, respectively.
So to get the desired output, initialize the variable explicitly inside the loop:
float newNum = 0.0;
C++ must be assigning some default
value (huhm, must be 0)
This is the mistake in your assumptions. C++ doesn't attempt to assign default values, you must explicitly initialise everything.
Most likely it will assign the same location in memory each time around the loop and so (in this simple case) newNum will probably seem to persist from each iteration to the next.
In a more complicated scenario the memory assigned to newNum would be in an essentially random state and you could expect weird behaviour.
http://www.cplusplus.com/doc/tutorial/variables/
The float you are creating is not initialised at all. Looks like you got lucky and it turned out to be zero on the first pass, though it could have had any value in it.
In each iteration of the loop a new float is created, but it uses the same bit of memory as the last one, so ended up with the old value that you had.
To get the effect you wanted, you will need to initialise the float on each pass.
float newNum = 0.0;
The mistake in thoughts you've expressed is "C++ must be assigning some default value". It will not. newNum contains dump.
You are using an uninitialized automatic stack variable. In each loop iteration it is located at the same place on the stack, so event though it has an undefined value, in your case it will be the value of the previous iteration.
Also beware that in the first iteration it could potentialliay have any value, not only 0.0.
You might have got your expected answer in a debug build but not release as debug builds sometimes initialise variables to 0 for you. I think this is undefined behaviour - because C++ doesn't auto initialise variables for you, every time around the loop it is creating a new variable but it keeps using the same memory as it was just released and doesn't scrub out the previous value. As other people have said you could have ended up with complete nonsense printing out.
It is not a compile error to use an uninitialised variable but there should usually be a warning about it. Always good to turn warnings on and try to remove all of them incase something nastier is hidden amongst them.
Using garbage value in your code invokes Undefined Behaviour in C++. Undefined Behavior means anything can happen i.e the behavior of the code is not defined.
float newNum; //uninitialized (may contain some garbage value)
newNum +=i; // same as newNum=newNum+i
^^^^^
Whoa!!
So better try this
float newNum=0; //initialize the variable
for (int i = 1; i <=5; ++i){
newNum +=i;
cout << newNum << " ";
}
C++ must be assigning some default value (huhm, must be 0).
C++ doesn't initialize things without default constructor (it may set it to something like 0xcccccccc on debug build, though) - because as any proper tool, compiler "thinks" that if you haven't provided initialization then it is what you wanted. float doesn't have default constructor, so it is unknown value.
I then expected the output to be "1 2 3 4 5". What was printed was "1 3 6 10 15".
Please help me know what's wrong with my expectation that float newNum would create a new variable for each iteration?
Variable is a block of memory. In this variable is allocated on stack. You didn't initialize it, and each iteration it just happen to be placed on the same memory address, which is why it stores previous value. Of course, you shouldn't rely on such behavior. If you want value to persist across iterations, declare it outside of loop.
Btw, in Java, this piece of code won't compile due to newNum not initialized
BTW, in C++ normal compiler would give you a warning that variable is not initialized (Example: "warning C4700: uninitialized local variable 'f' used"). And on debug build you would get crt debug error (Example: "Run-Time check failure #3 - The variable 'f' is being used without being initialized").
and that's probably better
Negative. You DO need uninitialized variables from time to time (normally - to initialize them without "standard" assignment operator - by passing into function by pointer/reference, for example), and forcing me to initialize every one of them will be a waste of my time.
I don't do too much C++ since last month, but:
The float values is newly allocated for each iteration. I'm a bit surprised about the initial zero value, though. The thing is, after each iteration, the float value runs out of scope, the next step (the reenter of the loop scope) first reallocates the float memory and this will often return the same memory block that was just freed.
(I'm waiting for any bashing :-P)
Related
I'm debugging a program that declares an array with 1024 elements and it's not initialized until much later. Every time I use "info locals" it shows me this really long list of uninitialized data. Is there any way to change the way that gdb presents uninitialized variables? Something along the lines of lot_data[1024]=UNINITIALIZED.
Is there any way to change the way that gdb presents uninitialized variables?
No.
GDB doesn't know whether a memory location has been assigned or not. To GDB it's just bits, and it can't display bits differently depending on where their value came from (which it doesn't know).
P.S. Actually tracking the state of bits is possible with instrumentation (clang -fsanitize=memory -fsanitize-memory-track-origins ...), but is a fairly expensive thing to do.
Also consider that memory can remain uninitialized despite being assigned:
int buf[5]; // uninitialized memory declared
int k = buf[0]; // k is still uninitialized
int *ip = malloc(sizeof(buf)); // uninitialized memory created
memcpy(buf, ip, sizeof(buf)); // buf is still uninitialized, despite being written to
int j = buf[0]; // j is still uninitialized
I have a piece of code:
#include <iostream>
using namespace std;
int main(){
char a[5][5] = {{'x','y','z','a','v'},{'d','g','h','v','x'}};
for(int i=0; i<2; i++){
for(int j = 0; j<6; j++)
{
cout << a[i][j];
}
}
return 0;
}
As you can see the first and second dimensions are or size 5 elements each. With the double for loop's I am just printing what is initialized for variable a.
The size of int "j", as it increases the output changes dramatically.
Why is this happen?
Does pointer is the solution to this? If yes how? If no what can we do to avoid run time errors caused by this incorrect access?
You might be treating this issue like an out-of-bounds error in Java, where the behavior is strictly defined: you'll get an ArrayIndexOutOfBoundsException, and the program will immediately terminate, unless the exception is caught and handled.
In C++, this kind of out-of-bounds error is undefined behavior, which means the compiler is allowed to do whatever silly thing it thinks will achieve the best performance. Generally speaking, this results in the compiler just blindly performing the same pointer arithmetic it would perform on array accesses that are in-bounds, regardless of whether the memory is valid or not.
In your case, because you've allocated 25 chars worth of memory, you'll access valid memory (in most environments, UB withstanding) at least until i * 5 + j >= 25, at which point any number of things could happen:
You could get garbage data off the stack
You could crash the program with a Segmentation Fault (Access Violation in Windows/Visual Studio)
The loop could refuse to terminate at the index you expect it to terminate.
That last one is an incredible bug: If aggressive loop optimization is occurring, you could get some very odd behavior when you make mistakes like this in your code.
What's almost certainly happening in the code you wrote is that that first point: though you allocated space for 25 chars, you only defined the contents of 10 of them, meaning any accesses beyond those first 10 will invoke a different kind of undefined behavior (access of an uninitialized variable), which the vast majority of the time, results in their values being filled in with whatever coincidentally was in that memory space before the variable was used.
The following code
int x;
cin >> x;
int b[x];
b[5] = 8;
cout << sizeof(b)/sizeof(b[0]) << endl << b[5];
with x inputted as 10 gives the ouput:
10
8
which seems very weird to me because:
According to http://www.cplusplus.com/doc/tutorial/arrays/ we shouldn't even be able to initialize an array using a value obtained from cin stream.
NOTE: The elements field within square brackets [], representing the number of elements in the array, must be a constant expression, since arrays are blocks of static memory whose size must be determined at compile time, before the program runs.
But that's not the whole story! The same code with x inputted as 4 sometimes gives the output
Segmentation fault. Core dumped.
and sometimes gives the output:
4
8
What the heck is going on? Why doesn't the compiler act in a single manner? Why can I assign a value to an array index that is larger than the array? And why can we even initialize an array using variable in the first place?
I initially mentioned this as a comment, but seeing how no one has answered, I'm gonna add it here.
What you have demonstrated above is undefined behavior. It means that you can't tell what will the outcome be. As Brian adds in the comments, it will result in a diagnostic message (which could be a warning). Since the compiler would go ahead anyway, it can be called UB as it is not defined in the standard.
Of the two following for loop implementations which should run faster or are they equal?
This one:
for(int i=0; i<objectPtr->bound; i++){
//do something that has no affect on objectPtr->bound
}
Or this one:
int myBound = objectPtr->bound;
for(int i=0; i<myBound; i++){
//do something that has no effect on objectPtr->bound or myBound
}
My hunch is the latter is faster but there could be some part of the compilation process that I don't understand that makes them equal in speed. I think the former will have to do an address resolution each loop cycle to determine if the value has changed.
Is there some c++ syntax that can be used to let the compiler know that the value/bound will not change. I know volatile lets the compiler know that the value will always have the possibility of changing so could I use const int for the objectPtr->bound variable to get the compiler to not always check its value each loop iteration?
The compiler might see that the value of objectPtr->bound doesn't change between iterations. In this case, it will automatically extract it into a variable to avoid repeated lookups.
There is no way to explicitly tell the compiler that the value of an expression doesn't change. If the compiler can't detect it itself, you can copy the value into a variable as you did.
Declaring local variables as const is not necessary. The compiler can see that you don't assign to the variable in a loop and deduce that its value doesn't change.
First of all, I am working in XCode C++ when I get the error. I declare a pointer variable as a constant and I set the value once. Then in the code a loop runs 3-5 times and the first time it is correct but then depending on the number of variables, the value of the coordinate changes to close to 0 (ie. 4.59163e-41). I know that the memory address does not change, just the value it holds does. Also I am working with really large amounts of data, and by that I mean between 2,000 and 20,000 coordinates. I'm sure I caused this with either a big or small problem so any help would be appreciated. Below is some of the code for the changing [not-so] constant variable:
I declare them in the header file as:
const float* m_xPointValues;
const float* m_yPointValues;
Then in the .cpp file I set them in the following function:
void ccGraphDisplay::setPointValues(float* xPointValues, float* yPointValues, unsigned numberOfPoints)
{
assert(xPointValues);
assert(yPointValues);
m_xPointValues = xPointValues;
m_yPointValues = yPointValues;
m_numberOfPoints = numberOfPoints;
....}
Then in the looping function I shift them but as far as I know this does NOT change their value:
for (unsigned i=0;i<m_numberOfPoints;++i)
{
shiftedXValue = (((m_xPointValues[i] - m_xAbsoluteMin)/(m_xAbsoluteMax-m_xAbsoluteMin))*(m_roi[2]-m_roi[0]))+m_roi[0];
shiftedYValue = (((m_yPointValues[i] - m_yAbsoluteMin)/(m_yAbsoluteMax-m_yAbsoluteMin))*(m_roi[3]-m_roi[1]))+m_roi[1];
}
To me this is a very odd error. I do not change the value of m_xPointValues or m_yPointValues anywhere else and in the largest sets of data only the end portion of the coordinates change. I also set the loop to print out the values at the beginning and end of the loop and the end is always the same as the beginning but then when the loop starts over is when the value of it changes.
Finally some of the debugging ideas I have already tried include:
1) Changing the pointer from storing floats to doubles
2) Changing the pointers to no longer be constant
3) Passing in constant values (both double and float)
Any help would be greatly appreciated (including ideas to try!).
Thanks!
This sounds like the locations pointed to by xPointValues and yPointValues, that you passed to setPointValues, do not have the same lifetime as m_xPointValues and m_yPointValues.