分段错误.我错在哪里?三.



我需要在C语言中实现动态矩阵。

我主要有这段代码:

#include <stdio.h>
#include <stdlib.h>
int main() {
int rows, cols;
scanf("%d", &rows);
scanf("%d", &cols);
int** A = create_matrix(rows, cols);
fill_matrix(A, rows, cols);
add_row(A, &rows, cols);
print_matrix(A, rows, cols);
free_matrix(A, rows);
return 0;
}

如您所见,我分配矩阵,然后通过以下方式填充它:

4 3
1 1 1
2 2 2
3 3 3
4 4 4

我想添加新行 [1, 1, 1],然后打印,然后自由。以下是函数

void add_row(int **matrix, int *rows_amount, int cols_amount)
{
printf("startedn");
(*rows_amount)++;
matrix = (int**)realloc(matrix, (*rows_amount) * sizeof(int*));
matrix[*rows_amount - 1] = (int*)malloc(cols_amount * sizeof(int));
for (int j = 0; j < cols_amount; j++)
matrix[*rows_amount - 1][j] = 1;
printf("endedn");
return;
}
int **create_matrix(int rows_amount, int cols_amount) 
{
int **matrix = (int**)malloc(rows_amount * sizeof(int*));
for(int i = 0; i < rows_amount; i++) 
matrix[i] = (int*)malloc(cols_amount * sizeof(int));
return matrix;
}
void fill_matrix(int **matrix, int rows_amount, int cols_amount) 
{
for(int i = 0; i < rows_amount; i++)  
for(int j = 0; j < cols_amount; j++)
scanf("%d", matrix[i] + j);
}
void free_matrix(int **matrix, int rows_amount) 
{
for(int i = 0; i < rows_amount; i++)  
free(matrix[i]);
free(matrix);
}
void print_matrix(int **matrix, int rows_amount, int cols_amount) 
{
for(int i = 0; i < rows_amount; i++)
{
for(int j = 0; j < cols_amount; j++)  
printf("%d ", matrix[i][j]);
printf("n");
}
}

当我使用 valgrind 找到导致 SEGFAULT 的线时,我得到这个:

stepan@WIN-KBCGJ2G97TU:/mnt/d/Desktop/study/sem3/c_prog/lab_09$ valgrind ./app.out < 1.txt 
==2715== Memcheck, a memory error detector
==2715== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2715== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2715== Command: ./app.out // I add < d.txt which contains test
==2715==
==2715== error calling PR_SET_PTRACER, vgdb might block
started // between this and next lines no errors! this is in add_row
ended
==2715== Invalid read of size 8
==2715==    at 0x1089F9: print_matrix (matrix.c:33)
==2715==    by 0x109048: main (main.c:19)
==2715==  Address 0x522e080 is 0 bytes inside a block of size 32 free'd
==2715==    at 0x4C31D2F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)      
==2715==    by 0x108DC5: add_row (matrix.c:102)
==2715==    by 0x109034: main (main.c:17)
==2715==  Block was alloc'd at
==2715==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)       
==2715==    by 0x1088A9: create_matrix (matrix.c:8)
==2715==    by 0x109006: main (main.c:11)
==2715==
1 1 1
2 2 2
3 3 3
4 4 4 // on the next line must have been 1 1 1
==2715== Invalid read of size 4
==2715==    at 0x108A09: print_matrix (matrix.c:33)
==2715==    by 0x109048: main (main.c:19)
==2715==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==2715==
==2715==
==2715== Process terminating with default action of signal 11 (SIGSEGV)
==2715==  Access not within mapped region at address 0x0
==2715==    at 0x108A09: print_matrix (matrix.c:33)
==2715==    by 0x109048: main (main.c:19)
==2715==  If you believe this happened as a result of a stack
==2715==  overflow in your program's main thread (unlikely but
==2715==  possible), you can try to increase the size of the
==2715==  main thread stack using the --main-stacksize= flag.
==2715==  The main thread stack size used in this run was 8388608.
==2715== 
==2715== HEAP SUMMARY:
==2715==     in use at exit: 100 bytes in 6 blocks
==2715==   total heap usage: 9 allocs, 3 frees, 8,324 bytes allocated
==2715==
==2715== LEAK SUMMARY:
==2715==    definitely lost: 40 bytes in 1 blocks
==2715==    indirectly lost: 60 bytes in 5 blocks
==2715==      possibly lost: 0 bytes in 0 blocks
==2715==    still reachable: 0 bytes in 0 blocks
==2715==         suppressed: 0 bytes in 0 blocks
==2715== Rerun with --leak-check=full to see details of leaked memory
==2715==
==2715== For counts of detected and suppressed errors, rerun with: -v
==2715== ERROR SUMMARY: 14 errors from 2 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

所以,似乎有些事情发生在add_row:

matrix = (int**)realloc(matrix, (*rows_amount) * sizeof(int*));
matrix[*rows_amount - 1] = (int*)malloc(cols_amount * sizeof(int));

这是真的 99.9%,因为不添加行,只需创建、填充和释放,没有内存错误。

而且我不明白为什么Invalid read of size 8在所有打印行之前(matrix.c:33printf("%d ", matrix[i][j]);(,然后他尝试读取 4 个字节 ̄_(ツ(_/̄。

怎么了?

更新。

我添加了返回矩阵;在主 A = add_row... 它有效!感谢大家的C记忆课:)

add_row函数修改matrix并使旧值无效,但不会将新值返回给调用方。

问题是add_row()通过realloc()更改matrix的值,但调用函数 - 在main(),也许? 没有看到这种变化。

同样,如果add_row()更改了cols_amount的值,则调用者将看不到该更改。你不在乎这个。

但是您确实关心计数更改对调用方可见,因此您正确传递了rows_amount的地址,以便当add_row()将一个添加到行计数时,调用方会看到该更改。

通过传递指针的地址对matrix执行相同的操作:

int add_row(int ***pMatrix, int *rows_amount, int cols_amount)
{
(*pMatrix) = realloc(*pMatrix, ...)
(*pMatrix)[*rows_amount - 1] = ...
// use (*pMatrix) where you used to use matrix
}
int main()
{
...
add_row(&matrix, &rows, cols);

编辑:从评论中回答一些问题;

当您分配内存时,该空间将为您保留,并且您会得到一个指针,并且下一个内存请求通常在第一个请求之后立即分配,可能由一些填充或内务管理隔开。 这意味着第一个和第二个分配或多或少彼此相邻。

|---alloc1---|
|---alloc1---| |---alloc2---|

realloc(alloc1)返回相同指针的唯一方法是分配是否有可用空间:如果发生这种情况,那么它将调整内务处理并返回相同的指针。

但在这里我们发现alloc2挡住了,没有空间扩展alloc1,所以它别无选择,只能保留一个新的位置,复制东西过来,然后发布第一个:

|---alloc1---|
|---alloc1---| |---alloc2---|
|---alloc2---| |---bigger alloc1-------|

我想向realloc()请求更少的内存会返回相同的指针,因为它可以更新内务管理,但这不是必需的,实际上你永远不会依赖它。

EDIT2在实践中,我不会以这种方式解决问题。我会创建一个结构来保存指针加上行/列计数,这样它就可以作为单个项目传递,而不是一次传递所有三个部分。

struct matrix {
int rows;
int cols;
int **cells;
};

相关内容

  • 没有找到相关文章

最新更新