它编译并运行在我的Linux机箱(Ubuntu)以及x86和x64的其他linux机箱上,但是在SunOS Generic_142900-02 sun4u sparc unix机箱上,它在线路上崩溃
matrix->col_head[i] = col_h;
发生总线错误,另外,当我用GCC -G编译它时,GDB无法找到任何有争议的符号
以下是代码:
typedef unsigned short short_u;
typedef struct node{
short_u row;
short_u col;
int value;
struct node* row_l;
struct node* col_l;
}node_t;
typedef struct matrix{
short_u N;
node_t** row_head;
node_t** col_head;
}matrix_t;
matrix_t* init_matrix(int N){
matrix_t* matrix = malloc(sizeof(matrix_t*));
matrix->row_head = malloc(sizeof(node_t*)*N);
matrix->col_head = malloc(sizeof(node_t*)*N);
matrix->N = N;
for (int i = 0; i < N; i++){
/* row */
node_t* row_h = malloc(sizeof(node_t*));
row_h->col = 0;
row_h->row = i+1;
row_h->value = 0;
row_h->col_l = row_h;
if (i != 0)
matrix->row_head[i-1]->row_l = row_h;
matrix->row_head[i] = row_h;
/* col */
node_t* col_h = malloc(sizeof(node_t*));
col_h->col = i+1;
col_h->row = 0;
col_h->value = 0;
col_h->row_l = col_h;
if (i != 0)
matrix->col_head[i-1]->col_l = col_h;
matrix->col_head[i] = col_h;
}
matrix->row_head[N-1]->row_l = matrix->row_head[0];
matrix->col_head[N-1]->col_l = matrix->col_head[0];
return matrix;
}
答案 0 :(得分:2)
当你这样做时
matrix_t* matrix = malloc(sizeof(matrix_t*));
您将指针的空间分配给matrix_t
,这对于整个matrix_t
来说是不够的。您的总线错误可能是在matrix->row_head
和matrix->col_head
访问未分配内存的结果。
你在行
中重复这个错误 node_t* row_h = malloc(sizeof(node_t*));
和
node_t* col_h = malloc(sizeof(node_t*));
您在Linux计算机上没有遇到段错误这一事实是一件幸事。
答案 1 :(得分:1)
您的代码在Mac OS X上的valgrind
下无法正常运行。
我把它包装成一个完整的程序:
#include <stdlib.h>
#include <stdio.h>
typedef unsigned short short_u;
typedef struct node{
short_u row;
short_u col;
int value;
struct node* row_l;
struct node* col_l;
}node_t;
typedef struct matrix{
short_u N;
node_t** row_head;
node_t** col_head;
}matrix_t;
static matrix_t* init_matrix(int N){
matrix_t* matrix = malloc(sizeof(matrix_t*));
matrix->row_head = malloc(sizeof(node_t*)*N);
matrix->col_head = malloc(sizeof(node_t*)*N);
matrix->N = N;
for (int i = 0; i < N; i++){
/* row */
node_t* row_h = malloc(sizeof(node_t*));
row_h->col = 0;
row_h->row = i+1;
row_h->value = 0;
row_h->col_l = row_h;
if (i != 0)
matrix->row_head[i-1]->row_l = row_h;
matrix->row_head[i] = row_h;
/* col */
node_t* col_h = malloc(sizeof(node_t*));
col_h->col = i+1;
col_h->row = 0;
col_h->value = 0;
col_h->row_l = col_h;
if (i != 0)
matrix->col_head[i-1]->col_l = col_h;
matrix->col_head[i] = col_h;
}
matrix->row_head[N-1]->row_l = matrix->row_head[0];
matrix->col_head[N-1]->col_l = matrix->col_head[0];
return matrix;
}
#if 0
static void free_matrix(matrix_t *matrix)
{
for (int i = 0; i < matrix->N; i++)
{
free(matrix->row_head[i]);
free(matrix->col_head[i]);
}
free(matrix->row_head);
free(matrix->col_head);
free(matrix);
}
#endif /* 0 */
int main(void)
{
matrix_t *m = init_matrix(100);
//free_matrix(m);
return(0);
}
它干净利落地编译。它在Mac OS X 10.7.3上实际运行时没有崩溃。
valgrind
然而,valgrind
抱怨这样(我称之为程序xx
,来源为xx.c
):
==73807== Memcheck, a memory error detector
==73807== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==73807== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==73807== Command: ./xx
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000D11: init_matrix (xx.c:21)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005128 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000D2F: init_matrix (xx.c:22)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005130 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000D8A: init_matrix (xx.c:30)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005840 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000D5A: init_matrix (xx.c:26)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000DB7: init_matrix (xx.c:33)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005128 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000E0A: init_matrix (xx.c:39)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005888 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000DDA: init_matrix (xx.c:35)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000E37: init_matrix (xx.c:42)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005130 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000D9A: init_matrix (xx.c:32)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005128 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000DAF: init_matrix (xx.c:32)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005838 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000D5A: init_matrix (xx.c:26)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000E1A: init_matrix (xx.c:41)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005130 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000E2F: init_matrix (xx.c:41)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005890 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000DDA: init_matrix (xx.c:35)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000E64: init_matrix (xx.c:44)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005128 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000E79: init_matrix (xx.c:44)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005128 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000E80: init_matrix (xx.c:44)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100009618 is 0 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000D5A: init_matrix (xx.c:26)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000E88: init_matrix (xx.c:45)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005130 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid read of size 8
==73807== at 0x100000E9D: init_matrix (xx.c:45)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100005130 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000CF2: init_matrix (xx.c:20)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807== Invalid write of size 8
==73807== at 0x100000EA4: init_matrix (xx.c:45)
==73807== by 0x100000EE3: main (xx.c:66)
==73807== Address 0x100009670 is 8 bytes after a block of size 8 alloc'd
==73807== at 0xB823: malloc (vg_replace_malloc.c:266)
==73807== by 0x100000DDA: init_matrix (xx.c:35)
==73807== by 0x100000EE3: main (xx.c:66)
==73807==
==73807==
==73807== HEAP SUMMARY:
==73807== in use at exit: 5,303 bytes in 235 blocks
==73807== total heap usage: 235 allocs, 0 frees, 5,303 bytes allocated
==73807==
==73807== LEAK SUMMARY:
==73807== definitely lost: 1,608 bytes in 3 blocks
==73807== indirectly lost: 1,600 bytes in 200 blocks
==73807== possibly lost: 0 bytes in 0 blocks
==73807== still reachable: 2,095 bytes in 32 blocks
==73807== suppressed: 0 bytes in 0 blocks
==73807== Rerun with --leak-check=full to see details of leaked memory
==73807==
==73807== For counts of detected and suppressed errors, rerun with: -v
==73807== ERROR SUMMARY: 804 errors from 16 contexts (suppressed: 1 from 1)
当我启用free_matrix()
功能时,我又遇到了一些错误,但我相信它们是init_matrix()
中问题的后果。然后我没有得到任何泄露的内存('仍然可以访问'内存在系统库中; valgrind
的所有运行在Mac OS X上都有相当大的内存量。)
他George Skoptsov answer的诊断是正确的。启用了free_matrix()
的此固定代码在valgrind
下无误地运行。注意习语的使用:
SomeType *variable = malloc(sizeof(*variable));
SomeType *arrayvar = malloc(sizeof(*arrayvar) * N);
虽然起初有点不舒服,但这些可以避免您遇到的问题。我想记住使用它们;我还在重新学习那些在很久以前学到的技术,以至于我正在遭受“很难教老狗的新技巧”。
#include <stdlib.h>
#include <stdio.h>
typedef unsigned short short_u;
typedef struct node{
short_u row;
short_u col;
int value;
struct node* row_l;
struct node* col_l;
}node_t;
typedef struct matrix{
short_u N;
node_t** row_head;
node_t** col_head;
}matrix_t;
static matrix_t* init_matrix(int N){
matrix_t* matrix = malloc(sizeof(*matrix));
matrix->row_head = malloc(sizeof(*matrix->row_head)*N);
matrix->col_head = malloc(sizeof(*matrix->col_head)*N);
matrix->N = N;
for (int i = 0; i < N; i++){
/* row */
node_t* row_h = malloc(sizeof(*row_h));
row_h->col = 0;
row_h->row = i+1;
row_h->value = 0;
row_h->col_l = row_h;
if (i != 0)
matrix->row_head[i-1]->row_l = row_h;
matrix->row_head[i] = row_h;
/* col */
node_t* col_h = malloc(sizeof(*col_h));
col_h->col = i+1;
col_h->row = 0;
col_h->value = 0;
col_h->row_l = col_h;
if (i != 0)
matrix->col_head[i-1]->col_l = col_h;
matrix->col_head[i] = col_h;
}
matrix->row_head[N-1]->row_l = matrix->row_head[0];
matrix->col_head[N-1]->col_l = matrix->col_head[0];
return matrix;
}
static void free_matrix(matrix_t *matrix)
{
for (int i = 0; i < matrix->N; i++)
{
free(matrix->row_head[i]);
free(matrix->col_head[i]);
}
free(matrix->row_head);
free(matrix->col_head);
free(matrix);
}
int main(void)
{
matrix_t *m = init_matrix(100);
free_matrix(m);
return(0);
}
有五个地方叫malloc()
;还有五个地方叫free()
。五个分配和释放中的两个是0..N-1循环,这些循环都很好地平衡。
valgrind
==73943== Memcheck, a memory error detector
==73943== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==73943== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==73943== Command: ./xx
==73943==
==73943==
==73943== HEAP SUMMARY:
==73943== in use at exit: 2,095 bytes in 32 blocks
==73943== total heap usage: 235 allocs, 203 frees, 8,519 bytes allocated
==73943==
==73943== LEAK SUMMARY:
==73943== definitely lost: 0 bytes in 0 blocks
==73943== indirectly lost: 0 bytes in 0 blocks
==73943== possibly lost: 0 bytes in 0 blocks
==73943== still reachable: 2,095 bytes in 32 blocks
==73943== suppressed: 0 bytes in 0 blocks
==73943== Rerun with --leak-check=full to see details of leaked memory
==73943==
==73943== For counts of detected and suppressed errors, rerun with: -v
==73943== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
因此,从这个简短的故事中可以学习各种课程:
valgrind
。Type *pointer = malloc(sizeof(*pointer));
惯用语进行分配。