2017-10-07 16 views
0

は、それが構造体の遷移ポインタで「サイズ8の不正読み取り」があると述べています。それはcallocと関係がありますか?そのまま読むと(nil)です。 (トライと呼ばれる)の構造体を持つ構造体ポインタフィールドの読み込みが無効なのはなぜですか? <a href="http://valgrind.org/" rel="nofollow noreferrer">Valgrind</a>でプログラムを実行する

が、それは次のように使用されます。

ここ
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <limits.h> 

const int MAX_SIZE = 20; 

struct _trie { 
    int maxNode; 
    int nextNode; 
    int** transition; 
    char* fin; 
}; 

typedef struct _trie * Trie; 

Trie createTrie (int maxNode){ 

    Trie trie; 

    trie = (Trie) malloc(sizeof(Trie)); 

    printf("size of trie: %lu, size of the struct: %lu, size of _trie: %lu\n",sizeof(trie),sizeof(Trie), sizeof(struct _trie)); 

    trie->maxNode = maxNode; 

    printf("maxNode = %d, size of maxNode: %lu\n",trie->maxNode,sizeof(trie->maxNode)); 
    printf("size of nextNode : %lu, size of transition: %lu, size of fin: %lu\n", 
      sizeof(trie->nextNode),sizeof(trie->transition),sizeof(trie->fin)); 

を、valgridを読み取ろうとするとき、それは "サイズ8の不正読み取り" と言う:

//invalid read 
    printf("transitions points to: %p, address: %p\n",trie->transition,&trie->transition); 

char *フィンから同じメッセージ:

//invalid read 
    printf("fin points to: %p, address: %p\n",trie->fin,&trie->fin); 

    getchar(); 

    trie->transition = (int**)calloc(maxNode,sizeof(int*)); 

    printf("trie->transition done.\n"); 
    printf("transitions points to: %p, address: %p\n",trie->transition,&trie->transition); 

    if(trie->transition == NULL){ 
     printf("null for trie->transition\n"); 
     exit(0); 
    } 

    printf("Size of transition: %lu, size of int:%lu, pointer: %p\n\n",sizeof(trie->transition),sizeof(int),trie->transition); 

    for(int counter = 0; counter < maxNode; ++counter){ 

     trie->transition[counter] = calloc(UCHAR_MAX,sizeof(int)); 

     if(trie->transition[counter] == NULL){ 
      printf("null for trie->transition[%d]\n",counter); 
      exit(0); 
     } 

     //printf("size of transition[%d]: %lu\n",counter,sizeof(trie->transition[counter])); 

    } 


    printf("\nFilling up trie->transition\n"); 


    for(int counter = 0; counter < maxNode; ++counter){ 


     for(int counter2 = 0; counter2 < UCHAR_MAX; ++counter2){ 

      trie->transition[counter][counter2] = -1; 

      //printf("size of transition[%d][%d]: %lu, value: %d\n",counter,counter2,sizeof(trie->transition[counter]),trie->transition[counter][counter2]); 

     } 

     //getchar(); 
    } 

    return (trie); 
} 

void free_all(Trie trie){ 

    for(int counter = 0; counter < trie->maxNode; ++counter){ 

     free(trie->transition[counter]); 

    } 

    free(trie->transition); 
    free(trie); 
} 

int main(int argc, char *argv[]){ 

    Trie trie = createTrie(MAX_SIZE); 

    free_all(trie); 
    return (0); 
} 

Valgrindの出力:

==3079== Memcheck, a memory error detector 
==3079== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
==3079== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info 
==3079== Command: ./debug_test 
==3079== 
size of trie: 8, size of the struct: 8, size of _trie: 24 
maxNode = 20, size of maxNode: 4 
size of nextNode : 4, size of transition: 8, size of fin: 8 
==3079== Invalid read of size 8 
==3079== at 0x1088AD: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
transitions points to: (nil), address: 0x5201048 
==3079== Invalid read of size 8 
==3079== at 0x1088D1: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201050 is 8 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
fin points to: (nil), address: 0x5201050 

