我遇到了2D阵列损坏的问题。请考虑以下代码:
int **generate_clique_adjacency_matrix(const formula f) {
int num_terms = f.num_clauses * kVarsPerClause;
printf("\nnum_terms: %d\n", num_terms);
// construct a 2D array of appropriate size
int **compatible = malloc(sizeof(int) * num_terms);
for (int i = 0; i < num_terms; i++) {
compatible[i] = malloc(sizeof(int) * num_terms);
// initialize every cell to 0
for (int j = 0; j < num_terms; j++) {
printf("writing 0 to (%d, %d)\n", i, j);
compatible[i][j] = 0;
}
}
printf("num_terms: %d\n", num_terms);
printf("matrix:\n");
for (int i = 0; i < num_terms; i++) {
printf("row %d: ", i);
for (int j = 0; j < num_terms; j++) {
printf("%d ", compatible[i][j]);
}
printf("\n");
}
exit(0);
}
产生令人震惊的产出:
num_terms: 6
writing 0 to (0, 0)
writing 0 to (0, 1)
writing 0 to (0, 2)
writing 0 to (0, 3)
writing 0 to (0, 4)
writing 0 to (0, 5)
writing 0 to (1, 0)
writing 0 to (1, 1)
writing 0 to (1, 2)
writing 0 to (1, 3)
writing 0 to (1, 4)
writing 0 to (1, 5)
writing 0 to (2, 0)
writing 0 to (2, 1)
writing 0 to (2, 2)
writing 0 to (2, 3)
writing 0 to (2, 4)
writing 0 to (2, 5)
writing 0 to (3, 0)
writing 0 to (3, 1)
writing 0 to (3, 2)
writing 0 to (3, 3)
writing 0 to (3, 4)
writing 0 to (3, 5)
writing 0 to (4, 0)
writing 0 to (4, 1)
writing 0 to (4, 2)
writing 0 to (4, 3)
writing 0 to (4, 4)
writing 0 to (4, 5)
writing 0 to (5, 0)
writing 0 to (5, 1)
writing 0 to (5, 2)
writing 0 to (5, 3)
writing 0 to (5, 4)
writing 0 to (5, 5)
num_terms: 6
matrix:
row 0: 22661104 0 22661136 0 0 0
row 1: 0 0 0 0 0 0
row 2: 0 0 0 0 0 0
row 3: 0 0 0 0 0 0
row 4: 0 0 0 0 0 0
row 5: 0 0 0 0 0 0
我的阵列是如何被破坏的?显然,第0行中的数据应全为零。我甚至尝试添加断言以确保malloc
成功。这让我疯了。
答案 0 :(得分:4)
这是错误的:
int **compatible = malloc(sizeof(int) * num_terms);
您需要为 n 指向int
预留空间(不适用于 n int
)
更改为
int **compatible = malloc(sizeof(int *) * num_terms);
或更好
int **compatible = malloc(sizeof(*compatible) * num_terms);
答案 1 :(得分:2)
改变这个:
int **compatible = malloc(sizeof(int) * num_terms);
到此:
int **compatible = malloc(sizeof(int *) * num_terms);
因为第一个维度是一个指针数组。
不要忘记最后释放内存:
for (int i = 0; i < num_terms; i++)
free(compatible[i]);
free(compatible);
答案 2 :(得分:1)
正如其他答案中所指出的,第一次分配需要为指向int
而不是int
的指针分配空间。最好在sizeof
操作数中使用标识符而不是显式类型,以避免在此处出错。此外,您需要检查malloc()
的返回值是否存在分配错误:
int **compatible = malloc(sizeof(*compatible) * num_terms);
if (compatible == NULL) {
fprintf(stderr, "Row allocation error\n");
exit(EXIT_FAILURE);
}
for (int i = 0; i < num_terms; i++) {
compatible[i] = malloc(sizeof(**compatible) * num_terms);
if (compatible[i] == NULL) {
fprintf(stderr, "Column allocation error\n");
exit(EXIT_FAILURE);
}
// initialize every cell to 0
for (int j = 0; j < num_terms; j++) {
printf("writing 0 to (%d, %d)\n", i, j);
compatible[i][j] = 0;
}
}
更好的方法是在分配中使用VLA,为num_terms
num_terms
的{{1}}数组分配空间,并将结果分配给指向数组的指针int
的。{这种方法的优点是分配的内存是连续的,如果分配失败,int
将返回空指针。您还应该将malloc()
类型用于数组索引,因为此类型可以保证能够保存任何数组索引。
size_t
如果您的阵列不是太大(这取决于系统),您可以简单地使用VLA。请注意,无法检测到VLA的分配错误。
int (*compatible)[num_terms] = malloc(sizeof(*compatible) * num_terms);
if (compatible == NULL) {
fprintf(stderr, "Allocation error\n");
exit(EXIT_FAILURE);
}
// initialize every cell to 0
for (size_t i = 0; i < num_terms; i++) {
for (size_t j = 0; j < num_terms; j++) {
printf("writing 0 to (%zu, %zu)\n", i, j);
compatible[i][j] = 0;
}
}