关于C#:找不到小内存泄漏的来源

Cannot find source of small memory leak

我创建了一个程序,可以使用蛮力回溯算法解决C中的数独难题,但是在分析valgrind中的内存使用情况后,我注意到它的泄漏很小。我知道有一个GCC错误,造成1个未命中空闲空间和72704个仍可访问的字节。

似乎我丢失了903个free() / delete / delete[]调用,它们占用了大约100KB的内存。

有人知道导致内存泄漏的原因以及如何解决吗?

Backtracker.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include"Backtracker.h"

/**
 * Clears all dynamic memory in the list.
 * @param lst: the pointer to the list to be cleared
 */

static void clearList(std::list<Grid*> *lst) {
    std::list<Grid*>::iterator it;
    for (unsigned int i = 0; i < lst->size(); i++) {
        it = lst->begin();
        std::advance(it, i);
        delete *it;
    }
    delete lst;
}

/**
 * Solves the sudoku puzzle or returns a null if there is no solution.
 * @param g: a pointer to the starting grid
 * @return: a pointer to the solution
 */

Grid* solve(Grid *g) {
    if (g->isGoal()) {
        return g;
    }

    std::list<Grid*> *successors = g->getSuccessors();
    std::list<Grid*>::iterator it;

    for (unsigned int i = 0; i < successors->size(); i++) {
        it = successors->begin();
        std::advance(it, i);

        if ((*it)->isValid()) {
            Grid *solution = solve(*it);
            if (solution != nullptr) {
                solution = solution->copyGrid();
                clearList(successors);
                return solution;
            }
        }
    }
    clearList(successors);

    return nullptr;
}`

Grid.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#include"Grid.h"

/**
 * Constructor for the Grid class.
 */

Grid::Grid() {
    grid = new int*[SIZE];

    for (int i = 0; i < SIZE; i++) {
        grid[i] = new int[SIZE];
    }

    currRow = 0;
    currCol = 0;
}

/**
 * Destructor for the Grid class.
 */

Grid::~Grid() {
    for (int i = 0; i < SIZE; i++) {
        delete[] grid[i];
    }

    delete[] grid;
}

/**
 * Getter for any value in the grid.
 * @param row: the index of the row
 * @param col: the index of the column
 * @return: the value at the given row and column indexes
 */

int Grid::getValue(int row, int col) {
    return grid[row][col];
}

/**
 * Setter for any value in the grid.
 * @param row: the index of the row
 * @param col: the index of the column
 * @param value: the value to set at the given row and column
 */

void Grid::setValue(int row, int col, int value) {
    grid[row][col] = value;
}

/**
 * Allocates dynamic memory for a new grid and copies over the contents.
 * @return: a pointer to the new grid object
 */

Grid* Grid::copyGrid() {
    Grid *copy = new Grid();

    for (int r = 0; r < SIZE; r++) {
        for (int c = 0; c < SIZE; c++) {
            copy->setValue(r, c, grid[r][c]);
        }
    }

    copy->currRow = currRow;
    copy->currCol = currCol;

    return copy;
}

/**
 * Creates a list of successors by moving the cursor and setting the next value.
 * @return: a list of the successors
 */

std::list<Grid*>* Grid::getSuccessors() {
    std::list<Grid*> *successors = new std::list<Grid*>();

    if (canMove()) {
        Grid *copy = copyGrid();
        copy->moveCursor();
        if (copy->getValue(currRow, currCol) != 0) {
            successors->push_back(copy);
            return successors;
        } else {
            delete copy;
        }
        for (int i = 0; i < SIZE; i++) {
            copy = copyGrid();
            copy->moveCursor();
            copy->setValue(currRow, currCol, i + 1);
            if (copy->isValid()) {
                successors->push_back(copy);
            } else {
                delete copy;
            }
        }
    }

    return successors;
}

/**
 * Determines if the current configuration could be a possible solution.
 * @return: true if it could be a solution, false if not
 */

bool Grid::isValid() {
    // Checks each row for a duplicate number.
    for (int r = 0; r < SIZE; r++) {
        bool nums[SIZE] = {false * SIZE};
        for (int c = 0; c < SIZE; c++) {
            if ((grid[r][c] > 0) && (!nums[grid[r][c] - 1])) {
                nums[grid[r][c] - 1] = true;
            } else if ((grid[r][c] > 0) && (nums[grid[r][c] - 1])) {
                return false;
            }
        }
    }

    // Checks each column for a duplicate number.
    for (int c = 0; c < SIZE; c++) {
        bool nums[SIZE] = {false * SIZE};
        for (int r = 0; r < SIZE; r++) {
            if ((grid[r][c] > 0) && (!nums[grid[r][c] - 1])) {
                nums[grid[r][c] - 1] = true;
            } else if ((grid[r][c] > 0) && (nums[grid[r][c] - 1])) {
                return false;
            }
        }
    }

    // Checks squares.
    int val;
    for (int sRow = 0; sRow < SQUARES; sRow++) {
        for (int sCol = 0; sCol < SQUARES; sCol++) {
            bool nums[SIZE] = {false * SIZE};
            for (int r = 0; r < SQUARES; r++) {
                for (int c = 0; c < SQUARES; c++) {
                    val = grid[(sRow * 3) + r][(sCol * 3) + c];
                    if ((val > 0) && (!nums[val - 1])) {
                        nums[val - 1] = true;
                    } else if ((val > 0) && (nums[val - 1])) {
                        return false;
                    }
                }
            }
        }
    }

    return true;
}

/**
 * Determines if the current configuration is a solution or not.
 * @return: true if it is a solution, false if not
 */

bool Grid::isGoal() {
    for (int r = 0; r < SIZE; r++) {
        for (int c = 0; c < SIZE; c++) {
            if (grid[r][c] <= 0 || grid[r][c] > 9) {
                return false;
            }
        }
    }

    return isValid();
}

/**
 * Determines if the cursor can be advanced a position or not.
 * @return: true if the cursor can be moved, false if it is at the last position of the board
 */

bool Grid::canMove() {
    return !((currRow == SIZE - 1) && (currCol == SIZE));
}

/**
 * Moves the cursor to the next position if it is not at the last position of the board.
 * @return: true if the cursor was moved, false if it cannot be moved
 */

bool Grid::moveCursor() {
    if (!canMove()) {
        return false;
    } else {
        if (currCol != SIZE - 1) {
            currCol++;
            return true;
        } else {
            currCol = 0;
            if (currRow == SIZE - 1) {
                return false;
            } else {
                currRow++;
                return true;
            }
        }
    }
}

/**
 * Creates a string for the given row.
 * @param row: the index of the row to generate a string for
 * @return: a string for that row
 */

std::string Grid::rowString(int row) {
    std::string output ="";
    int c;

    for (c = 0; c < 3; c++) {
        output += std::to_string(grid[row][c]) +"";
    }
    output +="|";

    for (c = 3; c < 6; c++) {
        output += std::to_string(getValue(row, c)) +"";
    }
    output +="|";

    for (c = 6; c < SIZE; c++) {
        output += std::to_string(getValue(row, c)) +"";
    }

    return output;
}

/**
 * Creates a string representation of the entire grid.
 * @return: a string for the entire grid.
 */

std::string Grid::toString() {
    std::string output ="";

    // TODO remove this
    output += std::to_string(currRow) +"," + std::to_string(currCol) +"\
"
;

    int r;

    for (r = 0; r < 3; r++) {
        output += rowString(r) +"\
"
;
    }
    output +="---------------------\
"
;

    for (r = 3; r < 6; r++) {
        output += rowString(r) +"\
"
;
    }
    output +="---------------------\
"
;

    for (r = 6; r < SIZE; r++) {
        output += rowString(r) +"\
"
;
    }

    return output;
}`