==3079== Invalid write of size 8 
==3079== at 0x108907: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
trie->transition done. 
==3079== Invalid read of size 8 
==3079== at 0x108923: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
transitions points to: 0x5201910, address: 0x5201048 
==3079== Invalid read of size 8 
==3079== at 0x10893F: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
==3079== Invalid read of size 8 
==3079== at 0x108962: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
Size of transition: 8, size of int:4, pointer: 0x5201910 

==3079== Invalid read of size 8 
==3079== at 0x108991: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
==3079== Invalid read of size 8 
==3079== at 0x1089B9: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 

Filling up trie->transition 
==3079== Invalid read of size 8 
==3079== at 0x108A20: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
==3079== Invalid read of size 8 
==3079== at 0x108A84: free_all (in /projects/trie/debug_test) 
==3079== by 0x108AF8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
==3079== Invalid read of size 8 
==3079== at 0x108AB3: free_all (in /projects/trie/debug_test) 
==3079== by 0x108AF8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== 
==3079== 
==3079== HEAP SUMMARY: 
==3079==  in use at exit: 0 bytes in 0 blocks 
==3079== total heap usage: 24 allocs, 24 frees, 22,616 bytes allocated 
==3079== 
==3079== All heap blocks were freed -- no leaks are possible 
==3079== 
==3079== For counts of detected and suppressed errors, rerun with: -v 
==3079== ERROR SUMMARY: 5167 errors from 11 contexts (suppressed: 0 from 0) 
+4

'トライ=(トライ)はmalloc(はsizeof(トライ));' - > 'トライ=(トライ)はmalloc(はsizeof(*トライ));' – BLUEPIXY

+2

プラス:背後にポインタを非表示にしないための強力なアドバイスtypedefs。 – wildplasser

+0

私が構造体をやっている例の1つでは、 'typedef struct _trie * Trie;'のようなものでした。しかし、今私はそうすることは良い習慣ではないことがわかります。 –

答えて

0
==3079== Invalid read of size 8 
==3079== at 0x1088AD: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 
==3079== Address 0x5201048 is 0 bytes after a block of size 8 alloc'd 
==3079== at 0x4C2DB2F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3079== by 0x108835: createTrie (in /projects/trie/debug_test) 
==3079== by 0x108AE8: main (in /projects/trie/debug_test) 

これは、コードが無効なアドレスから8バイトの値を読み取ろうとしていると言います。

このアドレスはちょうどcreateTriemalloc経由で割り当てられた8バイトのブロックの後にあります。言い換えれば、この行:

trie = (Trie) malloc(sizeof(Trie)); 

は、なぜそれがメモリの唯一の8バイトにtrieのポイントを考えていますか?あなたがsizeof (Trie)バイトを割り当てられ、Trie

typedef struct _trie * Trie; 

つまり上にあるので、あなたが全体の構造体のための十分なメモリを割り当てることを意図するとき、あなたはポインタのためのメモリを割り当てられました。

ことを強くまさにこの理由のため、typedefの背後にポインタを非表示にすることは推奨されません。

推奨修正:

typedef struct Trie Trie; 
struct Trie { 
    int maxNode; 
    int nextNode; 
    int** transition; 
    char* fin; 
}; 

Trie *createTrie(int maxNode) { 

    Trie *trie; 

    trie = malloc(sizeof *trie); 

注:

  • 何かが不混乱しているので、我々は両方のstruct Trieと(裸)Trieに同じ名前(Trie)を使用します。
  • すべてのポインタは目に見えて*で、ポインタとして宣言されています。
  • それはエラーの別の潜在的な供給源になるので、我々はmallocの戻り値をキャストしないでください。
  • trieが宣言されているにもかかわらず、trieが指し示すタイプの正しいバイト数を取得するために、sizeof *trieを使用します。
+0

は 'トライ= malloc関数(*はsizeofトライ)への変更;'依然としてtrie' 'のためにサイズの8つのバイトを生成します。これは、trieがポインタなので、そうですか? –

+0

@SeanWalshいいえ、いいえ。'sizeof * trie'は' trie'が指し示すどんな型のサイズでも与えます。 – melpomene

+0

ありがとう、ありがとう。 –

関連する問題