如何追踪导致段错误的原因?
How to trace what is causing a Segfault?
typedef struct Cell {
float altitude;
int type;
}Cell;
void MAZE(FILE *fp, Cell *Map);
int main(void) {
FILE *fp = fopen("map.bin", "rb");
Cell *Map;
Map = read_file(fp);
char choice;
while (1) {
system("color 0f");
system("cls");
puts("Main menu:");
puts("1. Show map by type.");
puts("2. Show map by altitude.");
puts("3. Build route.");
puts("4. Find suitable places for biker jumps.");
puts("5. Quit.");
std::cin >> choice;
std::cin.ignore();
switch (choice) {
case '1': {
display_map_by_type(fp, Map);
continue;
}
case '2': {
display_map_by_altitude(fp, Map);
continue;
}
case '3': {
MAZE(fp, Map);
continue;
}
case '5': {
puts("You've decided to quit.");
free(Map);
return 0;
}
default: {
system("color 9f");
puts("Invalid choice.");
puts(Press);
getche();
continue;
}
}
return 0;
}
}
void MAZE(FILE *fp, Cell *Map) {
bool (*initial_maze)[10][10] = (bool (*)[10][10])malloc(sizeof(bool[10][10]));
if (initial_maze == NULL) {
fprintf(stderr, NaM);
exit(-3);
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (Map[i * 10 + j].type == 2 || Map[i * 10 + j].type == 4) {
*initial_maze[i][j] = false;
}
else {
*initial_maze[i][j] = true;
}
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
printf("[%d]", Map[i *10 + j].type);
}
putchar('\n');
}
putchar('\n');
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++) {
printf("%3s", *initial_maze[i][j] ? "." : "[]");
}
putchar('\n');
}
getchar();
free(initial_maze);
}
此程序将一组对象加载到堆中 - Cell *Map
。该数组在 main
中可用,并且在 main
或任何其他函数中是可传递的和 free()
可用的。但是由于某种原因,在选择选项 3 时会出现段错误。我不知道为什么会发生段错误(Cell *Map
和 bool *initial_maze[10][10]
)。至少我没有找到段错误的任何原因,没有访问未初始化的内存,没有多个 free()
-s。从技术上讲,switch
中有一个循环中的 free()
,但这仍然不可能,因为在那之后有一个 return
语句。最重要的是,它也不总是崩溃,尽管在大多数情况下都会崩溃。
Visual Studio 中的调试器和代码块指向 free(initial_maze);
行,但没有任何问题,在此之前没有任何东西可以使数组无效。
出于某种奇怪的原因,Visual Studio 还指向了 system("color 0f");
行,就好像它可以触发异常一样。
至于某些上下文,void MAZE(FILE *fp, Cell *Map);
函数中发生了什么。它应该解决迷宫问题,但首先它必须根据传递给它的一维对象数组创建一个二维布尔数组。
我已经阅读了文档,我熟悉使用动态内存的规则。
如果你想要一些输出:
[0][0][2][3][1][4][1][2][0][3]
[2][1][1][0][3][4][0][2][1][0]
[4][0][4][3][1][1][0][4][1][2]
[2][1][3][1][3][2][1][3][1][0]
[2][2][3][0][0][1][2][4][4][3]
[1][3][2][1][2][2][0][1][1][3]
[4][4][0][3][1][2][0][4][1][2]
[3][0][4][4][4][1][0][3][2][0]
[1][4][3][4][3][4][0][1][1][0]
[1][1][2][2][1][1][3][1][3][3]
. . [] . . [] . [] . .
[] . . . . [] . [] . .
[] . [] . . . . [] . []
[] . . . . [] . . . .
[] [] . . . . [] [] [] .
. . [] . [] [] . . . .
[] [] . . . [] . [] . []
. . [] [] [] . . . [] .
. [] . [] . [] . . . .
. . [] [] . . . . . .
然后程序挂起并崩溃。
免责声明:此答案适用于 C,因为您已将问题标记为此类。但是,您的代码实际上是 C++。
这是一个简单的运算符优先级错误,*initial_maze[i][j]
应该是 (*initial_maze)[i][j]
。由于 [] 的优先级高于 *,您最终引用数组 bool[10][10]
次 i
,这不是本意。
但不要这样做,而是将 malloc 调用更改为:
bool (*initial_maze)[10] = malloc(sizeof(bool[10][10]));
然后以 initial_maze[i][j]
的形式访问它。更容易阅读。
尽管如评论中所述,首先几乎不需要动态内存。你可以只制作一个本地二维数组。
typedef struct Cell {
float altitude;
int type;
}Cell;
void MAZE(FILE *fp, Cell *Map);
int main(void) {
FILE *fp = fopen("map.bin", "rb");
Cell *Map;
Map = read_file(fp);
char choice;
while (1) {
system("color 0f");
system("cls");
puts("Main menu:");
puts("1. Show map by type.");
puts("2. Show map by altitude.");
puts("3. Build route.");
puts("4. Find suitable places for biker jumps.");
puts("5. Quit.");
std::cin >> choice;
std::cin.ignore();
switch (choice) {
case '1': {
display_map_by_type(fp, Map);
continue;
}
case '2': {
display_map_by_altitude(fp, Map);
continue;
}
case '3': {
MAZE(fp, Map);
continue;
}
case '5': {
puts("You've decided to quit.");
free(Map);
return 0;
}
default: {
system("color 9f");
puts("Invalid choice.");
puts(Press);
getche();
continue;
}
}
return 0;
}
}
void MAZE(FILE *fp, Cell *Map) {
bool (*initial_maze)[10][10] = (bool (*)[10][10])malloc(sizeof(bool[10][10]));
if (initial_maze == NULL) {
fprintf(stderr, NaM);
exit(-3);
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (Map[i * 10 + j].type == 2 || Map[i * 10 + j].type == 4) {
*initial_maze[i][j] = false;
}
else {
*initial_maze[i][j] = true;
}
}
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
printf("[%d]", Map[i *10 + j].type);
}
putchar('\n');
}
putchar('\n');
for (int i = 0; i < 10; i++){
for (int j = 0; j < 10; j++) {
printf("%3s", *initial_maze[i][j] ? "." : "[]");
}
putchar('\n');
}
getchar();
free(initial_maze);
}
此程序将一组对象加载到堆中 - Cell *Map
。该数组在 main
中可用,并且在 main
或任何其他函数中是可传递的和 free()
可用的。但是由于某种原因,在选择选项 3 时会出现段错误。我不知道为什么会发生段错误(Cell *Map
和 bool *initial_maze[10][10]
)。至少我没有找到段错误的任何原因,没有访问未初始化的内存,没有多个 free()
-s。从技术上讲,switch
中有一个循环中的 free()
,但这仍然不可能,因为在那之后有一个 return
语句。最重要的是,它也不总是崩溃,尽管在大多数情况下都会崩溃。
Visual Studio 中的调试器和代码块指向 free(initial_maze);
行,但没有任何问题,在此之前没有任何东西可以使数组无效。
出于某种奇怪的原因,Visual Studio 还指向了 system("color 0f");
行,就好像它可以触发异常一样。
至于某些上下文,void MAZE(FILE *fp, Cell *Map);
函数中发生了什么。它应该解决迷宫问题,但首先它必须根据传递给它的一维对象数组创建一个二维布尔数组。
我已经阅读了文档,我熟悉使用动态内存的规则。
如果你想要一些输出:
[0][0][2][3][1][4][1][2][0][3]
[2][1][1][0][3][4][0][2][1][0]
[4][0][4][3][1][1][0][4][1][2]
[2][1][3][1][3][2][1][3][1][0]
[2][2][3][0][0][1][2][4][4][3]
[1][3][2][1][2][2][0][1][1][3]
[4][4][0][3][1][2][0][4][1][2]
[3][0][4][4][4][1][0][3][2][0]
[1][4][3][4][3][4][0][1][1][0]
[1][1][2][2][1][1][3][1][3][3]
. . [] . . [] . [] . .
[] . . . . [] . [] . .
[] . [] . . . . [] . []
[] . . . . [] . . . .
[] [] . . . . [] [] [] .
. . [] . [] [] . . . .
[] [] . . . [] . [] . []
. . [] [] [] . . . [] .
. [] . [] . [] . . . .
. . [] [] . . . . . .
然后程序挂起并崩溃。
免责声明:此答案适用于 C,因为您已将问题标记为此类。但是,您的代码实际上是 C++。
这是一个简单的运算符优先级错误,*initial_maze[i][j]
应该是 (*initial_maze)[i][j]
。由于 [] 的优先级高于 *,您最终引用数组 bool[10][10]
次 i
,这不是本意。
但不要这样做,而是将 malloc 调用更改为:
bool (*initial_maze)[10] = malloc(sizeof(bool[10][10]));
然后以 initial_maze[i][j]
的形式访问它。更容易阅读。
尽管如评论中所述,首先几乎不需要动态内存。你可以只制作一个本地二维数组。