2017-10-07 10 views
0

Valgrind에서 프로그램을 실행하면 구조체의 전환 포인터에 "크기가 8 번 잘못되었습니다"라는 메시지가 표시됩니다. 그것은 calloc과 관련이 있습니까? 있는 그대로 읽으면 (nil)입니다. 다음과 같이구조체 포인터 필드를 읽는 것이 유효하지 않은 이유는 무엇입니까?

은, 그것이 사용되는 구조체 (라고 트라이)을 갖는

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

: valgrid 읽기를 시도 할 때 다음

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

, 그것은 "규모 8의 잘못된 읽기 말한다" 숯 * 핀에서 동일한 메시지 :

//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의 출력 :

,536,913,632 10
==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

: 강한 조언 뒤에 포인터를 숨길 수 typedef. – wildplasser

+0

구조체에 대한 예제 중 하나에서 '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 바이트 값을 읽으려고합니다.

이 주소는 malloc을 통해 할당 된 8 바이트 블록 바로 다음에 createTrie입니다. 즉,이 라인은 :

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

'trie = malloc (sizeof * trie);로 변경하면 여전히'trie'에 8 바이트의 크기가 생성됩니다. 이것은 trie가 포인터이기 때문입니다. –

+0

@SeanWalsh 아니요 아니요.'sizeof * trie'는'trie'가 가리키는 타입의 크기를 알려줍니다. – melpomene

+0

고맙습니다. –