2016-06-30 2 views
1

c에서 단일 링크 된 연결 목록을 구현하려고했습니다. 나는 목록의 여러 인스턴스를 사용할 수 있기를 원했고 main 함수에서 목록을 만들고 싶었다. 그래서 내가 그랬던 것처럼 그것을 구현하기로 결정했습니다.C malloc valgrind - 단일 링크 된 목록 구현의 초기화되지 않은 메모리 구현

코드는 완벽하게 작동하지만 valgrind 출력으로 인해 걱정이됩니다. 또한 임베디드 시스템에서 프로젝트의 코드를 사용하려고 시도했지만 이상한 오류가 발생합니다.

Valgrind의 출력은 : 시작

...

== 3570 == 조건부 점프 또는 이동 0x100000E8E에서 초기화되지 않은 값 (들)

== 3570 ==에 따라 : 0x100000D4F 의해

== 3570 == (./map_test)에 push_cfront : 주 (./map_test)에

== 3570 == 의 malloc (/usr/local/Cellar/valgrind/3.11.0/lib/valgrind/vgpreload_memcheck-amd64-darwin.so)에

: 초기화되지 않은 값이 힙 할당 0x100008EBB에서

== 3570 == 의해 만들어진

== 0x100000E80 의해 3570 == push_cfront (./map_test)에 의해 0x100000D4F

== == 3570 : 주 (./map_test)에

== 3570 ==

. 완료 됨

또한 하나의 블록을 잃어 버렸다고 나에게 알려줍니다. 나는 그것을 해제 실수를 할 경우

== 3570 == 누출 요약 : 16 바이트를 1 개 블록

== 3570 == 간접적 손실에 : 3570 == 확실히 손실

== : 2064 바이트를 1 개 블록 3570 == 아직 도달

==에 : 0 블록 3570 == 가능성이 손실

== 0 바이트 0 바이트 0 블록

== 3570 == 억압 : 186 블록의 24,525 바이트

어디서 잘못되었는지 힌트를주세요.

TEST.C :

#include <stdio.h> 
#include <stdint.h> 
#include <stdlib.h> 
#include "command_list.h"  
int main() { 

    printf("starting...\n"); 

    Clist * command_list = malloc(sizeof(Clist)); 
    if (command_list == NULL) printf("Malloc Failed\n"); 
    command_list->head = NULL; 

    //push_cback(command_list, 0); 
    push_cfront(command_list,1); 

    free_clist(command_list); 
    free(command_list); 
    printf("\n...finished\n"); 
    return 0; 
} 

command_list.h :

#ifndef __COMMAND_LIST_H 
#define __COMMAND_LIST_H 

typedef struct cnode { 
    uint8_t command; 
    struct cnode * next; 
} Cnode; 

typedef struct clist { 
    Cnode * head; 
} Clist; 

void push_cback(Clist * list, uint8_t command); 
void push_cfront(Clist * list, uint8_t command); 
void free_clist(Clist * list); 

#endif 

command_list.c

void push_cfront(Clist * list, uint8_t command){ 
    Cnode * new_node; 
    new_node = malloc(sizeof(Cnode)); 
    if (new_node->next == NULL) { 
     return; 
    } 
    new_node->command = command; 
    new_node->next = list->head; 
    list->head = new_node; 
} 

void free_clist(Clist * list){ 
    if (list->head == NULL){ 
     return; //already empty 
    } 
    Cnode * current = list->head; 
    while (current->next != NULL){ 
     Cnode* temp = current->next; 
     free(current); 
     current = temp; 
    } 
    free(current); 
    list->head = NULL; 
} 
+3

(new_node-> == NULL 옆)'그냥'그 일을 malloc'ed 경우'당신'할; 정렬 된 연결리스트에 삽입은 해당 기술은 같다 'next'는 설정되지 않습니다. 확실히'if (new_node == NULL)'을 사용하기로했다. – WhozCraig

+1

아, Valgrind를 사용하기위한 소품. – WhozCraig

+0

나는'list == NULL'을 확인해야한다고 생각합니다. – niceman

답변

0

몇 가지 문제가 있습니다. new_node (malloc의 반환 값) 대신 new_node->next (malloc 된 메모리의 초기화되지 않은 데이터)을 확인하고 있습니다. 적어도 내 컴퓨터에서는 우연히 new_node->next이 null이므로 메모리가 해제되지 않으므로 new_node을 해제하지 않고 반환합니다. 또한 연결된 목록의 뒤쪽으로 밀어 넣기를 지원하려면 전체를 통과하지 않고도 해당 작업을 수행 할 수 있으므로 순환 링크 된 목록을 고려해야합니다.

마지막으로 몇 가지 팁 : valgrind를 사용하는 것이 좋지만 -g으로 컴파일하여 디버깅 기호를 활성화하면 valgrind가 줄 번호를 알려줍니다. 또한 연결된 목록을 만들 때 일부 작업에 더미 헤드 노드를 사용하여 비어 있거나 싱글 톤 목록에 대한 특별한 경우를 피합니다. push_cfront`의 세 번째 줄에

int sorted_insert(Clist *list, char new_command){ 
    Cnode _head = {NULL, list->head}, *head = &_head, *prev = head, *tmp;//head is an auto dummy node obviating null checks. 
    int ord = -1;//If there are no existing nodes, newObj would be less than all objects. 
    while(prev->next && (ord = (int)newObj - prev->next->command)) > 0){//Iterate by prev->next not curr to use only one pointer. 
     prev = prev->next;//Looping while there is a next node and its data compares less than new_command. 
    } 
    if((!ord) || !(tmp = malloc(sizeof(Cnode))){//newObj is already in the list or allocation failed. 
     return 0; 
    } 
    *tmp = (Cnode){.next=prev->next, .command=new_command}; 
    prev->next = tmp; 
    list->head = head->next;//un- add head which is then deallocated by stack frame cleanup. 
    return 1; 
} 
+0

고마워요. 이제 free_clist에 관한 부분을 삭제할 것입니다. 고마워요. 그것은 때때로 내가 때때로 어떤 블록을 잃어 버렸고 때로는 그렇지 않은 이유를 분명하게했다. 사실 나는 -g를 사용하여 프로그램을 컴파일했고이 명령으로 valgrind를 사용했습니다. valgrind --leak-check = full --track-origins = yes – lugges

0

new_node->next은 값을 확인할 때 초기화되지 않습니다. 당신은 그럴 필요가 없습니다.

malloc 오류를 찾으려면 함수에 대한 반환 코드를 설정하고 호출 할 때 확인하십시오.

push_cfrontif 브랜치가 필요하지 않습니다.

... 아니면 list->head을 확인하고 싶습니까?

0

또한 new_node 메모리가 초기화되지 않기 때문에 그것은 정의되지 않은 동작입니다 push_cfront

new_node = malloc(sizeof(Cnode)); 
if (new_node->next == NULL) { 
    return; 
} 

코드의이 부분에 문제가 있습니다. 메모리가 실제로 할당되었는지 확인하려면 if (new_node == NULL)을 확인하려고했을 것입니다.

+0

new_node-> 다음을 점검하면서 문제를 지적 해 주신 모든 분들께 감사드립니다. 나는 자유로운 방법으로 내가 가진 문제를 보지 못한다. while 루프 후에 나머지 노드를 해제했습니다. 사실 나는 당신이 free_clist() 메서드에서 null을 해제하려고한다고 생각합니다. 또는 나는 틀린가? – lugges

+0

오, 당신 말이 맞아요. 무료로 놓친 (현재), 이것에 대해 더 자세히 살펴볼 것입니다, 나는 대답을 – buld0zzr