我必须创建代表矩阵的链表。 在第一个链表中,我有行coordonate,到下一个节点的链接和到另一个结构的链接,该结构包含列coordonate,到下一个节点的链接以及这些coordonates中矩阵的数字值。以下是我可能更明确的不同结构。
#include "sparsemat.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
matrix* tempMatrix = (matrix*)malloc(sizeof(matrix));
tempMatrix = sp_read("mat_100x5");
return 0;
}
struct matrix* sp_read(char* path) {
matrix* matrice = (matrix*)malloc(sizeof(matrix));
matrice->rowFirst = NULL;
matrice->nRows = 0;
matrice->nCols = 0;
row* rows = (row*)malloc(sizeof(row));
rows->indiceRow = 0;
rows->data = NULL;
rows->next = NULL;
col* cols = (col*)malloc(sizeof(col));
cols->value = 0, 0;
cols->indiceColumn = 0;
cols->next = NULL;
FILE* file = NULL;
file = fopen(path, "rb");
int nRow;
int nCol;
fread(&nRow, sizeof(int), 1, file);
fread(&nCol, sizeof(int), 1, file);
printf("%d , %d \n", nRow, nCol);
int i;
int j;
double* currentDigit = (double*)malloc(sizeof(double));
int count;
for (i = 1; i <= nRow; i++) {
if (i == 1) { // initialize the matrix
matrice->nRows = nRow;
matrice->nCols = nCol;
matrice->rowFirst = rows;
}
rows = pushRow(NULL, &i, matrice);
count = 0;
for (j = 1; j <= nCol; j++) {
fread(currentDigit, sizeof(double), 1, file);
if (*(currentDigit) != 0.0) {
count++;
if (count == 1) { // begin a new column list on the next node of
// the row list
cols = NULL;
rows->data = cols;
}
cols = pushCol(&j, currentDigit, cols);
}
}
}
fclose(file);
free(currentDigit);
return matrice;
}
row* pushRow(col* data, int* rows, matrix* top) {
row* f = NULL;
f = (row*)malloc(sizeof(row));
if (f == NULL) {
exit(EXIT_FAILURE);
}
f = top->rowFirst;
if (f->indiceRow == 0) {
printf("null");
f->data = data;
f->indiceRow = *(rows);
f->next = NULL;
}
else {
while (f->next != NULL) {
f = f->next;
}
row* temp = NULL;
temp = (row*)malloc(sizeof(row));
f->next = temp;
f->next->indiceRow = *(rows);
f->next->data = data;
f = f->next;
}
return f;
}
col* pushCol(int* column, double* value, col* dataRow) {
col* f = NULL;
f = (col*)malloc(sizeof(col));
if (f == NULL) {
exit(EXIT_FAILURE);
}
f = dataRow;
if (f->indiceColumn == 0) {
f->indiceColumn = *(column);
f->value = *(value);
dataRow = f;
}
else {
while (f->next != NULL) {
f = f->next;
}
col* temp = NULL;
temp = (col*)malloc(sizeof(col));
f->next = temp;
f->next->indiceColumn = *(column);
f->next->value = *(value);
f = f->next;
dataRow = f;
}
return dataRow;
}
程序在第35行执行nRows和nCols的printf,但是我收到了分段错误(核心转储)。 我希望我的问题很明确,在此先感谢您的帮助!
答案 0 :(得分:2)
由于您没有向我们展示row
,col
或matrix
的结构定义,因此无法可靠地编译代码。这个问题很糟糕。这也意味着很难猜测数据应该如何组织。看起来你对磁盘文件中的每个数据项都有一个值,但是数据中有足够的零,值得制作一个稀疏矩阵(基于缺少的头文件名中的提示)。
在main()
中,您有内存泄漏:
matrix* tempMatrix = (matrix*)malloc(sizeof(matrix));
tempMatrix = sp_read("mat_100x5");
您从tempMatrix
分配malloc()
,然后使用sp_read()
的结果覆盖它。但是,这不是核心转储问题。
在sp_read()
中,您应该在使用返回的文件指针之前检查fopen()
是否有效。但是,如果第一个fread()
不起作用,你就会崩溃,所以你现在正在逃避它,但不检查fopen()
是不好的做法,因为它失败了。同样,您应该检查每个fread()
以确保获取数据。如果你不这样做,你不应该继续假设你有价值观。同样,如果分配失败,您应该检查每个内存分配的结果并避免崩溃。
在C中,数组边界从0 ... N-1开始,而不是1 .. N.你有:
for (i = 1; i <= nRow; i++) {
if (i == 1) { // initialize the matrix
matrice->nRows = nRow;
matrice->nCols = nCol;
matrice->rowFirst = rows;
}
循环应为for (i = 0; i < nRow; i++)
。与列上的循环类似。
初始化代码应该在循环之外。
pushCol()
中的代码是另一组内存泄漏:
col* pushCol(int* column, double* value, col* dataRow) {
col* f = NULL;
f = (col*)malloc(sizeof(col));
if (f == NULL) {
exit(EXIT_FAILURE);
}
f = dataRow;
您将malloc()
的结果分配给f
;然后用f
中的值覆盖dataRow
,从而泄漏刚刚分配的内存。将f
初始化为null然后分配malloc()
的结果是毫无意义的(但最基本的优化编译器将为您解决这个问题)。只需将malloc()
的结果直接分配到f
。
pushRow()
中的代码同样泄漏了内存:
row* pushRow(col* data, int* rows, matrix* top) {
row* f = NULL;
f = (row*)malloc(sizeof(row));
if (f == NULL) {
exit(EXIT_FAILURE);
}
f = top->rowFirst;
pushCol()
的接口应该更简单;列号和值都不需要是指针 - 您可以通过值传递两者。 pushRow()
的界面可以int rows
代替int *rows
。
顺便说一句,写作:
cols->value = 0, 0;
是一种轻微的浪费;它指定0,但不需要逗号运算符。 (这可能会混淆在您的本地语言环境中将0,0
写为零,但在C中,如果包含小数点,则需要编写0.0
,如果不包含小数点,则该空格将是错误的使用逗号运算符。)
我为稀疏矩阵类型生成了一组定义,如下所示:
typedef struct col col;
typedef struct row row;
typedef struct matrix matrix;
struct col
{
int indiceColumn;
double value;
col *next;
};
struct row
{
int indiceRow;
col *data;
row *next;
};
struct matrix
{
row *rowFirst;
int nRows;
int nCols;
};
我还编写了一个程序来在文件中生成一个非常稀疏的单位矩阵:
#include <stdio.h>
int main(void)
{
int nRows = 5;
int nCols = 10;
fwrite(&nRows, sizeof(nRows), 1, stdout);
fwrite(&nCols, sizeof(nCols), 1, stdout);
for (int i = 0; i < nRows; i++)
{
for (int j = 0; j < nCols; j++)
{
double d = (i == j) ? 1.0 : 0.0;
fwrite(&d, sizeof(d), 1, stdout);
}
}
return 0;
}
在数据文件中,程序启动但在pushCol()
解除引用f
(if (f->indiceColumn == 0)
)时崩溃,强烈指示空指针。
查看调用代码:
if (*(currentDigit) != 0.0) {
count++;
if (count == 1) { // begin a new column list on the next node of
// the row list
cols = NULL;
rows->data = cols;
}
cols = pushCol(&j, currentDigit, cols);
我们可以看到传递给函数时cols
是一个空指针。在函数内部,即参数dataRow
,它被分配给f
,因此您将取消引用空指针。这不是什么大惊喜;这是一个非常常见的崩溃原因。
您将需要重新访问所有内存分配代码,确保不泄漏内存,并更仔细地决定应该分配哪些代码的数据。坦率地说,目前这是一个混乱 - 很难遵循预期的逻辑。看起来每行应该是非零列的链表。使用单位矩阵的数据,每行将具有从其链接的单个列值。但我不相信你已经为所有行结构分配了足够的空间,或者正确地分配了列。