How does the this c++ code work [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Here is the code
int& fun(){
static int x = 10;
return x;
}
int main() {
fun() = 30;
cout<< fun();
getch();
}
The output is 30.
How does this work?

Let's read it line by line:
int& fun()
declares a function named fun which returns a reference to an integer variable
{
static int x = 10;
The x variable is static inside this function. A special place in memory is reserved for it and is initialized with 10. Every time this function is called x will get the value stored in that special location.
return x;
}
We return x and leave the function. Let's go to the main one:
int main()
{
fun() = 30;
Remember that fun returns the reference to an int. Here we modify the integer to be 30. Since this integer has static allocation every time fun will be called from now on x will start with 30, unless other changes are made.
cout<< fun();
Since x is 30 that's what you get.
getch();
}
Suggestion: use GDB and trace the program's execution step-by step:
$ gdb ./a.out
(gdb) b main
Breakpoint 1 at 0x40077b: file 1.cpp, line 11.
(gdb) r
Starting program: /tmp/a.out
Breakpoint 1, main () at 1.cpp:11
11 fun() = 30;
We start GDB, set a breakpoint at the begining of main and start the program.
(gdb) disp fun()
1: fun() = (int &) #0x60104c: 10
Since fun returns a reference to a static variable I can display it's value at each step in GDB.
(gdb) s
fun () at 1.cpp:6
6 return x;
1: fun() = (int &) #0x60104c: 10
Running a single step we see that we are in func. This is the place where x is returned (as a reference) to be attributed 30.
(gdb) n
7 }
1: fun() = (int &) #0x60104c: 30
Indeed, after leaving the function, x is 30.
(gdb)
main () at 1.cpp:13
13 cout<< fun();
1: fun() = (int &) #0x60104c: 30
(gdb) s
fun () at 1.cpp:6
6 return x;
1: fun() = (int &) #0x60104c: 30
(gdb)
7 }
1: fun() = (int &) #0x60104c: 30
(gdb)
main () at 1.cpp:15
15 }
1: fun() = (int &) #0x60104c: 30
(gdb) q
We continue the program's execution and leave GDB (though your question is already answered).

It is straightforward : fun returns the reference to the static variable inside the function, which is assigned to 30 by this line:
fun() = 30;
this means, x inside the function is changed to 30. What is more? It is 30! You print it by calling again fun() in the next line.
Note that a static variable lives till the end of the program: it is not destroyed even if the function returns!

The fun function returns a reference-to an int type. This way, when you call fun() = 30, you actually set x to 30.
This way when you print it out, the fun function will no longer set it, cause that is a one-off declaration.

Related

How can I create threads by calling functions from a class? [duplicate]

This question already has answers here:
Start thread with member function
(5 answers)
Closed 4 years ago.
Suppose there's
class concurr{
public:
double arr[100];
void func1(vector<vector<double>> data,int x);
double func2(vector<vector<double>> data);
}
such that func2 takes in "data" and feeds it to func1 with the same "data" but varying numbers of x as it goes from 0 to up to 100. Then in func1, it calculates something and whatever the double value it comes out, fills it up for arr[x] So basically, the func2 looks generally like
double concurr::func2(vector<vector<double>> data){
thread threads[100];
for (int x = 0; x < 100; x++){
threads[x] = thread(concurr::func1,data,x); // this line is where the problem is
}
for (auto& th : threads){
th.join();
}
// ..... does something with the arr[100].... to come up with double = value
return value;
}
and without the multithreading part, the code runs well, it's just that with the added multithreading part, when I try to compile, it says
"reference to non-static member function must be
called"
When calling member function with a thread you need to pass an object of the class or a ref to it (in your case itself):
threads[x] = thread(concurr::func1, *this,data,x);
Or use a lambda
threads[x] = thread( [&]{ this->func1(data, x); } )

GDB breakpoint on function arguments

