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?
Related
I'm trying to print the return value of a templated member function in gdb (version 7.6.1 I think) of an rvalue reference, so what I write in gdb amounts to something like this:
gdb> print (*(TypeOne*)var).get<TypeTwo>()
I've tried parenthesizing various parts of the expression with no success, and I wasnt able to find any other question on this. Anyone know?
Starting from this related post: How to `print`/evaluate c++ template functions in gdb
I was able to figure out how to do this within my own program.
I'm not using an rvalue nor a variant so it may not work for that, but I think it's still relevant to this question.
My use case was a method with a single enum as a template parameter, similar to this:
#include <stdio.h>
enum class MyEnum {
VALUE_0 = 0,
VALUE_1 = 1
};
struct TestStruct {
template <MyEnum VALUE>
int getValue() {
if constexpr (VALUE == MyEnum::VALUE_0) {
return value_0;
} else /* VALUE == MyEnum::VALUE_1 */ {
return value_1;
}
}
const int value_0 = 7;
const int value_1 = 9;
};
int main()
{
TestStruct test;
test.template getValue<MyEnum::VALUE_0>();
test.template getValue<MyEnum::VALUE_1>();
return 0;
}
If we use ptype on the object we get a list of methods on the object:
(gdb) b 36
Breakpoint 1 at 0x4004f7: file main.cpp, line 36.
(gdb) r
Starting program: /home/a.out
Breakpoint 1, main () at main.cpp:36
36 return 0;
(gdb) ptype test
type = struct TestStruct {
const int value_0;
const int value_1;
public:
int getValue<(MyEnum)1>(void);
int getValue<(MyEnum)0>(void);
}
If we want to call this method:
int getValue<(MyEnum)1>(void);
We can call it by using the name exactly as shown, in single quotes.
(gdb) p test.'getValue<(MyEnum)1>'()
$1 = 9
You can try it here: https://onlinegdb.com/7OtaUvK3g
Note from the other thread:
Without an explicit instance in the source code, the compiler will treat the template code as it would "static inline" code and optimize it out if it is unused.
So you must call the method somewhere in your code to be able to call it in gdb at all, this will not work otherwise.
#include <iostream>
class C
{
private:
int *o;
public:
C(int &i) { *o = i;}
int* get_val() {return o;}
};
int main()
{
int t = 9;
C c(t);
int* p = c.get_val();
std::cout<<*p<<std::endl;
int* h = c.get_val(); //seg fault
std::cout<<*h<<std::endl;
int f = 25;
C g(f);
int* q = g.get_val(); //seg fault
std::cout<<*q<<std::endl;
return 0;
}
There are two objects to the class C : 'c' and 'g'.
Returning the private variable's pointer works fine for the first time, but, it results in seg fault, when called for the second time. Why is it so?
So, I commented out the second call and tried creating a new object and called tried to return the private variable's pointer. Even though, 'g' is another object of class C, returning it results in segmentation fault. Why is it so?
The constructor C::C(int) doesn't initialize the member variable o. It tries to write through the pointer o via *o=i, but since o is uninitialized, the results are unpredictable.
You are not initialising C::o at all. The problem isn't that you're returning the private pointer; it's that you're assigning to memory you haven't allocated.
Here's the output from gdb with a breakpoint at line 8 (C's constructor):
Breakpoint 1 at 0x400960: file tmp.cc, line 8.
Breakpoint 1, C::C (this=0x7fffffffdd00, i=#0x7fffffffdd08: 9) at tmp.cc:8
8 C(int &i) { *o = i;}
$1 = (int *) 0x7fffffffddf0
9
9
Breakpoint 1, C::C (this=0x7fffffffdce0, i=#0x7fffffffdcec: 25) at tmp.cc:8
8 C(int &i) { *o = i;}
$2 = (int *) 0x0
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400969 in C::C (this=0x7fffffffdce0, i=#0x7fffffffdcec: 25) at tmp.cc:8
8 C(int &i) { *o = i;}
On my machine, the first call succeeded, but the second call causes the segfault, because g.o is 0x0.
You should initialise C::o before assigning to *o, eg.
C(int &i) : o(new int) { *o = i;}
In
C(int &i) { *o = i;}
You have not already allocated space for you pointer before allocation. It should've been :
C(int i):o(new int){o=i;}
But allocating memory inside class functions requires that you need to systematically apply delete/delete[] on them. Well, this is to prevent memory leak. In short you need :
C::~C(){
delete o; // Freeing the memory associated with each object
}
Also, I can't think of a use-case for passing the value by reference in your implementation. So I changed C(int &i) to C(int i).
Consider the following program, which I compile with g++ -g myprog.cc.
#include<iostream>
struct Context {
//char *s; // version 1
std::string s; // version 2
};
void f(Context);
void f(Context c) {}
int main(void) {
Context c = Context();
f(c);
}
Version 1 has a char * member, while version 2 replaces it with std::string.
Using gdb, I step through the code and get this:
Temporary breakpoint 1, main () at myprog.cc:12
12 Context c = Context();
&ebsp;Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-11.el6.x86_64 libstdc++-4.4.7-11.el6.x86_64
(gdb) s
13 f(c);
(gdb) s
f (c=...) at myprog.cc:9
9 void f(Context c) {}
(gdb) s
main () at myprog.cc:14
14 }
Nothing wrong here.
If I step through version 2, I get:
Temporary breakpoint 1, main () at myprog.cc:12
12 Context c = Context();
Missing separate debuginfos, use: debuginfo-install libgcc-4.4.7-11.el6.x86_64 libstdc++-4.4.7-11.el6.x86_64
(gdb) s
Context::Context (this=0x7fffffffe400) at myprog.cc:3
3 struct Context {
(gdb) s
main () at myprog.cc:13
13 f(c);
(gdb) s
Context::Context (this=0x7fffffffe410) at myprog.cc:3
3 struct Context {
(gdb) s
f (c=...) at myprog.cc:9
9 void f(Context c) {}
(gdb) s
Context::~Context (this=0x7fffffffe410, __in_chrg=) at myprog.cc:3
3 struct Context {
(gdb) s
Context::~Context (this=0x7fffffffe400, __in_chrg=) at myprog.cc:3
3 struct Context {
(gdb) s
main () at myprog.cc:14
14 }
Why is it that when I pass in a struct Context with the std::string member, I get the output Context::Context (this=0x7fffffffe400)?
Also, when I instantiate the struct, this=0x7fffffffe400. When I pass it in, this=0x7fffffffe410. Why is that?
You pass c by value to a function that doesn't do anything. So the compiler has to produce any visible effects of pass by value semantics. The compiler can't be sure that copying and then destroying the string has no consequences, so it does it. It can be sure that copying a char * and destroying the copy has no consequences, so it doesn't bother.
What's happening is you're seeing the compiler generated constructor, which is not generated for the struct with just a pointer, because there would be nothing to do in that constructor. For the struct with the std::string member, it likely calls std::strings constructor.
Since the constructor is a non-static member function, the this=0x7fffffffe400 is the implicit 'this' pointer argument being passed in.
#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.
I defined a class named nth_best_parse this way:
class nth_best_parse {
public:
int traversal;
int nth_best_active;
int nth_best_passive;
double viterbi_prob;
nth_best_parse();
nth_best_parse(int t, int nbl, int nbr, double v) {traversal = t; nth_best_active = nbl; nth_best_passive = nbr; viterbi_prob = v;}
};
Then I declared vectors of this nth_best_parse as members of two different classes:
class Edge { // an edge associates an Earley style dotted-item with a span
public:
<some irrelevant stuff>
Span span; // Span of the edge
bool isActive;
vector<Traversal *> leading_traversals; // The list of traversals which lead to parsing of this edge
vector<nth_best_parse> n_best_parses;
union {
DottedRule rule_state; // Accessed if isActive is true
int symbol; // Accessed if isActive is false
// A symbol corresponding to the category of a passive edge
// Put inside this union to save space
};
inline int span_length() {return span.end - span.start;}
};
<some other stuff>
class BPCFGParser {
public:
// Some data structures used in intermediary computations for calculating the n-best parses
// vector<vector<int> > nth_best_pairs;
vector<vector<nth_best_parse> > n_best_pairs_for_traversals;
<some other stuff>
void compute_n_best_parses(Edge *e, int n);
<some other stuff>
}
Then I run this program with gdb (by the way, I'm using Linux Ubuntu 9.04, g++ 4.3.3,GNU gdb 6.8-debian) and set a breakpoint at the end of the definition of compute_n_best_parses() with some conditions (to locate the exact call of this function I wanted, I was tracing back from a segmentation fault). When gdb hit the breakpoint, I issued a set of commands and the gdb output was like this:
(gdb) print e->n_best_parses.size()
$27 = 1
(gdb) print e->n_best_parses[0]
$28 = (nth_best_parse &) #0x1e96240: {traversal = 0, nth_best_active = 0, nth_best_passive = 0, viterbi_prob = 0.16666666666666666}
(gdb) print e->n_best_parses[0].traversal
$29 = 0
(gdb) print &(e->n_best_parses[0].traversal)
$30 = (int *) 0x1e96240
(gdb) awatch *$30
Hardware access (read/write) watchpoint 6: *$30
(gdb) print e->n_best_parses
$31 = {<std::_Vector_base<nth_best_parse, std::allocator<nth_best_parse> >> = {
_M_impl = {<std::allocator<nth_best_parse>> = {<__gnu_cxx::new_allocator<nth_best_parse>> = {<No data fields>}, <No data fields>},
_M_start = 0x1e96240, _M_finish = 0x1e96258, _M_end_of_storage = 0x1e96288}}, <No data fields>}
(gdb) continue
Continuing.
Hardware access (read/write) watchpoint 6: *$30
Old value = 0
New value = 1
0x0000000000408a4c in __gnu_cxx::new_allocator<nth_best_parse>::construct<nth_best_parse> (this=0x1e96208, __p=0x1e96240, __args#0=#0x7fff8ad82260)
at /usr/include/c++/4.3/ext/new_allocator.h:114
114 { ::new((void *)__p) _Tp(std::forward<_Args>(__args)...); }
(gdb) backtrace
#0 0x0000000000408a4c in __gnu_cxx::new_allocator<nth_best_parse>::construct<nth_best_parse> (this=0x1e96208, __p=0x1e96240, __args#0=#0x7fff8ad82260)
at /usr/include/c++/4.3/ext/new_allocator.h:114
#1 0x000000000042169c in std::vector<nth_best_parse, std::allocator<nth_best_parse> >::push_back<nth_best_parse> (this=0x1e96208, __args#0=#0x7fff8ad82260)
at /usr/include/c++/4.3/bits/stl_vector.h:703
#2 0x0000000000402bef in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f5492858b78, n=3) at BPCFGParser.cpp:639
#3 0x00000000004027fd in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f5492859d58, n=3) at BPCFGParser.cpp:606
#4 0x00000000004027fd in BPCFGParser::compute_n_best_parses (this=0x7fff8ad82770, e=0x7f549285a1d0, n=3) at BPCFGParser.cpp:606
#5 0x00000000004064d8 in main () at experiments.cpp:75
Line 639 of BPCFGParser.cpp was like this:
PUSH_BEST_PAIR_FOR_TRAVERSAL(i,row,column,grammar->probs[temp_rule.symbol][temp_rule.expansion]);
This was a macro defined at the beginning of the file as:
#define PUSH_BEST_PAIR_FOR_TRAVERSAL(x,y,z,t) n_best_pairs_for_traversals[x].push_back(nth_best_parse(x, y, z, e->leading_traversals[x]->active_edge->n_best_parses[y].viterbi_prob * e->leading_traversals[x]->passive_edge->n_best_parses[z].viterbi_prob * t))
By the way, class Traversal is defined as:
class Traversal { // Class for a traversal
public:
Edge *active_edge;
Edge *passive_edge;
Traversal();
Traversal(Edge *a, Edge *p) {active_edge = a; passive_edge = p;}
};
So actually I'm pushing something to the vector n_best_pairs_for_traversals, which is a member of an instance of the class BPCFGParser and the push_back() code somehow overwrites on the vector n_best_parses, which is a member of an instance of the class Edge. How can this ever be possible?
You obviously have memory corruption problems somewhere.
BUT there is not enough here information to help you.
But you are writing C++ code and your class contain pointers.
This is not a good sign (there should hardly ever be a RAW pointer in a C++ class).
This is also often the cause of memory corruption for inexperienced C++ developers!
Have you obeyed the rule of 4?
Make sure every class that contains RAW owned pointers:
constructor
copy constructor
assignment operator
destructor.
Are you sure you're passing a valid first argument to your macro? Maybe you're accessing out of bounds when doing n_best_pairs_for_traversals[x] because x is larger than the vector size.
I'd guess that you are using a vector to store objects (perhaps Traversal?), not realizing that pushing new elements onto that vector can invalidate pointers to elements already in the vector. Use a deque instead if this is the case.