SIGSEGV 将对象分配给动态二维矩阵
SIGSEGV assigning an object to a dynamic 2d matrix
我试图简单地将定义为 Card
的元素类型从一个向量分配给 mtr[i][j]
,一个存储在堆中的二维矩阵,但调试器声称存在分段错误。
我想我尝试了所有方法,尝试使用静态矩阵,检查监视 NULL
,手动分配结构的每个成员。
出于好奇,我尝试将矩阵的类型更改为int
和char
。即便如此,分配(在正确更改要分配的值之后)不起作用。
int g_rows = 0, g_cols=0;
typedef struct{
char color;
int points;
}Segment;
typedef struct{
Segment h;
Segment v;
}Card;
Card** loadBoard(char* fileName, Card* cards) {
short tileRef; short rot;
short i=0;
FILE* fp = fopen(fileName,"r"); if(fp == NULL) return NULL;
if(fscanf(fp, "%hd %hd\n", &g_rows, &g_cols) == 0) {fclose(fp); return NULL;}
Card **mtr = (Card**)malloc(g_rows * sizeof(**mtr)); if(!mtr){printf("Error on first malloc.\n");}
for(short i = 0; i<g_rows; i++) {
mtr[i] = (Card*)malloc(g_cols * (sizeof (*mtr)) );
if(!mtr[i]) printf("error on 2nd malloc.\n");
}
i=0;
while(!feof(fp)){
for(short j=0;j<g_cols;j++) {
fscanf(fp, "%d/%d\n", &tileRef, &rot);
if (tileRef != -1)
mtr[i][j] = (rot == 0) ? cards[tileRef] : (Card) {.h = cards[tileRef].v, .v = cards[tileRef].h};
else
mtr[i][j] = (Card){{.points=-1,.color='[=10=]'},{.points=-1,.color='[=10=]'}};
}
fscanf(fp,"\b\n"); i++;
}
fclose(fp);
return mtr;
}
我试图搜索此类问题,但奇怪的是我最终研究了二维动态分配的代码示例。
也许我错过了一些重要的东西,但我真的抓不住。
最终编辑:我发现我使用的 che 编译器(Clang/LLVM 来自 MingW)是罪魁祸首。我尝试将 Visual Studio Community 设置为 CLion 中的默认工具链,但没有出现任何问题。
问题似乎是 malloc 调用中的细微拼写错误。
在矩阵的分配中,
Card **mtr = (Card**)malloc(g_rows * sizeof(**mtr));
malloc 正在为 g_rows * sizeof(Card)
分配 space。但是由于 mtr 被用来存储 Card 指针,而不是 Cards,所以我们需要 g_rows * sizeof(Card*)
.
然后在每个矩阵行的分配中,
mtr[i] = (Card*)malloc(g_cols * (sizeof (*mtr)) );
malloc 正在为 g_cols * sizeof(Card*)
分配 space。但是由于每个矩阵行都被用来存储卡片,而不是卡片指针,所以我们需要 g_cols * sizeof(Card)
。这个错误特别严重,因为 sizeof(Card*) 小于 sizeof(Card),所以没有分配足够的内存。
在从文件中读取数据的while循环中,下面还有一个潜在的问题。只要文件继续,循环就会迭代,而不检查 i
变量是否仍在边界内。因此,如果文件格式不正确,可能会导致此代码注销矩阵的末尾和段错误。
评论:我强烈推荐使用 Valgrind or Address Sanitizer (ASan)。这些工具会自动检查与内存相关的错误,对于调试此类问题非常有用。
我试图简单地将定义为 Card
的元素类型从一个向量分配给 mtr[i][j]
,一个存储在堆中的二维矩阵,但调试器声称存在分段错误。
我想我尝试了所有方法,尝试使用静态矩阵,检查监视 NULL
,手动分配结构的每个成员。
出于好奇,我尝试将矩阵的类型更改为int
和char
。即便如此,分配(在正确更改要分配的值之后)不起作用。
int g_rows = 0, g_cols=0;
typedef struct{
char color;
int points;
}Segment;
typedef struct{
Segment h;
Segment v;
}Card;
Card** loadBoard(char* fileName, Card* cards) {
short tileRef; short rot;
short i=0;
FILE* fp = fopen(fileName,"r"); if(fp == NULL) return NULL;
if(fscanf(fp, "%hd %hd\n", &g_rows, &g_cols) == 0) {fclose(fp); return NULL;}
Card **mtr = (Card**)malloc(g_rows * sizeof(**mtr)); if(!mtr){printf("Error on first malloc.\n");}
for(short i = 0; i<g_rows; i++) {
mtr[i] = (Card*)malloc(g_cols * (sizeof (*mtr)) );
if(!mtr[i]) printf("error on 2nd malloc.\n");
}
i=0;
while(!feof(fp)){
for(short j=0;j<g_cols;j++) {
fscanf(fp, "%d/%d\n", &tileRef, &rot);
if (tileRef != -1)
mtr[i][j] = (rot == 0) ? cards[tileRef] : (Card) {.h = cards[tileRef].v, .v = cards[tileRef].h};
else
mtr[i][j] = (Card){{.points=-1,.color='[=10=]'},{.points=-1,.color='[=10=]'}};
}
fscanf(fp,"\b\n"); i++;
}
fclose(fp);
return mtr;
}
我试图搜索此类问题,但奇怪的是我最终研究了二维动态分配的代码示例。
也许我错过了一些重要的东西,但我真的抓不住。
最终编辑:我发现我使用的 che 编译器(Clang/LLVM 来自 MingW)是罪魁祸首。我尝试将 Visual Studio Community 设置为 CLion 中的默认工具链,但没有出现任何问题。
问题似乎是 malloc 调用中的细微拼写错误。
在矩阵的分配中,
Card **mtr = (Card**)malloc(g_rows * sizeof(**mtr));
malloc 正在为
g_rows * sizeof(Card)
分配 space。但是由于 mtr 被用来存储 Card 指针,而不是 Cards,所以我们需要g_rows * sizeof(Card*)
.然后在每个矩阵行的分配中,
mtr[i] = (Card*)malloc(g_cols * (sizeof (*mtr)) );
malloc 正在为
g_cols * sizeof(Card*)
分配 space。但是由于每个矩阵行都被用来存储卡片,而不是卡片指针,所以我们需要g_cols * sizeof(Card)
。这个错误特别严重,因为 sizeof(Card*) 小于 sizeof(Card),所以没有分配足够的内存。
在从文件中读取数据的while循环中,下面还有一个潜在的问题。只要文件继续,循环就会迭代,而不检查 i
变量是否仍在边界内。因此,如果文件格式不正确,可能会导致此代码注销矩阵的末尾和段错误。
评论:我强烈推荐使用 Valgrind or Address Sanitizer (ASan)。这些工具会自动检查与内存相关的错误,对于调试此类问题非常有用。