Can we set a GDB breakpoint on a function such that it will break into only if the function argument matches the value specified?
Ex
int foo(int i) {
return i*i;
}
int main() {
foo(0);
................
foo(9);
}
How do I set a breakpoint on foo only when the argument i of foo is 5?
Sure, use "break if"
break foo if i == 5
If you have multiple variable if need to break on, just use classic if syntax :
break foo if i == 5 && j == 3

"this" pointer pushed lexically last instead of first

I have a problem with compiling some code for mingw32, linking a mingw32-compiled library. When I call a member function (i.e. constructor) of a class in the library that I am dynamically linking to, the arguments are pushed onto the stack in the wrong order.
Here's an example:
Program received signal SIGSEGV, Segmentation fault.
0x65e717e9 in TCODMap::TCODMap (this=0x40, width=48, height=40)
at src/fov.cpp:28
28 src/fov.cpp: No such file or directory.
(gdb) backtrace
#0 0x65e717e9 in TCODMap::TCODMap (this=0x40, width=48, height=40)
at src/fov.cpp:28
#1 0x00401bda in map::map (this=0x8683c8, dim=..., fill=0 '\000')
at src/map.cpp:12
#2 0x004017d7 in next_init () at src/main.cpp:24
#3 0x00401b8e in main (argc=1, argv=0x862fc8) at src/main.cpp:98
My call to the TCODMap constructor has the arguments width=64 and height=48, however notably the this implicit argument is set to 64 (0x40), the width is set to 48, and the height is set to some garbage value 40. In this case, the constructor is called as part of an initializer for another class that I have in my user code.
The code in question:
map::map(loc dim, uint8 fill) : _dim(dim), tcodmap(_dim.x, _dim.y), actors()
{
_size = _dim.x * _dim.y;
_data = new uint8[_size];
for (int xi = 0; xi < _dim.x; xi++)
{
for (int yi = 0; yi < _dim.y; yi++)
{
put(xi, yi, fill);
}
}
}
It seems the thiscall calling convention, which says the this pointer should be pushed last onto the stack such that it is lexically first in the argument list, is not being obeyed correctly.
How do I fix this?
I wrote a test program to check what you trying to do. 1st of all you are getting the error at run time and not at compile time as you have provided a stack trace of gdb.
#include <iostream>
struct Data{
int _x;
int _y;
};
class A{
public:
A(){}
A(int x){}
A(const A&,int y){}
A(int x , int y)
{
}
};
class B{
Data _d;
A _a;
public:
B(Data d,int fill):_d(d),_a(_d._x,_d._y)
{
}
};
int main()
{
Data d;
d._x=1;
d._y=2;
B instance(d,4);
return 0;
}
Stacktrace:
> Breakpoint 1, B::B (this=0x7fffffffe1a0, d=..., fill=4) at this.cpp:26
> 26 B(Data d,int fill):_d(d),_a(_d._x,_d._y) (gdb) s A::A
> (this=0x7fffffffe1a8, x=1, y=2) at this.cpp:17 17 } (gdb) bt
> #0 A::A (this=0x7fffffffe1a8, x=1, y=2) at this.cpp:17
> #1 0x00000000004006fb in B::B (this=0x7fffffffe1a0, d=..., fill=4)
> at this.cpp:26
> #2 0x0000000000400652 in main () at this.cpp:39
Point here is that the 'this' implicit pointer would point to a valid address until unless your program is causing "stack buffer overflow" which corrupts the memory assigned to 'this' pointer for tcodmap.
You should share more details of complete code, how you use this program.
Do you experince this issue at every run or is it random?

can anyone explain the output?

Can anyone explain the output?
#include<iostream>
using namespace std;
int &fun(){
static int x = 10;
return x;
}
int main(){
fun() = 30;
cout << fun();
return 0;
}
output is 30
That's how static locals work - they persist the value between the function calls. Basically fun() has a static local and returns a reference to it, the effect is roughly the same as you would have with a global variable.
You return the static by reference, so when you do fun() = 30 you change it.
It's pretty clear, no?
Basically, foo() returns a reference to x.
When you call fun()a static variable is created and you return the reference to it. Basically, because of the static, the variable is not destroyed even if you exit the scope of the function. You affect the reference with 30 and then recalling the function you get 30 (the x at the second call is exactly the same at the first call). Basically the static works like a global variable in this case.
AS fun is the reference to the function so when you write this line
fun() = 30; it stores 30 in its return value i.e x, that is why you are getting the output as 30.

