进入函数调用堆栈时,此指针设置为空 - 在 gdb 下发生 Google 测试

this pointer gets set to null when entering function call stack - happening with Google Test under gdb

(gdb) list 95, 195
95      int BishopArranger::FillAndRecurse(int cursor)
96      {
97              if (cursor == _solutionVec.size())
98              {
99                      return 1;
100             }
101
102             unordered_set<tuple<int, int>> candidates = GetCandidates(cursor); //kn
103             if (candidates.empty())
104             {
105                     return 0;
106             }
107
108             int sum = 0;
109             for (unordered_set<tuple<int, int>>::iterator it = candidates.begin(); it != candidates.end(); it++) //n^2
110             {
111                     _solutionVec[cursor] = *it;
112                     sum += FillAndRecurse(cursor+1); //k recursions, each being kn
113             }
114             //kn^3
115             return sum;
116     }
117
118     void ConstructBoard(int k, int n)
119     {
120             BOARD = unordered_set<tuple<int, int>>();
121             for (int i=0; i<n; i++)
122             {
123                     for (int j=0; j<n; j++)
124                     {
125                             BOARD.insert(tuple<int, int>(i, j));
126                     }
127             }
128     }
129
130     int BishopArranger::Solution(int k, int n)
131     {
132             if (n == 0)
133             {
134                     return 0;
135             }
136
137             ConstructBoard(k, n);
138             _solutionVec = vector<tuple<int, int>>(k);
139             return FillAndRecurse(0);
140     }
(gdb) next
102             unordered_set<tuple<int, int>> candidates = GetCandidates(cursor); //kn
(gdb) print this
 = (BishopArranger * const) 0x22a5f0
(gdb) step

Program received signal SIGILL, Illegal instruction.
0x0000000100401bb7 in BishopArranger::GetCandidates (this=0x0, cursor=0)
    at ./src/bishop_arranger/BishopArranger.cc:84
84      {

我写了一些代码并 运行 对其进行了一些 (Google) 测试,结果发现它失败了:程序完成并给出了错误的输出。所以我很自然地启动了 gdb 并尝试调试我的测试。

有趣的是,就在我进入 GetCandidates(int cursor) 函数之前,在第 102 行,'this' 指针是好的:

(gdb) print this

 = (BishopArranger * const) 0x22a5f0

然后我在函数中做了一个 'step' ,它立即给了我一个异常抱怨 'this' was null(this=0x0):

(gdb) step

Program received signal SIGILL, Illegal instruction.
0x0000000100401bb7 in BishopArranger::GetCandidates (this=0x0, cursor=0)
    at ./src/bishop_arranger/BishopArranger.cc:84
84      {

这有多荒谬? 我确信这只发生在我调试用 [=45= 编写的测试用例时] 测试,不是当我运行他们:

[ RUN      ] Solution.TinyBoardTinyK
./test/bishop_arranger/UnitTests.cc:14: Failure
Value of: bishopArranger.Solution(2, 2)
  Actual: 12
Expected: 4
[  FAILED  ] Solution.TinyBoardTinyK (0 ms)

如您所见,当我 运行 测试 Google 时,产生了错误的输出 12。程序虽然断言没有通过,但无一例外地结束了。

您可能感兴趣的一些信息:

1,我的程序中只有一个线程,尽管 Google 测试利用 pthreads 来并行执行测试,根据他们的文档(它说没有 gua运行tee 某些测试在其他人之前完成)。

不确定这是否与我的情况相关,因为我的每个测试都有自己的对象并且没有共同的 setup/teardown 部分,因此一个测试中的对象不太可能被另一个测试破坏。它们看起来像:

TEST(Solution, BoundaryCondition)
{
    BishopArranger bishopArranger;
    EXPECT_EQ(0, bishopArranger.Solution(0, 0));
}


TEST(Solution, TinyBoardTinyK)
{
    BishopArranger bishopArranger;
    EXPECT_EQ(4, bishopArranger.Solution(2, 2));
}


TEST(Solution, SmallBoardSmallK)
{
    BishopArranger bishopArranger;
    EXPECT_EQ(260, bishopArranger.Solution(4, 4));
}

2、平台:CYGWIN_NT-6.1; g++ 用于编译 Google 测试和此程序:4.8.3(是的,我遵循 Google 测试的文档并使用与我的 c++ 程序相同版本的编译器从源代码编译以避免潜在问题) ; gdb 版本:7.8

在此先感谢您的投入!

我相信这是一个隐藏在 cygwin 某处的错误,因为我后来用真正的 Linux 系统尝试了同样的事情,并且它按预期工作得很好。我得到的教训:如果你想做认真的开发,请远离Cygwin。

BishopArranger::GetCandidates (this=0x0, ...)

在尚未构造的静态C++对象中也会发生这种情况。但不清楚您是否遇到该问题。

对于那一团糟,请参阅 "static initialization order fiasco"。在 GCC 下,使用 init_priority 来构造它们。在 Windows 下,使用 init_seg 创建它们。