int& lameness()
{
int h=66;
return h;
}
int main()
{
int c;
c = lameness();
cout<<"c is "<<c<< endl;
system("pause");
return 0;
}
Why does this work? int h is a local variable and shouldnt h be destroy once it exits function scope?
If i change my function to this it works without warning. Is this safer in any way?
:
int& lameness()
{
int h=66;
int &a = h;
return a;
}
Yes. But the wonderful thing about undefined behavior is that what actually happens is... undefined. Destroying an int actually doesn't involve doing anything at all, so if nothing reuses that spot on the stack, the value is going to still be there. That's what makes this kind of thing so frustrating -- often it seems to work, until you make some small, seemingly unrelated change and it stops working!
It works by coincidence, check this:
http://www.velocityreviews.com/forums/t285367-return-reference-to-local-variable.html
Basically, it returned the right value due to the memory still being set to that value. Sometimes in the future, that might not be the case. Don't do this.
It does not work. It is undefined behavior. Your skepticism was right on: the lameness function is an error, and some compilers would flag it as such. Nonetheless, a compiler may be "conforming" and still "allow" this code...such is the "lameness" of C and C++.
It is destroyed. It happens to work because memory that h was stored in hasn't been overwritten by the time you print the value.
It only works for you by coincidence, and because your code takes a copy of the value in the reference before doing anything else. It is not guaranteed to work.
You could see it failing with:
#include <iostream>
using namespace std;
int& lameness()
{
int h=66;
return h;
}
int main()
{
int &c = lameness();
cout << "c is " << c << endl;
return 0;
}
Of course, I had to ignore compilation warnings:
x.cpp: In function ‘int& lameness()’:
x.cpp:5:13: warning: reference to local variable ‘h’ returned [enabled by default]
x.cpp: In function ‘int main()’:
x.cpp:12:28: warning: ‘h’ is used uninitialized in this function [-Wuninitialized]
The output was:
c is 0
This happens because by the time c is passed to the I/O system, the space that was once h in lameness() has been reused for other variables, thus scratching the 66 that was stored in the space. In fact, even your original code produces 0 on my machine.
Related
I've made this example to show what I'm talking about. I want to know if there is a way to run through main() without resetting value to 0.
int main(){
int value = 0;
value++;
cout << value << endl;
main();
}
Before answering the question, your example has two big problems
Calling, or even taking the address of, main is not allowed.
Your function has infinite recursion which makes your program have undefined behavior.
A different example where value is saved between calls could look like this. It uses a static variable, initialized to 0 the first time the function is called, and is never initialized again during the program execution.
#include <iostream>
int a_function() {
static int value = 0;
++value;
if(value < 100) a_function();
return value;
}
int main(){
std::cout << a_function(); // prints 100
}
If you want to keep the variable value local to the main function, you can declare it as static int value = 0;.
As has been pointed out in various comments though, recursively calling any function without an escape mechanism like you are is a bad idea. Doing it with main is a worse idea still apparently not even possible.
I am wondering what happens when you return int&. Lets jump to the example.
I have a simple class Foobar storing one int.
Lets have a look at this function:
Foobar showObjectsValue() {
Foobar b(50);
return b;
}
It returns copy of a local object so when I call this function I actually get some data instead of some trash. But when I do something like this:
Foobar& showObjectsValue() {
Foobar b(50);
return b;
}
It returns garbage because after we exit scope of the "showObjectsValue()" object "b" gets popped from the memory stack and we return reference to this popped object (correct me if I am wrong). But I don't know what is happening in case of returning int instead of object.
This function:
int& showIntegerValue() {
int i = 50;
return i;
}
and this function:
int showIntegerValue() {
int i = 50;
return i;
}
return the same value, both give me int = 50. So can someone explain what actually is going on in case of returning reference to local integer and local object?
So can someone explain what actually is going on in case of returning reference to local integer and local object?
Integers are objects. Trying to access an alias to a destroyed object is undefined behavior. Don't expect anything from it. Your compiler should even give you a warning about this:
main.cpp:4:9: warning: reference to local variable 'i' returned [-Wreturn-local-addr]
int i = 50;
In the end, when you're dealing with undefined behavior, just because you see something doesn't mean it is expected. To further prove this point, trying to run this code with GCC results in the warning above and a segmentation fault.
in following program, is output always zero, or undefined behavior?
#include<iostream>
int main()
{
int i= i ^ i ;
std::cout << "i = " << i << std::endl;
}
with gcc 4.8.0 this code success compiled, and output is 0.
int i= i ^ i ;
Since i is an automatic variable (i.e it is declared in automatic storage duration), it is not (statically) initialized yet you're reading its value to initialize it (dynamically). So your code invokes undefined behaviour.
Had you declared i at namespace level or as static, then your code would be fine:
Namespace level
int i = i ^ i; //declared at namespace level (static storage duration)
int main() {}
Or define locally but as static:
int main()
{
static int i = i ^ i; //static storage duration
}
Both of these code are fine, since i is statically initialized, as it is declared in static storage duration.
Undefined behavior. Uninitialized garbage doesn't actually have to be an unknown but valid value of the given type. On some architectures (specifically Itanium), uninitialized garbage can actually cause a crash when you try to do anything with it. See http://blogs.msdn.com/b/oldnewthing/archive/2004/01/19/60162.aspx for an explanation of how IA64's Not a Thing can mess you up.
I encountered this problem in my program which was creating problems. so let me explain it by a example:
#include<iostream>
int func(){
if(1==0) return 100;
}
int main(){
int x=99;
x= func();
std::cout<<"Value of x: " << x <<std::endl;
}
I had thought the output will be 99 but output is 0, so what's going on here?
It is causing undefined behavior. The condition is false so there is no return value from the function.
You have undefined behavior because your function is declared to return an int but the execution path through the function never reaches a return statement.
In C++ it is illegal to exit a function defined as returning a non-void type other than via a return statement with an argument.
ISO/IEC 14882:2003 6.6.3 [stmt.return] / 2:
[...] Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
From C++03 6.6.3/2 "The return statement":
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
Since your function flows "off the end", it's UB and you can expect nothing (or anything).
As a side note: this is slightly different than in C, where flowing off the end of a function that is declared to return something is not UB in itself - it becomes UB only if the caller uses the result of a function that does that.
In other words, using your example, in C++ you have UB at the moment func() returns, whether that result is assigned to x or not. In C it's UB only because you assign the result to x.
It depends on the compiler you are using.
When you compile this code, a normal compiler will cause a warning similar to:
warning C4715: 'func' : not all control paths return a value
It looks like your compiler is placing a statement that returns 0 when it doesn't find a return statement on the way out. So, x will be assigned 0.
As everyone else has said, you have undefined behavior. As for how to fix/identify it, one way would be to use warning flags when compiling your program. If you run your code in codepad, it's easy to see the issue:
http://codepad.org/MXDSniWw
cc1plus: warnings being treated as errors
In function 'int func()':
Line 5: warning: control reaches end of non-void function
In func(), your if loop is never true, but you haven't specified any other return value, so you have undefined behavior. Adding return 0; after the if.. will fix the issue.
So you expect a 99, the safest bet is to pass x by reference:
#include<iostream>
void func(int& a){
if (1==0)
a = 100;
}
int main(){
int x(99);
func(x);
std::cout << "Value of x: " << x << std::endl;
}
Given:
int i, j = 1;
Is the value of i defined? If so, what is it?
I suspect this is a duplicate, but it's somewhat hard to search for - if anyone can find it let me know.
Global variables are initialized by
default to their default values (0
for int)
Local variables are not initialized
by default
For example:
#include <iostream>
int a, b=1; // a=0, b=1
int main(void) {
int p, q=1; // p=undef, q=1
return 0;
}
proof for local variables:
#include <iostream>
int main(void) {
{
int x = 99; // change stack where a would be
}
int a, b=0;
std::cout << a << std::endl;
return 0;
}
If this code is in global scope, then i will be 0. Otherwise i is not defined.
No, it's not defined, and the compiler should complain if you try to use it, depending on the language.
If this is defining local variables then the value of i won't be defined.
The code you showed is equivalent to:
int i;
int j = 1;
that means, that i is defined, but not initialized.
i will be undefined. This leads to undefined behaviour if you try to use i without assigning it something.
Any good compiler will warn you about stuff like this. Using an undefined variable of type int might be harmless enough, but don't use undefined pointers.
Perhaps not today, but some time ago, before sufficient hardware and software protection, you could damage your machine's BIOS by using pointers with uninitialized variables.
Moral of the story: if it isn't initialized, don't use it.
The variable i can contain anything from 0 to garbage.
please refer to the following link
http://www.intap.net/~drw/cpp/cpp03_02.htm for more information
int i is a definition statement, but it is not assigned with a value.
Extern int i is declaration.