How does backtrace work?

#include <iostream>
using namespace std;
class dummyA
{
int x;
public:
dummyA ()
{
x = 0;
}
void test ()
{
x++;
}
};
int main ()
{
cout << "\nG'Morning";
dummyA obj;
obj.test ();
return 0;
}
The backtrace output:
(gdb) bt
#0 main () at backtrace.cpp:21
(gdb) bt full
#0 main () at backtrace.cpp:21
obj = {x = -8896}
(gdb) n
22 dummyA obj;
(gdb)
Questions:
bt is said to be printing a backtrace of the entire stack: one line per frame for all frames in the stack, but I see only the name of the function in the output? Why is that so?
bt full shows the inner works, how can it read the 'obj' when the control is not on that line (dummyA obj;) yet?
EDIT 1:
Breakpoint 1, dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
20 x = x + 2;
(gdb) bt 0
(More stack frames follow...)
The above output shows nothing because the callee function testB has zero local variables? Is that correct?
(gdb) bt 1
#0 dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
(More stack frames follow...)
(gdb) bt 2
#0 dummyA::testB (this=0x7fffffffdc50) at backtrace.cpp:20
#1 0x000000000040078b in main () at backtrace.cpp:31
What do frames 1 and 2 show exactly?
(gdb) bt full
#0 main () at backtrace.cpp:26
obj1 = {x = -8896}
obj2 = {x = 0}
Why does x have two different values here, assuming that the breakpoint is on main?
WRT the following code:
#include <iostream>
using namespace std;
class dummyA
{
int x;
public:
dummyA ()
{
x = 0;
}
void testA ()
{
x = x + 1;
}
void testB ()
{
x = x + 2;
}
};
int main ()
{
cout << "\nG'Morning";
dummyA obj1;
dummyA obj2;
obj1.testA ();
obj1.testB ();
obj2.testA ();
obj2.testB ();
return 0;
}
bt is said to be printing a backtrace of the entire stack: one line per frame for all frames in the stack, but I see only the name of the function in the output? Why is that so?
The backtrace shows the current function, then the function that called that, and so on, all the way back to main(). Each "stack frame" is the section of stack used by a particular function, so there's one frame per function. Since the current function is main(), there is only one frame to show.
(Perhaps you were hoping the the backtrace would allow you to see every line of code that was executed. Unfortunately, when running code normally (which is what gdb does, apart from adding breakpoints), there isn't enough available information to do that; the best you can do is look at the history of function calls.)
bt full shows the inner works, how can it read the 'obj' when the control is not on that line (dummyA obj;) yet?
Space has been allocated (in the local stack frame) for the object; it just hasn't been initialised yet. You're seeing whatever happens to be in that space, and it should become {x = 0} if you step over the initialisation line.
The above output shows nothing because the callee function testB has zero local variables? Is that correct?
It shows nothing because you asked it to show nothing; the argument to bt specifies how many stack frames to show, and you said zero.
What do frames 1 and 2 show exactly?
In the first case, you asked for one stack frame; that of the current function. It tells you that you're in the function dummyA::testB, that the address of the object it was called on (this) is 0x7fffffffdc50, and that the corresponding source line is line 20 of backtrace.cpp.
In the second case, you asked for two frames, so it also shows where the current function was called from: the function main(), source line 31 of backtrace.cpp.
Why does x have two different values here, assuming that the breakpoint is on main?
Each is the member of a different object (obj1.x and obj2.x), and neither has been initialised; so each is showing some random value that happens to be in that memory location. Again, both will become zero if you step over the initialisers.
The object has not been constructed yet, but space has been allocated for it. You're seeing the entire backtrace -- you're in main, period.