【问题标题】:"this" pointer pushed lexically last instead of first“this”指针按词法最后而不是第一个
【发布时间】:2013-12-04 03:50:19
【问题描述】:

我在为 mingw32 编译一些代码时遇到问题,链接一个 mingw32 编译的库。当我在动态链接的库中调用类的成员函数(即构造函数)时,参数会以错误的顺序推送到堆栈中。

这是一个例子:

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

我对 TCODMap 构造函数的调用有参数 width=64height=48,但值得注意的是,this 隐式参数设置为 64 (0x40),width 设置为 48,height设置为某个垃圾值 40。在这种情况下,构造函数被调用为我在用户代码中拥有的另一个类的初始化程序的一部分。

有问题的代码:

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);
    }
  }
}

似乎 thiscall 调用约定,即 this 指针应最后压入堆栈,使其在参数列表中的词法上排在第一位,但没有得到正确遵守。

我该如何解决这个问题?

【问题讨论】:

  • 电脑很听话!
  • 您确定您的项目中没有链接过时的对象文件吗?
  • 没有过时的对象。我已经多次重新编译了所有代码,但得到了相同的一致结果。

标签: c++ c++11 mingw this mingw32


【解决方案1】:

我写了一个测试程序来检查你想做什么。首先,您在运行时而不是在编译时收到错误,因为您提供了 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;
}

堆栈跟踪:

> 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

这里的要点是,'this' 隐式指针将指向一个有效地址,除非您的程序导致“堆栈缓冲区溢出”破坏分配给 tcodmap 的 'this' 指针的内存。

您应该分享完整代码的更多详细信息,以及您如何使用该程序。 您是否在每次运行时都会遇到此问题,还是随机出现的?

【讨论】:

  • 每次运行,始终如一地在代码中的任何位置使用相同的构造函数,每次运行的值相同,具体取决于调用它的位置。我已经完全重建了我的代码,以确保没有陈旧的对象。
  • 尝试在堆上为 tcdomp 分配内存并使用 new 运算符(将 tcodmap 更改为指针类型)。您可以这样做并查看行为吗?
  • 使用“new”和存储指针时的行为是相同的。它在调用构造函数时发生。我怀疑问题出在库二进制文件中。我会看看我是否可以从源代码重建库,尽管到目前为止它只给了我 Windows 标题错误。
猜你喜欢
  • 2010-10-13
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-25
  • 2017-02-26
相关资源
最近更新 更多