The constructor is called with the wrong pointer "this". Is this corruption of the stack?

edit I figured this out with the help of commentators. To answer the question posed in my title: No, this is not stack corruption, its gdb reports incorrect values. The program really behaves as expected and has the correct this pointer. The actual buggy behavior that prompted me to post this question is probably completely unrelated to the issue I am describing here.

First warning. I believe this is a memory corruption problem, and I usually did not expect an answer other than โ€œthoroughly check your codeโ€, but I saw this behavior repeated more than once and hoped that some of you would understand the problem and how I could find it a source.

I am currently doing temporary static analysis, which tracks the possible range of variables in a C program. The copy constructor for my base interval class looks like this:

 itvt::itvt(const itvt& i) : _i(i.type == INTBV ? new intbv_intervalt(ii()) : NULL), _f(i.type == FLOAT ? new float_intervalt(if()) : NULL), type(i.type), other_bottom(i.other_bottom) { } 

Now I found a memory corruption error and managed to trace it to the following code fragment:

 itvt itvt::get_split(bool le) const { itvt result(*this); [...] } 

Using gdb, I found that calling the constructor does not seem to create a "result" object:

 Breakpoint 1, itvt::get_split (this=0x1016af560, le=false) at itv.cpp:517 517 itvt result(*this); (gdb) n 519 if(is_singleton() || is_bot()) (gdb) print result $3 = { _i = { _M_ptr = 0x7fff5fbfe100 }, _f = { _M_ptr = 0x7fff5fbfed60 }, type = 1606410016, other_bottom = 255 } (gdb) print *this $4 = { _i = { _M_ptr = 0x1020833a0 }, _f = { _M_ptr = 0x0 }, type = itvt::INTBV, other_bottom = false } 

Looking deeper, I found that inside the copy constructor, the "this" pointer points to the wrong object:

 Breakpoint 1, itvt::get_split (this=0x1016af560, le=false) at itv.cpp:517 517 itvt result(*this); (gdb) print &result $5 = (itvt *) 0x7fff5fbfdee0 (gdb) s itvt::itvt (this=0x7fff5fbfdf80, i=@0x1016af560 ) at itv.cpp:500 500 type(i.type), other_bottom(i.other_bottom) (gdb) print this $6 = (itvt * const) 0x7fff5fbfdf80 

Since the "result" is allocated on the stack at 0x7fff5fbfdee0, I would expect the "this" pointer inside the copy constructor to point to the same address. Instead, it points to 0x7fff5fbfdf80.

It looks like the copy constructor is initializing something, but not the result object on the stack on which it is called. In fact, I can access the memory cell that the constructor perfectly initialized:

 Breakpoint 1, itvt::get_split (this=0x1016af560, le=false) at itv.cpp:517 517 itvt result(*this); (gdb) s itvt::itvt (this=0x7fff5fbfdf80, i=@0x1016af560 ) at itv.cpp:500 500 type(i.type), other_bottom(i.other_bottom) (gdb) finish Run till exit from #0 itvt::itvt (this=0x7fff5fbfdf80, i=@0x1016af560 ) at itv.cpp:500 itvt::get_split (this=0x1016af560, le=false) at itv.cpp:519 519 if(is_singleton() || is_bot()) (gdb) print *((const itvt*) (0x7fff5fbfdf80)) $7 = { _i = { _M_ptr = 0x1016b6d10 }, _f = { _M_ptr = 0x0 }, type = itvt::INTBV, other_bottom = false } 

My first question is: Can I explain that the "this" pointer points to the wrong object, as normal behavior? It seems like some kind of weird memory corruption issue, but maybe I missed something.

I am compiling with the g ++ and "-O0 -ggdb" flags and have done a new recompilation of all that by the way. Here is my g ++ version:

 leo@scythe ai$ g++ --version i686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00) Copyright (C) 2007 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

My second question: If this is memory corruption, do you have any tips on how I can track the source. I usually follow such problems in their root cause with gdb, but I don't know where to look now.

This is not the first time I've come across this particular behavior. I saw how this happened when viewing other people's mistakes. I never managed to directly access it directly, it simply ceased to exist, or at least became a visible problem after some other code change. This makes me think that maybe this is just a weird artifact viewing the stack with gdb.

I am grateful for any advice or insights you can offer.

edit Here is the corresponding fragment of the itvt class:

 class itvt { protected: typedef std::auto_ptr<intbv_intervalt> iptrt; typedef std::auto_ptr<float_intervalt> fptrt; iptrt _i; fptrt _f; public: typedef enum {INTBV, FLOAT, OTHER} itv_typet; itv_typet type; bool other_bottom; //copy constr itvt(const itvt& i); inline intbv_intervalt& i() { return *_i; } inline float_intervalt& f() { return *_f; } inline const intbv_intervalt& i() const { return *_i; } inline const float_intervalt& f() const { return *_f; } itvt get_split(bool le) const; [...] }; 
+6
source share
2 answers

Second question: use valgrind , this is really what you need here. It keeps track of all distributions / for free and tells you if you are trying to use free memory, as well as many other materials. Itll show you memory corruption.

+4
source

I figured this out with the help of commentators: it seems that gdb is not telling the truth (possibly due to the old version of gdb). The program really behaves as expected.

The actual behavior of the buggy that prompted me to study the problem is not completely related to the initialization of the object.

+2
source

Source: https://habr.com/ru/post/909738/


All Articles