mardi 24 février 2015

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
$2 = (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 {


I wrote some code and ran a few (Google) tests on it, only to find that it failed: the program finished and gave an incorrect output. So naturally I fired up gdb and tried to debug my tests.


Interestingly, right before I stepped into GetCandidates(int cursor) function, on line 102, the 'this' pointer was good:



(gdb) print this

$2 = (BishopArranger * const) 0x22a5f0


then I did a 'step' into the function and it immediately gave me an exception complaining '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 {


How absurd is that? I know for sure this only happened when I debugged through my test cases written with Google Test, not when I ran them:



[ 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)


As you see, when I ran the Google tests, an incorrect output 12 was produced. Although the program failed to pass the assertion, it finished with no exception.


Some info you might be interested in:


1, There's only one thread in my program, although Google Test makes use of pthreads to parallelize execution of tests, according to their documentation(it says there's no guarantee certain tests finish before the others).


Not sure this is relevant in my case, as each of my test has its own object and there's no common setup/teardown parts so it's not likely for the object in one test to be destructed by another test. They look like:



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, Platform: CYGWIN_NT-6.1; g++ used to compile Google Test and this program: 4.8.3(Yes, I followed the documentation of Google Test and compiled from source using the same version of compiler for my c++ programs to avoid potential problems); gdb version: 7.8


Thanks in advance for inputs!


Aucun commentaire:

Enregistrer un commentaire