2016-08-28 3 views
-3

다음은 프로그램 초기화시 생성 된 동적으로 할당 된 구조의 수를 모니터하는 C 프로그램입니다. 구조체는 현재 (fd) 베어 본 요구 사항을 가지고 있습니다. 그것은 파일 기술자에게 C Valgrind stacktrace fail, 구조체의 선형 malloc 배열

  • 매치 적절한 일치를위한
  • 그들을 통해
  • 검색에서 그들을 채 웁니다 N 구조의 메모리를 초기화하고 너무 많은이있는 경우 주변에 루프를 수행

    1. 효과적으로

      ,

    문제는 valgrind와 관련이 있습니다 ... 나는 내가 무엇을 잘못하고 있는지 알지 못합니다. 포인터, 구조 등 ... 여기

    코드입니다 : ...이 원인이 뭐죠 내가 아무 생각이

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <stdint.h> 
    #include <unistd.h> 
    #include <time.h> 
    #include <ctype.h> 
    #include <string.h> 
    #include <sys/socket.h> 
    #include <sys/types.h> 
    #include <netdb.h> 
    
    #define NO_ERROR 0 
    #define DEFAULT_ERROR -1 
    
    typedef struct dev_conn_state_s { 
        int fd; 
    } dev_con_state_t; 
    
    int current_elements = 0; 
    int max_elements = 0; 
    
    int init_datastruct_commhandler(int size, dev_con_state_t ** conn_list); 
    dev_con_state_t *new_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list); 
    dev_con_state_t *search_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list); 
    
    dev_con_state_t *build_insert_element(dev_con_state_t * conn_list, int fd); 
    dev_con_state_t *build_search_element(dev_con_state_t * conn_list, int fd); 
    
    void set_max_conns(int max); 
    extern inline int get_max_conns(void); 
    
    /** 
    * init_datastruct_commhandler(int size, dev_con_state_t ** conn_list) 
    * 
    * @brief initializes large heap and buffer for each device to be tracked 
    * @param size 
    * @param conn_list 
    * @return (-1) for error, 0 for success 
    */ 
    int init_datastruct_commhandler(int size, dev_con_state_t ** conn_list) 
    { 
        printf("Init datahandler memory heap\n"); 
    
        // Quick param check 
        if (size <= 0) { 
         return DEFAULT_ERROR; 
        } 
        current_elements = 0; 
        *conn_list = malloc(sizeof(dev_con_state_t) * size); 
    
        // Check if malloc failed 
        if (*conn_list == NULL) { 
         printf("stack malloc failed\n"); 
         return DEFAULT_ERROR; 
        } 
    
        memset(*conn_list, 0, sizeof(dev_con_state_t) * size); 
    
        printf("Completed datahandler memory heap\n"); 
    
        return NO_ERROR; 
    } 
    
    /** 
    * build_insert_element(dev_con_state_t *conn_list, struct sockaddr_rc in_addr) 
    * @brief Build a static element in the heap and insert 
    * @param conn_list 
    * @param fd 
    * @param in_addr 
    * @param conn if built 
    */ 
    dev_con_state_t *build_insert_element(dev_con_state_t * conn_list, int fd) 
    { 
        //~ dev_con_state_t conn = { 0 }; 
        //~ printf("ob %p\n",fd); 
        //~ conn.fd = fd; 
        //conn.last_activity = time(NULL); 
        printf("a %p %p\n",conn_list,&conn_list); 
    
        return new_datastruct_commhandler_element(fd, conn_list); 
    } 
    
    /** 
    * build_search_element(dev_con_state_t *conn_list) 
    * @brief Build a static element in the heap and search 
    * @param conn_list 
    * @param fd 
    * @param in_addr 
    * @param conn if built 
    */ 
    dev_con_state_t *build_search_element(dev_con_state_t * conn_list, int fd) 
    { 
    
        return search_datastruct_commhandler_element(fd, conn_list); 
    } 
    
    /** 
    * new_datastruct_commhandler_element(dev_con_state_t * conn, dev_con_state_t * conn_list) 
    * 
    * @brief Adds new datastruct to connection tracker heap 
    * @param conn 
    * @param conn_list 
    * @return (-1) for error, 0 for success 
    */ 
    dev_con_state_t *new_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list) 
    { 
    
        //int size = sizeof(dev_con_state_t) * current_elements; 
        printf("%p %p\n",conn_list,&conn_list); 
    
        dev_con_state_t *tmp = conn_list + (sizeof(dev_con_state_t) * current_elements); 
    
        int last_elements = current_elements; 
    
        if (current_elements == (max_elements)) { 
         tmp->fd = fd; 
         current_elements = 0; 
        } else { 
         tmp->fd = fd; 
         current_elements++; 
        } 
    
        return (dev_con_state_t *) conn_list + (sizeof(dev_con_state_t) * last_elements); 
    } 
    
    /** 
    * search_datastruct_commhandler_element(dev_con_state_t * conn, dev_con_state_t * conn_list) 
    * 
    * @brief Searches for datastruct in connection tracker heap 
    * @note USES FD (file descriptor) for NOW! 
    * @param conn 
    * @param conn_list 
    * @return NULL for error, non-NULL for success (aka the element we were tracking) 
    */ 
    dev_con_state_t *search_datastruct_commhandler_element(int fd, dev_con_state_t * conn_list) 
    { 
        int i = 0; 
        dev_con_state_t *tmp = NULL; 
        for (i = 0; i < get_max_conns(); i++) { 
         tmp = (conn_list + (sizeof(dev_con_state_t) * i)); 
    
         if (tmp->fd == fd) { 
          return ((dev_con_state_t *) conn_list + (sizeof(dev_con_state_t) * i)); 
         } 
    
        } 
        return (NULL); 
    } 
    
    /** 
    * cleanup_connection_tracker(dev_con_state_t **conn_list) 
    * 
    * @brief Cleanup connection tracker function 
    * @param conn_list 
    */ 
    void cleanup_connection_tracker(dev_con_state_t ** conn_list) 
    { 
    
        if (*conn_list != NULL) { 
         free(*conn_list); 
         *conn_list = NULL; 
        } 
    } 
    
    /** 
    * set_max_conns(int max) 
    * @brief set max 
    * @param max 
    */ 
    void set_max_conns(int max) 
    { 
        max_elements = max; 
    } 
    
    /** 
    * get_max_conns(void) 
    * @brief get max 
    * @return max 
    */ 
    inline int get_max_conns(void) 
    { 
        return max_elements; 
    } 
    
    //#ifdef CODE_TEST 
    #define MAX_DEVS 8 
    int main(int argc, char **argv) 
    { 
        int size = MAX_DEVS; 
        dev_con_state_t *conn_list = NULL; 
    
        printf("initial address: %p\n", conn_list); 
        printf("initial address: %p\n", &conn_list); 
    
        set_max_conns(size); 
    
        if (init_datastruct_commhandler(size, &conn_list) < 0) { 
         return (-1); 
        } 
        printf("init address: %p\n", conn_list); 
        printf("init address: %p\n", &conn_list); 
    
        dev_con_state_t conn_array[MAX_DEVS] = { 0 }; 
    
        dev_con_state_t *ptr = NULL; 
        int i = 0; 
        for (i = 0; i < get_max_conns(); i++) { 
         conn_array[i].fd = i; 
         //~ if ((ptr = new_datastruct_commhandler_element(conn_array[i].fd, conn_list)) == NULL) { 
         //~ return (-1); 
         //~ } 
         /// test will error -> we looped around 
         if ((ptr = build_insert_element(conn_list, conn_array[i].fd)) == NULL) { 
          printf("error finding element\n"); 
         } else { 
          printf("found: %d\n", ptr->fd); 
         } 
    
         printf("inserted: %d\n", ptr->fd); 
        } 
    
        if ((ptr = search_datastruct_commhandler_element(conn_array[5].fd, conn_list)) != NULL) { 
         printf("found: %d\n", ptr->fd); 
        } else { 
         printf("NOT found: %d\n", conn_array[5].fd); 
        } 
    
        if ((ptr = search_datastruct_commhandler_element(conn_array[3].fd, conn_list)) != NULL) { 
         printf("found: %d\n", ptr->fd); 
        } else { 
         printf("NOT found: %d\n", conn_array[3].fd); 
        } 
    
        /// Still visible out here? 
        //~ dev_con_state_t *ptr2 =(&conn_list + sizeof(dev_con_state_t)); 
        //~ printf("test: %d\n", ptr2->fd); 
    
        /// test for searching for last element 
        if ((ptr = build_search_element(conn_list, conn_array[6].fd)) == NULL) { 
         printf("error finding element\n"); 
        } else { 
         printf("found: %d\n", ptr->fd); 
        } 
    
        /// test for finding a number that doesnt exist 
        if ((ptr = build_search_element(conn_list, 9)) == NULL) { 
         printf("error finding element\n"); 
        } else { 
         printf("found: %d\n", ptr->fd); 
        } 
    
        if ((ptr = build_insert_element(conn_list, conn_array[6].fd)) == NULL) { 
         printf("error finding element\n"); 
        } else { 
         printf("inserted: %d\n", ptr->fd); 
        } 
    
        /// test will error -> we looped around 
        if ((ptr = build_search_element(conn_list, conn_array[0].fd)) == NULL) { 
         printf("error finding element\n"); 
        } else { 
         printf("found: %d\n", ptr->fd); 
        } 
    
        cleanup_connection_tracker(&conn_list); 
    
        printf("Done\n"); 
        return (0); 
    } 
    
    //#endif 
    

    , 내 malloc에 ​​또는 내 arithmitic을 수행하고있는 방법에서 무언가인가?

    valgrind --tool=memcheck --leak-check=yes ./test 
    ==27353== Memcheck, a memory error detector 
    ==27353== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. 
    ==27353== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info 
    ==27353== Command: ./test 
    ==27353== 
    initial address: (nil) 
    initial address: 0xffefffdc8 
    Init datahandler memory heap 
    Completed datahandler memory heap 
    init address: 0x5202040 
    init address: 0xffefffdc8 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 0 
    inserted: 0 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 1 
    inserted: 1 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    ==27353== Invalid write of size 4 
    ==27353== at 0x400784: new_datahub_commhandler_element (test.c:119) 
    ==27353== by 0x4006E9: build_insert_element (test.c:80) 
    ==27353== by 0x400968: main (test.c:213) 
    ==27353== Address 0x5202060 is 0 bytes after a block of size 32 alloc'd 
    ==27353== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
    ==27353== by 0x400656: init_datahub_commhandler (test.c:49) 
    ==27353== by 0x4008D3: main (test.c:197) 
    ==27353== 
    ==27353== Invalid read of size 4 
    ==27353== at 0x400984: main (test.c:216) 
    ==27353== Address 0x5202060 is 0 bytes after a block of size 32 alloc'd 
    ==27353== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
    ==27353== by 0x400656: init_datahub_commhandler (test.c:49) 
    ==27353== by 0x4008D3: main (test.c:197) 
    ==27353== 
    found: 2 
    ==27353== Invalid read of size 4 
    ==27353== at 0x40099B: main (test.c:219) 
    ==27353== Address 0x5202060 is 0 bytes after a block of size 32 alloc'd 
    ==27353== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
    ==27353== by 0x400656: init_datahub_commhandler (test.c:49) 
    ==27353== by 0x4008D3: main (test.c:197) 
    ==27353== 
    inserted: 2 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 3 
    inserted: 3 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 4 
    inserted: 4 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 5 
    inserted: 5 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 6 
    inserted: 6 
    a 0x5202040 0xffefffd78 
    0x5202040 0xffefffd40 
    found: 7 
    inserted: 7 
    ==27353== Invalid read of size 4 
    ==27353== at 0x4007EA: search_datahub_commhandler_element (test.c:142) 
    ==27353== by 0x4009CC: main (test.c:222) 
    ==27353== Address 0x5202060 is 0 bytes after a block of size 32 alloc'd 
    ==27353== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
    ==27353== by 0x400656: init_datahub_commhandler (test.c:49) 
    ==27353== by 0x4008D3: main (test.c:197) 
    ==27353== 
    
    valgrind: m_mallocfree.c:303 (get_bszB_as_is): Assertion 'bszB_lo == bszB_hi' failed. 
    valgrind: Heap block lo/hi size mismatch: lo = 4, hi = 17179869184. 
    This is probably caused by your program erroneously writing past the 
    end of a heap block and corrupting heap metadata. If you fix any 
    invalid writes reported by Memcheck, this assertion failure will 
    probably go away. Please try that before reporting this as a bug. 
    
    
    host stacktrace: 
    ==27353== at 0x38083F98: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x380840B4: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x38084241: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x38091AEC: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x3807D653: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x3807BEE3: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x380800BA: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x3807B47A: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x380593E1: ??? (in /usr/lib/valgrind/memcheck-amd64-linux) 
    ==27353== by 0x802D490EB: ??? 
    ==27353== by 0x802CA9F2F: ??? 
    ==27353== by 0x80200831F: ??? 
    ==27353== by 0x4009CC: main (test.c:222) 
    
    sched status: 
        running_tid=1 
    
    Thread 1: status = VgTs_Runnable (lwpid 27353) 
    ==27353== at 0x4009DC: main (test.c:223) 
    
    
    Note: see also the FAQ in the source distribution. 
    It contains workarounds to several common problems. 
    In particular, if Valgrind aborted or crashed after 
    identifying problems in your program, there's a good chance 
    that fixing those problems will prevent Valgrind aborting or 
    crashing, especially if it happened in m_mallocfree.c. 
    
    If that doesn't help, please report this bug to: www.valgrind.org 
    
    In the bug report, send all the above text, the valgrind 
    version, and what OS and version you are using. Thanks. 
    

    도움이 될 것입니다! 머리에 키보드를 대고 있는데 ... 작동하는 것처럼 보입니다. 이 출력으로 주어진대로

    ./test 
    initial address: (nil) 
    initial address: 0x7fff41386a68 
    Init datahandler memory heap 
    Completed datahandler memory heap 
    init address: 0x650010 
    init address: 0x7fff41386a68 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 0 
    inserted: 0 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 1 
    inserted: 1 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 2 
    inserted: 2 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 3 
    inserted: 3 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 4 
    inserted: 4 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 5 
    inserted: 5 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 6 
    inserted: 6 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    found: 7 
    inserted: 7 
    found: 5 
    found: 3 
    found: 6 
    error finding element 
    a 0x650010 0x7fff41386a18 
    0x650010 0x7fff413869e0 
    inserted: 6 
    found: 0 
    Done 
    
  • +0

    [최소 테스트 케이스] (http://stackoverflow.com/help/mcve)를 구성하십시오. –

    +0

    Oliver, 업데이트했습니다. – mcdoomington

    +0

    MCVE ([MCVE])를 만드는 방법을 읽어보십시오. MCVE는 자체 포함 (자체 데이터를 생성 또는 포함)하거나 사용 된 데이터를 지정해야합니다. 보고 된 오류는 간단합니다. Valgrind는 할당 된 구조의 끝을 넘어 서면 쓰고 있음을 확인하고 있습니다. 'dev_con_state_t * tmp = conn_list + (sizeof (dev_con_state_t) * current_elements);'- 왜 크기를 곱한거야? C는 이미 개체의 크기만큼 포인터 연산을 조정합니다. 당신은'dev_con_state_t * temp = conn_list + current_elements; '를 의미합니다. –

    답변

    0

    여기에 서사시 의견에 의해 주어진 가장 간단한 해결책을위한 코드입니다.

    #include <stdio.h> 
    #include <stdlib.h> 
    #include <stdint.h> 
    #include <unistd.h> 
    #include <ctype.h> 
    #include <string.h> 
    #include <sys/socket.h> 
    #include <sys/types.h> 
    
    typedef struct mystruct_s { 
        int fd; 
        int a; 
        int b; 
    } mystruct_t; 
    
    int current_elements = 0; 
    int max_elements = 0; 
    
    int init(int size, mystruct_t ** conn_list) 
    { 
        if (size <= 0) { 
         return (-1); 
        } 
        current_elements = 0; 
    
        *conn_list = malloc(max_elements *sizeof(mystruct_t)); 
    
        if (*conn_list == NULL) { 
         return (-1); 
        } 
    
        return (0); 
    } 
    
    void insert(int fd, mystruct_t ** conn_list, mystruct_t ** res) 
    { 
    
        *res = NULL; 
    
        if (current_elements == (max_elements)) { 
         (*conn_list)[current_elements].fd = fd; 
         (*conn_list)[current_elements].a = fd; 
         (*conn_list)[current_elements].b = fd; 
         *res = &(*conn_list)[current_elements]; 
         current_elements = 0; 
        } else { 
         (*conn_list)[current_elements].fd = fd; 
         (*conn_list)[current_elements].a = fd; 
         (*conn_list)[current_elements].b = fd; 
         *res = &(*conn_list)[current_elements]; 
         current_elements++; 
        } 
    } 
    
    int search(int fd, mystruct_t ** conn_list, mystruct_t ** res) 
    { 
        int i = 0; 
        if (*conn_list == NULL) { 
         *res = NULL;   
         return (-1); 
        } 
        for (i = 0; i < max_elements; i++) { 
         if ((*conn_list)[i].fd == fd) { 
          *res = &(*conn_list)[i]; 
          return (1); 
         } 
    
        } 
        *res = NULL; 
        return (-1); 
    } 
    
    #define MAX_ELEMENTS 8 
    int main(int argc, char **argv) 
    { 
        int size = MAX_ELEMENTS; 
        mystruct_t conn_array[MAX_DEVS] = { 0 }; 
        mystruct_t *conn_list = NULL; 
    
        max_elements = MAX_DEVS; 
    
        if (init(size, &conn_list) < 0) { 
         return (-1); 
        } 
    
        mystruct_t *ptr = NULL; 
        int i = 0; 
        for (i = 0; i < max_elements; i++) { 
         conn_array[i].fd = i; 
         insert(conn_array[i].fd, &conn_list, &ptr); 
        } 
    
        if ((search(conn_array[5].fd, &conn_list, &ptr)) > 0) { 
         printf("Found: %d\n", ptr->fd); 
        } else { 
         printf("NOT found: %d\n", conn_array[5].fd); 
        } 
    
        if (conn_list != NULL) { 
         free(conn_list); 
        } 
        return (0); 
    } 
    
    +0

    포인터 연산이 여전히 틀리다. 요소의 크기를 곱할 필요가 없습니다. 포인터 연산을 전혀 사용하지 않는 이유는 무엇입니까? C의 배열에는 완벽하게 좋은 인덱싱 연산자가 있습니다. 'conn_list [i]'만 있으면 충분합니다. –

    +0

    @ n.m 배열이 더 좋은 이유를 말해 주시겠습니까? 이 경우 동적이지 않으며 변경해야 할 수도 있습니다. 당신이 포인터의 배열을 언급하지 않는다면? – mcdoomington

    +1

    "왜 배열이 더 좋을까요?" 'malloc (n * sizeof (mystruct_t))'는'mystruct_t' 타입의'n '원소들의 배열을위한 공간을 할당하고 첫 번째 요소에 대한 포인터를 반환합니다. 이제 올바르게 사용하거나 잘못 사용하도록 선택할 수 있습니다. conn_list [i]는 올바른 사용법의 한 예일 것이다. 그래서'* (conn_list + i)'가 될 것입니다. **는 정의에 의해 ** 이전 예제와 같습니다. '* (conn_list + i * sizeof (mystruct_t))'는 잘못된 사용법의 예입니다. 'conn_list [i]'는 읽기 쉽고 쓰기 쉽습니다. 당신이 쓴 것은 올바르지도 않습니다. –