2009-04-10 4 views
2

는 다음과 같은 C 코드를 생각해malloc'ed 블록을 사용하지 않으면 어떻게됩니까?

int main(){ 
    int* c; 
    c = (int*)malloc(sizeof(int)); 
    c = 0xdeadbeef; 
    free(c); 
    return 0; 
} 

이전에 malloc으로 할당 된 것이 아닙니다있는 C을 확보하기 위해 노력하고 있기 때문 세그 폴트 것입니다. 내 질문은 블록 malloc'ed 무슨 일이 일어나는가? 분명히 c는 더 이상 가리 키지 않아서 사용할 수 없지만 여전히 '무료'목록의 일부로 간주됩니까? 아니면 명시 적 메모리 누수입니까?

답변

12

누출입니다. 프로그램이 종료되면 OS에서 회수합니다.

+0

: 당신은 당신이 출력을 얻을 것이다 (libc의()의 malloc(), realloc을(), ... 기능을 무료로 교체 자체에 회계를 수행하여 작동하는) Valgrind의이 실행한다면 전통적인 Unix 가비지 수집 방식 : 프로그램을 실행하고 종료 될 때 메모리를 회수합니다. IDE, 브라우저 및 오랫동안 실행될 가능성이있는 다른 프로그램에서는 잘 작동하지 않습니다. –

1

그 코드는 메모리는 여전히 메모리 누수의 원인이 할당 c = 7;

+0

free (c)는 segfault 일 수 있습니다. 왜냐하면 free()가 정크 포인터를 역 참조 할 것이기 때문입니다. – Michael

+0

Majd, 당신은 엄밀히 말하면 정확합니다. 그러나 가장 잘못된 주소로 포인터를 변경하고 역 참조를 시도하는 것이 그 요점이었습니다. –

+0

c = 7을 * c = 7로 변경하면 문제가 해결되지 않습니다. 주제가 약간이지만 맞습니다. – Ben

10

*c = 7;에 변경 가정, 세그 폴트되지 않습니다. 다른 방법을 원하니? 실제로 할당 된 메모리를 다시 확보해야한다는 것을 기계/컴파일러가 알 수있는 방법은 없습니다. 이것이 올바른 행동이 아니라면, 당신의 코드는 확률 적으로 기능 할 것입니다. 코드를 결코 믿을 수는 없습니다.

나중에 언제든지 해당 메모리 블록을 다시 가리킬 수 있으므로 자동으로 메모리를 확보하면 그 아래에서 러그가 당겨집니다.

+0

C가 아닌 다른 언어의 경우 당신을 위해 가비지 컬렉터라고 불리는 것들. –

+0

예,하지만 이것은 C입니다. :) – Anthony

0

변환 void* ->int*이 자동이기 때문에 malloc()에 의해 반환 된 값은 변환 할 필요가 없습니다.

또한이 같은 호출 다시 작성할 수 있습니다 : 그래서 지금 당신이 c의 유형을 변경하는 경우

c = malloc(sizeof *c); 

을, 당신은 모든 할당을 다시 할 필요가 없습니다.

[편집]

또한 할당이 성공했음을 확인하는 것이 좋을 것 (즉 c != NULL).

+0

4 행에서 (int *) 로의 캐스팅이 필요하지만 경고가 표시됩니다. –

+0

C의 경우, (int *) 또는 무엇이든 malloc()에서 제외하는 것이 좋습니다. 반드시 필요하지는 않으며 # 을 포함하지 않을 가능성이있는 오류를 다룹니다. –

1

malloc() 뒤에 c은 메모리 주소를 보유하는 변수입니다. 이 경우 c에는 할당 한 첫 번째 바이트의 메모리 주소 값이 있습니다.

c = 7라고 말하면 "c은 이제 메모리 주소 '7' '을 가리 킵니다. 이 경우 메모리 주소 "7"이 프로세스에 할당되지 않았으므로 free() 할 수 없습니다. 이론적으로는 메모리 주소 "7"(또는 0xa73c930bf 또는 설정 한 값)이 실제로 프로세스에 할당되었으므로 free()가 성공적으로 수행 될 수 있습니다.

그러나 c의 값을 변경하면 메모리는 계속 할당됩니다. 프로세스에는 여전히 메모리와 데이터가 있습니다. 포인터를 잃어 버렸습니다. 그 기억이 어디서 시작되는지 당신은 모른다.

괜찮습니다. C에서는 메모리 주소를 가리키는 변수가 다를 수 있습니다. 메모리 주소를 저장하는 "int *"보다는 "int"를 가질 수도 있습니다. C는 특정 메모리 주소 (실제로 숫자 일뿐)를 저장했는지 여부를 추적하지 않습니다. 이렇게하면 트랙을 유지하려는 시도가 유연성 C 포인터가 제공하는 일부를 잃을 것이므로 불가능한 작업입니다.

귀하의 질문에 대답 : 당신은 C의 가치를 추적 할 방법이 없으므로,이 프로그램은 메모리 누출이 있습니다.그리고 그 말은, 여러분의 프로그램이 사용하지 못하는 메모리를 가지고 있으며 따라서 자원을 낭비하고 있다는 것을 의미합니다.

