0

コンパイルして、私の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;
}
4

2 に答える 2

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 マシンで segfault が発生しないという事実は、嬉しい事故です。

于 2012-04-15T03:00:07.767 に答える
1

valgrindMac OS Xでは、コードが正常に実行されません。

したがって、私はそれを完全なプログラムにラップしました:

#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 OSX10.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()。その後、リークされたメモリは取得されませんでした(「まだ到達可能な」メモリはシステムライブラリにあります。MacOSXでは、すべての実行でvalgrindそのようなメモリがかなりの量になります)。

修正されたコード

彼の答えにおけるGeorgeSkoptsovによる診断は、的を射たものです。この修正されたコードは、有効にすると、の下でエラーなしで機能します。イディオムの使用に注意してください。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()と呼ばれる場所は5つあります。free()と呼ばれる場所も5つあります。そして、5つの割り当てと解放のうちの2つは、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)

学ぶべき教訓

したがって、この短い話から学ぶべきさまざまな教訓があります。

  1. 太陽があなたに問題を指摘してくれたことに感謝してください。
  2. 使用方法を学びますvalgrind
  3. Type *pointer = malloc(sizeof(*pointer));割り当てにイディオムを使用することを検討してください。
于 2012-04-15T04:42:40.673 に答える