简体   繁体   English

链表分段错误

[英]Linked lists segmentation fault

I have to create linked lists which will represent a matrix.我必须创建代表矩阵的链表。 In the first linked list I have the row coordinate, a link to the next node and a link to another structure which contain the column coordinate, the link to the next node and the value of the number from the matrix at those coordinates.在第一个链表中,我有行坐标、到下一个节点的链接和到另一个结构的链接,其中包含列坐标、到下一个节点的链接以及这些坐标处矩阵的数字值。 Here are my different structures which might be more explicit.这是我的不同结构,可能更明确。

#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;
}

The program execute the printf of the nRows and nCols at the line 35 but then I receive a segmentation fault (core dumped).程序在第 35 行执行 nRows 和 nCols 的 printf,但随后我收到一个分段错误(核心转储)。

Since you've not shown us the structure definitions for row , col or matrix , it is not possible to reliably compile the code.由于您没有向我们展示rowcolmatrix的结构定义,因此无法可靠地编译代码。 That's bad in a question.这在一个问题中很糟糕。 It also means it is hard to guess how the data is supposed to be organized.这也意味着很难猜测数据应该如何组织。 It seems you have a value for every data item in the disk file, but there are enough zeros in the data that it is worth making a sparse matrix (based on the hint in the missing header file name).似乎您对磁盘文件中的每个数据项都有一个值,但是数据中有足够的零值得制作稀疏矩阵(基于丢失的头文件名中的提示)。

In main() , you have a memory leak:main() ,您有内存泄漏:

matrix* tempMatrix = (matrix*)malloc(sizeof(matrix));
tempMatrix = sp_read("mat_100x5");

You assign tempMatrix from malloc() , and then overwrite it with the result of sp_read() .您从malloc()分配tempMatrix ,然后用sp_read()的结果覆盖它。 However, that is not the core dump problem.然而,这不是核心转储问题。

In sp_read() , you should check that the fopen() worked before you use the returned file pointer.sp_read() ,您应该在使用返回的文件指针之前检查fopen()工作。 However, you'd be crashing on the first fread() if it didn't work, so you are getting away with it at the moment, but it is bad practice not to check fopen() because it fails.但是,如果第一个fread()不起作用,您会在第一个fread()上崩溃,因此您目前可以逃脱,但不检查fopen()是不好的做法,因为它失败了。 Similarly, you should be checking each and every fread() to ensure you get data.同样,您应该检查每个fread()以确保您获得数据。 If you don't, you should not continue assuming you got values.如果你不这样做,你不应该继续假设你有价值观。 Similarly, you should check the result of every memory allocation and avert crashes if the allocation fails.同样,您应该检查每个内存分配的结果,并在分配失败时避免崩溃。

In C, array bounds go from 0 .. N-1, not 1 .. N. You have:在 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;
    }

The loop should be for (i = 0; i < nRow; i++) .循环应该是for (i = 0; i < nRow; i++) Similarly with the loop on columns.与列上的循环类似。

The initialize code should be outside the loop.初始化代码应该在循环之外。

The code in pushCol() is another set of memory leaks: 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;

You assign the result of a malloc() to f ;您将malloc()的结果分配给f then you overwrite f with the value in dataRow , thereby leaking the memory you just allocated.然后你用dataRow的值覆盖f ,从而泄漏你刚刚分配的内存。 Initializing f to null and then assigning the result of malloc() is marginally pointless (but the most basic optimizing compiler will fix that for you).f初始化为 null,然后分配malloc()的结果malloc()没有意义(但最基本的优化编译器会为您解决这个问题)。 Simply assign the result of the malloc() directly to f .只需将malloc()的结果直接分配给f

The code in pushRow() is similarly leaking memory: 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;

The interface to pushCol() should be simpler; pushCol()的接口应该更简单; neither the column number nor the value needs to be a pointer — you can pass both by value.列号和值都不需要是指针——您可以通过值传递两者。 The interface to pushRow() could take int rows instead of int *rows . pushRow()的接口可以采用int rows而不是int *rows

Incidentally, writing:顺便写一下:

 cols->value = 0, 0;

is a minor waste;是轻微的浪费; it assigns 0, but there is no need for the comma operator.它分配 0,但不需要逗号运算符。 (This may be confusion with writing 0,0 for zero in your native locale, but in C, you need to write 0.0 if you include a decimal point, and the space would be erroneous if it were not for the use of the comma operator.) (这可能与在您的本地语言环境中将0,0写为 0 混淆,但在 C 中,如果包含小数点,则需要写0.0如果不使用逗号运算符,则空格将是错误的.)


I generated a set of definitions for the sparse matrix type like this:我为稀疏矩阵类型生成了一组定义,如下所示:

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;
};

I also wrote a program to generate an identity matrix in a file, which is pretty sparse:我还编写了一个程序来在文件中生成单位矩阵,它非常稀疏:

#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;
}

With this in a data file, the program starts but crashes in pushCol() dereferencing f ( if (f->indiceColumn == 0) ), strongly indicating a null pointer.在数据文件中,程序启动但在pushCol()取消引用fif (f->indiceColumn == 0) )时崩溃,强烈指示空指针。

Looking at the calling code:查看调用代码:

        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);

We can see that cols when passed to the function is a null pointer.我们可以看到传递给函数的cols是一个空指针。 Inside the function, that is the parameter dataRow , which is assigned to f , so you are dereferencing a null pointer.在函数内部,即分配给f的参数dataRow ,因此您正在取消引用空指针。 That's not a big surprise;这不是什么大惊喜。 it is a very common cause of crashes.这是崩溃的一个非常常见的原因。

To Fix修理

You are going to need to revisit all your memory allocation code, making sure you are not leaking memory, and deciding more carefully which code is supposed to allocate which data.您将需要重新访问所有内存分配代码,确保没有泄漏内存,并更仔细地决定应该分配哪些数据的代码。 Frankly, it is something of a mess at the moment — it is rather hard to follow the intended logic.坦率地说,目前这有点混乱——很难遵循预期的逻辑。 It looks as if each row should be a linked list of non-zero columns.看起来每一行都应该是一个非零列的链表。 With the data for the identity matrix, each row would have a single column value linked from it.对于单位矩阵的数据,每一行都将有一个从中链接的列值。 But I'm not convinced you've allocated enough space for all the row structures, or allocated the columns properly.但是我不相信您已经为所有行结构分配了足够的空间,或者正确分配了列。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM