2012-02-25 2 views
-2

malloc과 goto의 관계에 문제가 있다고 생각합니다. 아니면 여기에 메모리 낭비 나 메모리 손상 등이 있습니다. 희망, 누군가가 내게 정확한 오류를 지적 할 수 있습니다. 컴파일 할 때 오류가 발생하지 않지만 내 수석은 내가 실수 한 것으로 주장합니다.이 기능의 문제점은 무엇입니까?

#define FINISH() goto fini; 

BOOL Do() 
{ 

    BOOL stat; 
    UINT32 ptr; 
    int err; 

    ptr = (UINT32)malloc(1000); 


    free((void*)ptr); 

fini: 
    return stat; 
} 
+15

'#DEFINE 마감() 고토 피니, '오 주여 자비 – orlp

+3

이 goto''사용하지 마십시오있다 : 당신이 실제 포인터 타입으로 ptr을 변경하면, 바로 이렇게. 매크로 안에'goto'를 숨기지 마십시오. –

+0

이 코드가 컴파일됩니까? 나는 그렇게 생각하지 않는다. –

답변

4

여기서 I 코드 err != ERROR_SUCCESS이 함수 메모리 누출

  • 에서 발견 된 문제이다. free 호출로 건너 뜁니다.
  • malloc의 리턴을 32 비트 위치에 저장합니다. 이것은 휴대용 솔루션이 아닙니다. 64 비트 플랫폼에서는 주소를 잘라내는 것처럼 프로그램에 혼란을 초래할 것입니다. 포인터가 아닌 유형을 사용해야하는 경우 여기서 size_t을 사용하십시오 (정수형보다 포인터를 사용하는 것이 좋습니다).
  • 로컬 stat은 여기에 확실하게 지정되지 않습니다. err != ERROR_SUCCESS 인 경우 쓰레기를 반환합니다. 항상 값을 할당해야합니다. 가장 쉬운 방법은 기본값을 제공하는 것입니다.
  • 당신은 malloc의 반환 값을 확인하고 잠재적으로 Fun2

에 숨겨진 NULL 포인터를 전달 여기에 당신이 포인터를 변환하는 내가

BOOL Do() 
{ 

    BOOL stat = FALSE; 
    size_t ptr = 0; 
    int err; 

    ptr = (UINT32)malloc(1000); 
    err = Fun1(); 

    if (err != ERROR_SUCCESS || ptr == 0) 
     FINISH(); 
    else 
     stat = Fun2(ptr); 

fini: 
    free((void*)ptr); 
    return stat; 
} 
+0

'stat'도 true로 평가되는 경우 초기화되지 않는다고 생각합니다. – Muggen

+0

'ptr! = 0' 체크가 필요 없습니다 :'0'은 널 포인터로 변환되고'free()'는 널 포인터 안전합니다 – Christoph

+0

@Muggen 덕분에 최근 편집에서 수정되었습니다 – JaredPar

3

malloc은 포인터를 반환합니다. 정수에 대한 포인터를 캐스팅하고 있지만 포인터와 정수는 같은 표현을 요구하지 않습니다. 예를 들어 포인터 크기는 64 비트 일 수 있으며 정수에 맞지 않습니다.

또한 개체 stat을 함수에서 초기화하지 않고 사용할 수 있습니다. 명시 적으로 초기화하지 않으면 객체 stat은 선언 후에 불확정 값을가집니다.

+0

이것은 정답입니다. Downvoter는 설명을 걱정할 것입니까? –

+0

@ ErnestFriedman-Hill,'(UINT32) malloc (1000)'은 무엇을하고 있다고 생각합니까? –

+0

내 나쁜, downvote 반전, 덧글이 제거되었습니다. 이 하나가 저에게 나가지 않는 다른 많은 문제가 있습니다. –

1

우리는 이것이 무엇을하기로되어 있는지 알지 못하지만, Fun1()ERROR_SUCCESS을 반환하지 않으면 ptr은 결코 해제되지 않습니다. 아마도 상사가 말하는 오류 일 것입니다.

1

을 제안 편집과 함수의하지 않습니다 uint32_t 그리고 다시. 이렇게하면 포인터 값의 위쪽 절반이 지워집니다.

0

무엇을 하든지 해당 코드를 컴파일하지 않습니다. 구문 오류가 있습니다.

if(foo) 
    bar;; 
else 
    baz 

빌드 시스템을 확인하십시오.

0

내 전반적인 의견과 C로 작업하기위한 일반적인 경험 법칙 ... 포인터 캐스트를 수행해야하는 경우 스스로 물어보십시오. 정말로해야합니까? 솔직히 포인터 캐스트를해야 할 때가 매우 드뭅니다. 훨씬 더 일반적인 것은 사람들이 이해하는데 약간의 차이가 있기 때문에 포인터 캐스팅을 사용하고, 수행하려고 시도하거나해야하는 작업을 명확하게 알지 못하고 컴파일러 경고를 침묵 시키려고하기 때문입니다.

ptr = (UINT32)malloc(1000); 

매우 나쁨! 이 "포인터"로 무엇이든하면 64 비트 플랫폼에서 작동하면 매우 운이 좋을 것입니다. 포인터를 포인터 유형으로 둡니다.절대적으로 정수에 저장해야하는 경우에는 충분히 큰 것으로 보장되는 uintptr_t을 사용하십시오.

나는 당신이 시도되었을 수 있습니다 말하고 싶지만 :

// Allocate 1,000 32-bit integers 
UINT32 *ptr = (UINT32*)malloc(1000 * sizeof(UINT32)); 

그러나 심지어는 C 코드, 이상한 C 및 C++ 하이브리드에 대한 빈약 한 형태이다. , void*에 캐스팅

free((void*)ptr); 

또 다른 큰 붉은 깃발되면, 그 자주 기호를

// Allocate 1,000 32-bit integers 
UINT32 *ptr = malloc(1000 * sizeof(UINT32)); 

마지막 : C++과는 달리, C에서 당신은 단지 void * 걸릴 수 있으며 암시 적으로 어떤 포인터 형식으로 가져 저자는 그들이하는 일을 모릅니다.

free(ptr);