C++ and storage allocation questions

Started by
4 comments, last by noatom 10 years, 11 months ago

According to one of my books,the following code should not work:


void f(){
	int ma;
	cin >> ma;
	if(ma == 10)
		goto heya;

	int x;
heya:
	cout << "a";
}

Why? Because the storage for x is allocated at the beginning of the code block,but if I type 10,then it will jump to heya,so,it will skip the definition,thus constructor call.

The code should generate a warning,or an error,but I got none.

The code + explanation is from Thinking in C++.

Is that concept still correct,or outdated?

Advertisement
The concept is fine, but the specifics are a bit off. Try initializing x - that should generate a warning.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I initialized x,and still nothing.

What level are you compiling this at because if any optimisations are on the compiler will just ignore the declaration of "x" as it can tell you are never going to use it. And even then the CPU can shift all of these instructions around if it likes so there is no way to say for certain it won't just initialise x at the beginning of the function or even at all.

All you will get when initialising the parameter is a initialised but unused variable detected warning which is what I expected anyway, and that is in a debug build with no optimisations on btw.

A compiler is allowed to change your code as long as the instruction that make it into the executable have the same behaviour as what you expressed in the code. So it is very likely you are just running into a compiler transformation that makes the code more efficient to execute. If you are interested in knowing more about these kind of transformations you should watch this as it explains what the compiler and CPU are allowed to do in the face of multithreading and it's barriers(semaphore, mutex, critical section): http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, theHunter, theHunter: Primal, Mad Max, Watch Dogs: Legion

What level are you compiling this at because if any optimisations are on the compiler will just ignore the declaration of "x" as it can tell you are never going to use it. And even then the CPU can shift all of these instructions around if it likes so there is no way to say for certain it won't just initialise x at the beginning of the function or even at all.

All you will get when initialising the parameter is a initialised but unused variable detected warning which is what I expected anyway, and that is in a debug build with no optimisations on btw.

A compiler is allowed to change your code as long as the instruction that make it into the executable have the same behaviour as what you expressed in the code. So it is very likely you are just running into a compiler transformation that makes the code more efficient to execute. If you are interested in knowing more about these kind of transformations you should watch this as it explains what the compiler and CPU are allowed to do in the face of multithreading and it's barriers(semaphore, mutex, critical section): http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2

There's more to it than just preserving the observed behavior; it has to compile with respect to rules defined by the language. Any optimization, such as removing unused variables, has to be performed at a later stage.

For example, the language states that it is illegal to jump past an initialization. And, if you use Visual Studio and disable language extensions (VS allows jumping past initialization by default, it has to be explicitly disabled), then the compiler indeed generates an error saying that the jump skips initialization of the variable. Without initialization, the jump is fine according to the language and the compiler doesn't complain. So the error is generated, because that is how the language is defined, even if the variable is unused and will be removed at a later optimization stage.


class X { 
public: 
X(); 
}; 

X::X() {} 

void f(int i) { 

if(i < 10) { 
//! goto jump1; // Error: goto bypasses init 
} 
X x1; // Constructor called here 
jump1: 

switch(i) { 
case 1 : 
X x2; // Constructor called here 
break; 

//! case 2 : // Error: case bypasses init 
X x3; // Constructor called here 
break; 
} 
} 

In the code above, both the gotoand the switchcan potentially jump past the sequence point where a constructor is called. That object will then be in scope even if the constructor hasn’t been called, so the compiler gives an error message. This once again guarantees that an object cannot be created unless it is also initialized

This topic is closed to new replies.

Advertisement