struct calloc 中的动态数组或指针失败,C

发布于 2024-12-28 18:57:15 字数 1993 浏览 3 评论 0原文

我正在尝试用 C 语言完成稀疏矩阵的分配。我有一个稀疏矩阵作为值和坐标列表保存,并将其转换为耶鲁格式。

我遇到了一个奇怪的内存分配问题,以前似乎没有人见过。我的代码是:

yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;

yale* yale = (struct y*)calloc(1, sizeof(yale));

int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));    
int* JA = (int*)calloc(matrix_elements, sizeof(int));

printf("%d elements\n",matrix_elements);

yale->A = A;      // Value
yale->IA = IA;          // Row (X)
yale->JA = JA;     // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;

list* tmp_list = input->first;

for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
    printf("Input Value: %d \n",tmp_list->point.value);
    A[i] = tmp_list->point.value;
    // Initialise the first row
    if(i == 0) IA[0] = tmp_list->point.x;
    else{
        // Add a new row index
        if(tmp_y != tmp_list->point.x){
            j++;
            IA[j] = i;
            tmp_y = tmp_list->point.x;
        }
    }
    JA[i] = tmp_list->point.y;
    tmp_list = tmp_list->next;
}

for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
    printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->JA[i]);

return yale;
}

这是 yale 的结构:

typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;

但是程序在循环的第一次迭代中的第一个相关 printf 处出现段错误。

      printf("%d,",yale->A[i]);

我很肯定: matrix_elements 是一个整数(在我的测试用例中为 9) 矩阵行数是一个整数 A / IA / JA 都填充了正确的值(如果您在 printf 中将 yale->A 替换为 A,则效果很好)。 直接将数组调用到结构指针不会影响结果。 Mallocing,callocing,而不是类型转换,都没有效果。

感谢 Xcode 和 gdb,我还可以在段错误处看到这一点。结构指针似乎指向数组

I'm attempting to complete an assignment on sparse matrices in C. I have a sparse matrix held as a list of values and coordinates and am converting it to Yale format.

I have run into a strange memory allocation issue that no one seems to have seen before. My code is:

yale* convertMatrix(matrix_list* input){
int matrix_elements = input->elements;
int matrix_rows = input->m;

yale* yale = (struct y*)calloc(1, sizeof(yale));

int* A = (int*)calloc(matrix_elements, sizeof(int));
int* IA = (int*)calloc(matrix_rows + 1, sizeof(int));    
int* JA = (int*)calloc(matrix_elements, sizeof(int));

printf("%d elements\n",matrix_elements);

yale->A = A;      // Value
yale->IA = IA;          // Row (X)
yale->JA = JA;     // Column (Y)
yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;

list* tmp_list = input->first;

for(int i = 0, j = 0, tmp_y = 0; i < matrix_elements && tmp_list!=NULL; i++){
    printf("Input Value: %d \n",tmp_list->point.value);
    A[i] = tmp_list->point.value;
    // Initialise the first row
    if(i == 0) IA[0] = tmp_list->point.x;
    else{
        // Add a new row index
        if(tmp_y != tmp_list->point.x){
            j++;
            IA[j] = i;
            tmp_y = tmp_list->point.x;
        }
    }
    JA[i] = tmp_list->point.y;
    tmp_list = tmp_list->next;
}

for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
    printf("%d,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->JA[i]);

return yale;
}

And here is the struct for yale:

typedef struct y{
int n;
int m;
int elements;
int *IA;
int *JA;
int *A;
} yale;

But the program segfaults at the first relevant printf on the first iteration of the loop.

      printf("%d,",yale->A[i]);

I'm positive:
matrix_elements is an integer (9 in my test case)
matrix_rows is an integer
A / IA / JA are all filled with correct values (if you swap yale->A for A in the printf, it works fine).
Directly callocing the array to the struct pointers doesn't affect the result.
Mallocing, callocing, not typecasting, all no effect.

Thanks to Xcode and gdb I can also see that at the point of the segfault. The structure pointers do NOT seem to point to the arrays

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凤舞天涯 2025-01-04 18:57:15

我建议您在 Valgrind 下运行代码。这应该报告缓冲区溢出错误。 (缓冲区溢出是指写入超出数组末尾的情况)。

我还建议您为代码编写一些单元测试。它们对于检测错误非常有帮助。特别是,我建议您使用 3x3 输入矩阵编写一个测试,每个位置都有一个值。检查您得到的值是否符合您的预期。

I suggest you run your code under Valgrind. This should report the buffer overflow error. (A buffer overflow is where you write past the end of an array).

I also recommend you write some unit tests for your code. They can be very helpful detecting bugs. In particular, I suggest you write a test with a 3x3 input matrix with a value in every position. Check that the values you get out are what you expect.

萌︼了一个春 2025-01-04 18:57:15

为了编译它,我需​​要将其添加到代码片段中:

#include <stdlib.h>
#include <stdio.h>

typedef struct y{
        int n;
        int m;
        int elements;
        int *IA;
        int *JA;
        int *A;
        } yale;

typedef struct list {
        struct list *next;
        struct point { int x,y,value; } point;
        } list;

typedef struct matrix_list {
        int elements;
        int m;
        int n;
        struct list *first;
        int *point;
        } matrix_list;

更新:我将程序转换为更具可读性的内容(恕我直言)。我一点也不知道 IA 和 JA 应该做什么,但下面的片段应该相当于 OP。

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

struct y {
        unsigned int n;
        unsigned int m;
        unsigned int elements;
        unsigned int *IA;
        unsigned int *JA;
        int *A;
        } ;

struct list {
        struct list *next;
        struct point { unsigned int x,y; int value; } point;
        } ;

struct matrix_list {
        unsigned int elements;
        unsigned int m;
        unsigned int n;
        struct list *first;
        } ;

struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;

struct y *yale ;
struct list *tmp_list ;

yale = calloc(1, sizeof *yale);
assert (yale != NULL);

printf("%u elements\n",matrix_elements);

yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);

yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;

    // Initialise the first row, set start condition
        // FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
    printf("Input Value: %d \n",tmp_list->point.value);
    yale->A[ii] = tmp_list->point.value;
        // Add a new row index
    if(tmp_y != tmp_list->point.x){
        jj++;
        yale->IA[jj] = ii;
        tmp_y = tmp_list->point.x;
    }
    yale->JA[ii] = tmp_list->point.y;
    if (++ii >= matrix_elements ) break;
}

for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
    printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
    printf("%u,",yale->JA[i]);

return yale;
}

注意:我将 (ii == 0) {} 条件移出了循环,并用两个字母的等效项替换了一个字母的索引。另外:所有索引都是无符号的(因为它们应该是)

To get it compiled, I need to prepend this to the snippet:

#include <stdlib.h>
#include <stdio.h>

typedef struct y{
        int n;
        int m;
        int elements;
        int *IA;
        int *JA;
        int *A;
        } yale;

typedef struct list {
        struct list *next;
        struct point { int x,y,value; } point;
        } list;

typedef struct matrix_list {
        int elements;
        int m;
        int n;
        struct list *first;
        int *point;
        } matrix_list;

UPDATE: I transformed the program into something more readable (IMHO). I don't have the faintest idea what the IA and JA are supposed to do, but the below fragment should be equivalent to the OP.

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

struct y {
        unsigned int n;
        unsigned int m;
        unsigned int elements;
        unsigned int *IA;
        unsigned int *JA;
        int *A;
        } ;

struct list {
        struct list *next;
        struct point { unsigned int x,y; int value; } point;
        } ;

struct matrix_list {
        unsigned int elements;
        unsigned int m;
        unsigned int n;
        struct list *first;
        } ;

struct y *convertMatrix(struct matrix_list* input)
{
unsigned int matrix_elements = input->elements;
unsigned int matrix_rows = input->m;
unsigned int ii,jj,tmp_y;

struct y *yale ;
struct list *tmp_list ;

yale = calloc(1, sizeof *yale);
assert (yale != NULL);

printf("%u elements\n",matrix_elements);

yale->A = calloc(matrix_elements, sizeof *yale->A);
assert (yale->A != NULL);
yale->IA = calloc(matrix_rows + 1, sizeof *yale->IA);
assert (yale->IA != NULL);
yale->JA = calloc(matrix_elements, sizeof *yale->JA);
assert (yale->JA != NULL);

yale->elements = matrix_elements;
yale->m = matrix_rows;
yale->n = input->n;

    // Initialise the first row, set start condition
        // FIXME: this ignores the empty list or size=0 cases
yale->IA[0] = tmp_y = input->first->point.x;
ii = jj = 0;
for(tmp_list = input->first ;tmp_list; tmp_list = tmp_list->next) {
    printf("Input Value: %d \n",tmp_list->point.value);
    yale->A[ii] = tmp_list->point.value;
        // Add a new row index
    if(tmp_y != tmp_list->point.x){
        jj++;
        yale->IA[jj] = ii;
        tmp_y = tmp_list->point.x;
    }
    yale->JA[ii] = tmp_list->point.y;
    if (++ii >= matrix_elements ) break;
}

for(int i = 0; i < matrix_elements; i++)
    printf("%d,",yale->A[i]);
printf("\n");
for(int i = 0; i < matrix_rows + 1; i++)
    printf("%u,",yale->IA[i]);
printf("\n");
for(int i = 0; i < matrix_elements; i++)
    printf("%u,",yale->JA[i]);

return yale;
}

Note: I moved the (ii == 0) {} condition out of the loop, and replaced the one-letter indices by there two-letter equivalents. Also: all the indices are unsigned (as they should be)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文