2015-01-14 2 views
0

Visual Studio에서 나에게 미친 문제가 발생했습니다. 할당되지 않은 포인터에 관한 것입니다.Visual Studio unallocted 포인터가 NULL이 아닙니다.

간단한 연결 목록 응용 프로그램을 작성하고 싶습니다. 문제는 해제 된 포인터와 할당되지 않은 포인터가 NULL이 아니기 때문에 목록을 반복 할 수 없기 때문입니다.

라인 문제 1과 문제 2, listTemp-> pNext는 NULL하지만 0xfdfdfdfd없는에서 C 코드

#include "stdafx.h" 
#include <malloc.h> 

typedef struct _item 
{ 
    char data; 
    struct _item * pNext; 
}item, *pItem; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    pItem listHead; 
    pItem listTemp; 
    pItem listCurr; 

    listHead = (pItem) malloc(sizeof(listHead)); 
    listHead->data = '0'; 
    listHead->pNext = NULL; //will create exception in free 

    listTemp = listHead; 

    while(listTemp->pNext != NULL) //issue 1 
    { 
     listTemp = listTemp->pNext;//0xfdfdfdfd - never NULL? how to check? 
    } 

    listCurr = (pItem) malloc(sizeof(listHead)); 
    listCurr->data = '1'; 
    listCurr->pNext = NULL; //will create exception in free 
    listTemp->pNext = listCurr; 

    listTemp = listHead; 
    while(listTemp->pNext != NULL) //issue 2 
    { 
     printf("%d ", listTemp->data - 48); //"0 " 
     listTemp = listTemp->pNext; 
    } 

    printf("%d ", listTemp->data - 48); 
    free(listTemp); //is set to oxfeeefee not to NULL? //issue 3 


    listTemp = listHead; 
    while(listTemp->pNext != NULL) //issue 4 
    { 
     listTemp = listTemp->pNext; 
    } 

    free(listTemp);//Not null? 

    return 0; 
} 

다음 고려하십시오. 이렇게하면 라인 이슈 3에서리스트 의 마지막 요소를 가져 오지 못하게됩니다. free는 해제 된 포인터를 null로 설정하지 않고 0xfeeefeee로 설정합니다. 이렇게하면 마지막 요소를 다시 가져올 수 없습니다.

어떻게 이러한 문제를 해결할 수 있습니까? 도움 주셔서 감사합니다.

+0

변수는 단순히 초기화되지 않습니다. 디버거는 거기에 0xfdfdfdfd 패턴을 저장하여 초기화하지 않은 장소를 찾을 수 있도록 도와줍니다. 릴리스 빌드에서는 그러한 일이 발생하지 않습니다. BTW :'calloc() '을 확인하고 C에서 그러한 함수의 반환 값을 캐스팅하는 것을 중단하십시오. –

+0

Ulrich, 답장을 보내 주셔서 감사합니다. 0xfdfdfdfd 패턴을 이해했습니다. 문제는 어떻게 코드를 디버깅합니까? – esso

+0

이것은 주로 C 질문입니다. 그래서 그 태그를 추가했습니다. –

답변

1

여기에 몇 가지 문제가있는 것 같습니다. 한 가지 문제는 충분한 메모리를 할당하지 못한다는 것입니다.

listHead = (pItem) malloc(sizeof(listHead)); 

listHead은 포인터입니다. 따라서 포인터를 보유 할 수있는 충분한 메모리 만 할당하고 전체 item 구조체는 보유하지 마십시오. 그것은이어야합니다 :

listHead = (pItem) malloc(sizeof(item)); 

처음에는 어떻게 처음부터 NULL이 될 수 있는지 알 수 없습니다. 디버거를 단계별로 실행 했습니까? 그러나 충분한 메모리를 할당하지 않는 문제는 free()에서 문제를 일으킬 수 있으며 다른 문제가 발생할 수 있는지 확실히 말하기는 다소 어렵습니다.

+0

@Erany 루프의 "issue 2"에 댓글을 달았습니다. 마지막 항목 (유효하게)에'pNext == NULL'이 있기 때문에 목록의 마지막 항목이 인쇄되지 않습니다. 그래서 내가 잘못 시퀀스를 구문 분석하고있다. –

0

구문이 제 컴파일러에 맞게 약간 변경되었습니다. 두 가지 주요 쟁점은 (1) 이미 언급 한 바와 같이 충분한 메모리를 할당하지 않는 것입니다. (2) 목록을 구문 분석하기위한 잘못된 순서.

#include <stdio.h> 
#include <stdlib.h> 

typedef struct item { 
    char data; 
    struct item * pNext; 
} item, *pItem; 

void show (pItem list, int cue) { 
    printf("List %d: ", cue); 
    while(list != NULL) { 
     printf("%c ", list->data); 
     list = list->pNext; 
    } 
    printf("\n"); 
} 

int main(int argc, char* argv[]) { 
    pItem listHead, listTemp, listCurr; 

    listHead = malloc(sizeof(item)); 
    listHead->data = '0'; 
    listHead->pNext = NULL; 
    show(listHead, 1); 

    listCurr = malloc(sizeof(item)); 
    listCurr->data = '1'; 
    listCurr->pNext = NULL; 
    listHead->pNext = listCurr; 
    show(listHead, 2); 

    printf("Freeing: "); 
    while(listHead != NULL) { 
     listTemp = listHead; 
     printf("%c ", listHead->data); 
     listHead = listHead->pNext; 
     free(listTemp); 
    } 
    printf("\n"); 

    show(listHead, 3); 
    return 0; 
} 

은 위의 코드는리스트의 말미에 다음 항목을 추가하여 방법을 다음하지만 일반적으로 머리 전에 추가하고 새로운 listHead을 설정합니다.

listCurr = malloc(sizeof(item)); 
listCurr->data = '1'; 
listCurr->pNext = listHead; 
listHead = listCurr; 

이 또한 빈 목록을 표시하기 위해 listHead = NULL를 초기화 제공 항목에 대한 작동합니다.

+0

Visual Studio에서 실행 했습니까? 디버그 모드에서 실행하면 listCurr-> pNext = NULL을 설정 했으므로 예외가 발생합니다. 이것은 나의 주요한 문제입니다. – esso

+0

@Erany 내 코드가 NULL이거나, 초기화되지 않은 경우, 내 포인터가 모든 포인터를 보류하거나'free()'하지 않습니다. –

+0

@Erany'listCurr-> pNext = NULL'은 목록의 끝을 나타냅니다. 이것은 일반적인 관행입니다. –

0

답은 자유로운 메모리에 NULL 포인터를 설정해야한다는 것입니다. free 함수는 포인터의 메모리를 힙으로 다시 릴리스합니다. 포인터 매개 변수는 값으로 전달되며 free 함수 자체로 수정할 수 없습니다.

또한 메모리에서 해제하고 포인터를 NULL로 설정할 때 목록의 이전 항목에 대한 참조를 유지해야합니다. 그러면 포인터를 임시 항목이 아닌 목록 항목에서 수행 할 수 있습니다.

listCurr = NULL; 
listTemp = listHead; 

while(listTemp->pNext != NULL) 
{ 
    listCurr = listTemp; 
    listTemp = listTemp->pNext; 
} 

if(NULL != listCurr) 
{ 
    free(listCurr->pNext); 
    listCurr->pNext = NULL; 
} 
관련 문제