2014-04-26 4 views
1
#include <stdio.h> 
#include <stdlib.h> 

int *seperateDigits(int n) 
{ 
    int *digits, numberOfDigits = 0, temp = n; 

    while (temp) { 
     temp /= 10; 
     numberOfDigits++; 
    } 

    digits = (int *)malloc(sizeof(int) * (numberOfDigits + 1)); 

    digits[numberOfDigits] = -1; 
    while (numberOfDigits >= 0) { 
     digits[--numberOfDigits] = n % 10; 
     n /= 10; 
    } 

    return digits; 
} 

int main(void) { 
    int n, *na; 

    scanf("%d", &n); 
    na = seperateDigits(n); 

    if (!na) { 
     printf("Cannot allocate memory!\n"); 
     return 1; 
    } 

    while (*na != -1) 
     printf("%d ", *na++); 

    free(na); 

    return 0; 
} 

숫자를 숫자로 분리하는 함수를 작성했습니다. 메모리를 할당 해제하지 않으면 아무 것도 잘 작동하지 않습니다. 하지만 동적으로 할당 된 메모리를 free() 함수로 할당 해제하려고하면 런타임 오류가 발생합니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?free() 함수로 인해 런타임 오류가 발생했습니다.

답변

3

증가하면 na이되므로 malloc이 반환 한 값을 해제하지 않습니다 (그러나 포인터 numberOfDigits은 그 이전에 위치합니다). 대신 명시 적 정수 인덱스를 사용하십시오.

오, 그리고 malloc()의 반환 값을 int *으로 변환하지 마십시오. it's harmful.

+0

내 바보 같은 실수! – yunusaydin

+0

왜 던지기가 해로운가요? – yunusaydin

+0

@yunusaydin 링크를 참조하십시오. (그리고 다음 번에 적어도 디버거를 사용하거나 프로그램에 대한 이유를 찾으십시오.) –

2

free 함수는 malloc에 의해 반환 된 포인터를 전달해야합니다. 즉시 malloc를 호출 한 후 NULL에 대한 malloc의 반환 값을 확인해야합니다, 또한

printf("%d ", *na++); 

- 그러나, 후행 증가 연산자는 main에서 printf 호출 na의 값을 변경합니다. malloc의 결과를 전송하지 마세요. 유용하지 않으며 프로토 타입이 포함 된 stdlib.h 헤더를 포함하는 것을 잊어 버리면 문제가 발생할 수 있습니다. 이 읽기 - Do I cast the result of malloc? 나는 다음과 같은 변경을 제안 - na의 포스트 증가뿐만 아니라

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

int *seperateDigits(int n) 
{ 
    int *digits, numberOfDigits = 0, temp = n; 

    while (temp) { 
     temp /= 10; 
     numberOfDigits++; 
    } 

    // don't cast the result of malloc 
    digits = malloc((numberOfDigits + 1) * sizeof(*digits)); 

    // check the result of malloc just after calling it 
    if(digits == NULL) { 
     printf("malloc failed to allocate memory\n"); 
     return NULL; 
    } 

    digits[numberOfDigits] = -1; 
    while (numberOfDigits >= 0) { 
     digits[--numberOfDigits] = n % 10; 
     n /= 10; 
    } 

    return digits; 
} 

int main(void) { 
    int n, *na; 
    int i = 0; 

    scanf("%d", &n); 
    na = seperateDigits(n); 

    if(na == NULL) 
     return 1; 

    while (na[i] != -1) { 
     printf("%d ", na[i]); 
     i++; 
    } 

    free(na); 

    return 0; 
} 
+0

[런타임 오류] (http://ideone.com/rEjN7h)입니다. – yunusaydin

+0

하지만 ideone.com에서는 (gcc)를 컴파일하고 내 컴퓨터에서 성공적으로 실행했기 때문에 ideone.com과 관련이 있다고 생각합니다. – yunusaydin

+0

@yunusaydin 네, 제 시스템에서 테스트했기 때문입니다. 잘 작동합니다. 내가 추락 할 이유가 없다. – ajay

0

를 다른 문제가 있습니다. 그것을 잘 이해하기 위해서는 자유가 내부적으로 어떻게 작동하는지 이해해야합니다.

자유롭게 포인터 na가 가리키는 메모리 양을 묻지 않으므로 올바른 할당 해제가되고 얼마나 많은 메모리인지 정확히 알 수 있습니다. 문제는 그 정보를 얼마나 자유롭게 알 수 있는가입니다. 그리고 응답은 내부적으로 malloc calloc을 호출하거나 realloc 함수가 요청한 것보다 더 많은 메모리를 할당 할 때 할당 한 양 + 대략 해당 메모리에 대한 정보, 특히 그 크기에 필요한 메모리 양입니다.

Tab=malloc (3*sizeof (int))에 배열 3 개가있는 경우 실제로 malloc은 4 * sizeof (int) 바이트의 메모리를 할당한다고 가정합니다. 즉, 첫 번째 sizeof에 4 개의 정수 배열 Tab0이 할당됩니다. (int) 바이트, 즉 Tab0 [0] 당신이 요청한 메모리의 크기가 즉 Tab0[0] =3*sizeof (int); 인 경우 다음 3 * sizeof (int) 바이트 즉, return &Tab0[1];을 가리키는 포인터를 반환합니다. free (Tab);가 호출 될 때, 그것을 감소하고 확보하기 위해 얼마나 많은 메모리를 읽을 수 있도록 준 포인터가 배열의 제 2 부재를 의미 것을 알고 그것을 수행합니다

int* Tab0=Tab-1; 
int memoryToFree=Tab0[0];. 

나는주의 싶어 내가 말한 것은 정확히 무슨 일이 아니며, 런타임 오류가 발생하는 이유를 이해하는 것이 단순화 된 것입니다. 일반적으로 malloc, realloc, calloc 및 free를 사용하기 위해 malloc realloc 또는 calloc에서 반환 된 포인터 만 해제하기 위해 전달해야하는 것이 내부적으로 어떻게 작동하는지 이해할 필요가 없습니다.

당신이 한 문제는 무료로 당신이 여기 있다고 한 제대로 작동하려면 당신이 액세스하고 중요 메모리를 만지지해야 메모리를 변경한다는 것입니다 :

while (numberOfDigits >= 0) { 
    digits[--numberOfDigits] = n % 10; 
    n /= 10; 
} 

이 numberOfDigits == 0 digits[--numberOfDigits] = n % 10; 인 경우 numberOfDigits=-1; digits[-1] = n % 10;에 해당합니다. 시스템은 malloc에 ​​의해 할당 된 메모리를 실제로 소유하고 있으며, 자유롭게 필요로하는 중요한 정보를 저장하는 데이터를 변경했기 때문에이를 세그먼트 화 오류로 인식하지 못합니다. 이렇게하면 다음과 같이 수정할 수 있습니다.

while (numberOfDigits > 0) { 
    digits[--numberOfDigits] = n % 10; 
    n /= 10; 
} 
관련 문제