valgrind输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
==3021==
==3021== HEAP SUMMARY:
==3021==     in use at exit: 106,488 bytes in 903 blocks
==3021==   total heap usage: 3,260,824 allocs, 3,259,921 frees, 121,174,996 bytes allocated
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 19 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x401A69: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 20 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 21 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 22 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 23 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 24 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 25 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 26 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 27 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 412 (16 direct, 396 indirect) bytes in 1 blocks are definitely lost in loss record 28 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x40230F: main (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== 29,664 (1,152 direct, 28,512 indirect) bytes in 72 blocks are definitely lost in loss record 31 of 32
==3021==    at 0x4C2E0EF: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3021==    by 0x402620: Grid::copyGrid() (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x404104: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==    by 0x4040ED: solve(Grid*) (in /home/anthony/Documents/Code/c-c++-projects/Sudoku-Solver/sudoku-solver)
==3021==
==3021== LEAK SUMMARY:
==3021==    definitely lost: 1,312 bytes in 82 blocks
==3021==    indirectly lost: 32,472 bytes in 820 blocks
==3021==      possibly lost: 0 bytes in 0 blocks
==3021==    still reachable: 72,704 bytes in 1 blocks
==3021==         suppressed: 0 bytes in 0 blocks
==3021== Reachable blocks (those to which a pointer was found) are not shown.
==3021== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==3021==
==3021== For counts of detected and suppressed errors, rerun with: -v
==3021== ERROR SUMMARY: 11 errors from 11 contexts (suppressed: 0 from 0)


不确定这是您的问题,但是...据valgrind称,问题与Grid::copyGrid()中分配的内存有关,因此由以下new

分配的内存

1
2
3
4
5
Grid* Grid::copyGrid() {
    Grid *copy = new Grid();
    // ...
    return copy;
}

我怀疑问题(有问题吗?)在solve()中。

1
2
3
4
5
6
7
8
if ((*it)->isValid()) {
    Grid *solution = solve(*it);
    if (solution != nullptr) {
        solution = solution->copyGrid();
        clearList(successors);
        return solution;
    }
}

观察到solve()返回由

获得的solution

1
solution = solution->copyGrid();

所以是分配的(new)值,但丢失了

获得的solution原始值

1
Grid *solution = solve(*it);

来自solve()

,因此已被分配。

我的意思是:在哪里删除solve()返回的值?

我想你应该写类似

的东西

1
2
3
4
5
6
7
8
9
if ((*it)->isValid()) {
    Grid *solution = solve(*it);
    if (solution != nullptr) {
        Grid *retSol = solution->copyGrid();
        clearList(successors);
        delete solution;
        return retSol;
    }
}

-编辑-

操作答案:

I just tried this, however it only causes a segmentation fault. Removing the delete solution; line fixes the segmentation fault, but the memory leak is still there.

我明白了...
这里的问题是(如果我没记错的话)solve()也可以返回接收到的值

1
2
3
4
Grid* solve(Grid *g) {
    if (g->isGoal()) {
        return g;
    }

嗯...

因此,只有与*it不同时,才必须删除它。

我不喜欢,但我建议

1
2
3
4
5
6
7
8
9
10
11
12
if ((*it)->isValid()) {
    Grid *solution = solve(*it);
    if (solution != nullptr) {
        Grid *retSol = solution->copyGrid();
        clearList(successors);

        if ( solution != *it )
           delete solution;

        return retSol;
    }
}