그러나 프로그램이 종료되면 프로세스에 할당 된 모든 메모리가 해제되어 다른 프로그램에서 사용할 수있게됩니다.

+0

주소를 int에 저장할 수도 있지만 좋지 않습니다. int와 int *의 크기와 표현이 동일하다는 보장은 없습니다. –

+0

free()를 시도해 볼 수 있으며 구현시 free() 코드를 실제로 실행하여 메모리를 변경할 수 있습니다. 이것은 프로그램의 나머지 부분에서 중요 할 수있는 메모리 덩어리에서는 잘 정의되어 있지 않았기 때문에 거의 항상 나쁜 것입니다. –

+0

정수형 변수에 포인터를 저장하려면 intptr_t를 사용하십시오. intptr_t는 모든 유형의 포인터를 저장할만큼 충분히 큽니다. – sigjuice

1

제발 화를 내고 싶지는 않지만 질문의 요지는 명확하지 않습니다. 분명히하고있는 일은 언어가 의도하는 바와 직접적으로 충돌합니다. "소화기의 노즐이 가스 탱크 구멍에 들어갔 기 때문에 소화기 오일로 차의 가스 탱크를 채우면 어떻게 될까요?"라고 말하는 것과 같습니다.
나는 바보가 되려고하지 않고 왜이 특별한 질문을했는지 명확하지 않습니다. 나는 포인터의 힘을 이용하는 수많은 질문에 대해 생각할 수 있으며 잘못 사용하는 방법이 얼마나 많은지 궁금해 응용 프로그램 오류를 초래할 수 있습니다. 코드를 올바르게 수행 할 수있는 방법을 찾아 낼 수 있다면 코드 *가 수행하려고하는 작업이 있습니까? 또는 포인터를 추적하고 실수로 트랙을 잃어 버리면 해당 메모리를 다시 사용할 수 있도록하는 내부 메커니즘이 있는지 궁금하십니까? (그렇다면, 그 질문은 위에 답했다.)

1

글쎄, 이전에 할당하지 않은 메모리를 확보하려고했기 때문에이 시점에서 얻게되는 segfault는 운영 체제에서 사용자에게 권한을 부여하지 않은 메모리 주소를 참조하려고하기 때문에 발생합니다 당신을 (당신은 세분화 결함의 정의입니다) 당신에게.

일부 실험, 당신은 출력으로이 얻을 것이다, 당신은 Valgrind의에서 샘플 코드를 실행 할 말 :

 
    ==6945== Invalid free()/delete/delete[] 
    ==6945== at 0x402265C: free (vg_replace_malloc.c:323) 
    ==6945== by 0x80483D5: main (bla.c:6) 
    ==6945== Address 0x7 is not stack'd, malloc'd or (recently) free'd 
    ==6945== 
    ==6945== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 1) 
    ==6945== malloc/free: in use at exit: 4 bytes in 1 blocks. 
    ==6945== malloc/free: 1 allocs, 1 frees, 4 bytes allocated. 

그래서이 'PUR이 노래'메모리 누수입니다. 이제 자유롭게하려고하는 포인터가 할당 한 포인터에 '가까이'있도록 코드를 변경한다고 가정합니다 (운영 체제는 여전히 액세스 권한을 가지고 있으므로 운영 체제는 바이트 경계에 메모리 액세스 권한을 부여하지 않습니다).() (의 malloc의 소유자()과 free) 당신은 이상 (커널에 의해 방출) 세그먼트 오류를 ​​얻을 수 없겠죠이 응용 프로그램 만의 glibc에서 경고를 실행하는 경우

int main(){ 
    int* c; 
    c = (int*)malloc(sizeof(int)); 
    c++; 
    free(c); 
    return 0; 
} 

: 우리는이 같은 코드를 수정 말

 
    [email protected]:/tmp$ ./a.out 
    *** glibc detected *** ./a.out: free(): invalid pointer: 0x0804a00c *** 
    ... followed by a trace 

그래서 당신은 커널이 당신에 속하는 알고있는 일부 메모리를 확보하기 위해 노력하고 있지만, 그 중 glibc는 당신에게 나눠주고 기억할 수 없습니다.

 
    ==6955== Invalid free()/delete/delete[] 
    ==6955== at 0x402265C: free (vg_replace_malloc.c:323) 
    ==6955== by 0x80483D2: main (bla.c:5) 
    ==6955== Address 0x418a02c is 0 bytes after a block of size 4 alloc'd 
    ==6955== at 0x4022AB8: malloc (vg_replace_malloc.c:207) 
    ==6955== by 0x80483C0: main (bla.c:3) 
    ==6955== 
    ==6955== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 11 from 1) 
    ==6955== malloc/free: in use at exit: 4 bytes in 1 blocks. 
    ==6955== malloc/free: 1 allocs, 1 frees, 4 bytes allocated. 
+0

bash 프롬프트에서 FSM을 사용하는 경우 +1. –

관련 문제