sourcetip

C에서 포인터가 이미 해제되었는지 어떻게 확인합니까?

fileupload 2023. 7. 2. 20:55
반응형

C에서 포인터가 이미 해제되었는지 어떻게 확인합니까?

포인터가 이미 해제되었는지 확인하고 싶습니다.gnu 컴파일러 세트를 사용하여 이것을 어떻게 합니까?

그럴수는 없어요.이를 추적하는 방법은 포인터를 다음에 할당하는 것입니다.0또는NULL그것을 해방시킨 후에.그러나 Fred Larson이 언급했듯이, 이것은 동일한 위치를 가리키는 다른 포인터에는 아무런 영향을 주지 않습니다.

int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL;

그럴수는 없어요.그냥 할당NULL당신 뒤에 있는 것.free그것은 당신이 그것을 두 번 풀어주지 않도록 확실히 하기 위해. (괜찮아요.free(NULL)).

더 좋은 것은 가능하면 "잊어버린" 곳에 코드를 쓰지 않는 것입니다.

편집

질문을 포인터로 가리킨 메모리가 이미 해제되었는지 확인하는 방법으로 해석: 할 수 없습니다.부기는 당신이 직접 해야 합니다.

Greg가 언급했듯이 포인터가 해제되었는지 여부를 확인할 수 있는 신뢰할 수 있는 방법은 없습니다. 해제된 메모리가 다른 관련 없는 데이터에 의해 점유될 수 있으므로 잘못된 결과를 얻을 수 있습니다.

그리고 실제로 포인터가 해제되었는지 확인할 수 있는 표준 방법은 없습니다.그렇긴 하지만,glibc기능이 있음(mcheck,mprobe) 힙 일관성 검사를 위한 포인터의 malloc 상태를 찾기 위해, 그 중 하나는 포인터가 해제되었는지 확인하는 것입니다.

그러나 이러한 함수는 주로 디버깅에만 사용되며 스레드 안전하지 않습니다.요구 사항을 잘 모르는 경우 이러한 기능을 사용하지 마십시오.짝을 이루었는지 확인하십시오.malloc/free.


예: http://ideone.com/MDJkj :

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

void no_op(enum mcheck_status status) {}

int main()
{
    mcheck(&no_op);

    void* f = malloc(4);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_OK);

    free(f);

    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);
    printf("%d (should be %d)\n", mprobe(f), MCHECK_FREE);

    return 0;
}

포인터 값을 할당하는 매크로를 작성하면 포인터 값에 NULL을 할당하는 개념을 확장할 수 있습니다.예:

#define FREE(ptr) do{ \
    free((ptr));      \
    (ptr) = NULL;     \
  }while(0)

그런 다음 코드가 무료()가 아닌 무료()만 사용하는지 확인하면 작성한 코드가 동일한 메모리를 두 번 사용하지 않는다는 것을 상당히 확신할 수 있습니다.물론 그것은 메모리를 확보하는 라이브러리 기능에 대한 다중 호출을 방지하는 데 아무런 도움이 되지 않습니다.그리고 그것은 모든 몰록들에게 무료가 있다는 것을 보장하지 않습니다.

함수를 사용하여 시도할 수 있지만, 참조 연산자를 넣어야 하고 더 이상 무료()에 대한 일반적인 호출처럼 보이지 않기 때문에 워드가 됩니다.

당신은 할 수 없기 때문에 당신은 할 수 없습니다.

가져온 포인터 추적malloc()그리고 그것들을 자유롭게 해주고, 단 한 번.

메모리는 메모리가 없으므로 할당 여부를 알 수 없습니다.OS의 메모리 관리자만 알 수 있습니다(그러나 C에는 이 정보를 쿼리하는 표준화된 메커니즘이 포함되어 있지 않습니다).

는 이 이 나는이대인 있습니다.a little bit늦었지만, 저는 방금 이 답변을 읽고 다음을 확인하기 위해 코드를 작성했습니다.

Free(자유)는 메모리 블록을 자체 자유 블록 목록에 넣습니다.일반적으로 주소 공간에서 인접한 블록을 함께 혼합하려고 시도합니다.무료 블록 목록은 메모리 청크의 순환 목록일 뿐이며 처음에는 물론 일부 관리 데이터가 포함되어 있습니다.무료 목록은 또한번째 위치이며, malloc은 필요할 때 새로운 메모리 덩어리를 찾습니다.OS에서 새 메모리를 호출하기 전에 검색됩니다.필요한 메모리보다 큰 청크가 발견되면 두 부분으로 나뉩니다.하나는 발신자에게 반환되고 다른 하나는 무료 목록에 다시 포함됩니다.

이 코드는 할당된 첫 번째 포인터가 해제된 경우에만 확인합니다.

int is_freed(void *p)
{
    void * q;
    char p_addr [50];
    char q_addr [50];

    sprintf(p_addr, "%p", p);

    q = malloc (1);
    sprintf(q_addr, "%p", q);
    free (q);

    return ! strcmp(q_addr, p_addr);
}

저는 HP-UX와 Linux Redhat에서 이 코드를 테스트해 보았는데 포인터 하나만 사용해도 작동합니다.

우호적인 메모:포인터 매개 변수를 다음으로 설정하는 경우NULL다른 함수에서, 그리고 그것이 인수에 영향을 미치길 원하며(원래 포인터가 전달됨), 함수는 그 포인너에 대한 포인터를 받아들여야 할 것입니다(더블 ptr).

예를들면,

void cleanup(int *int_ptr) {
  free(int_ptr);
  int_ptr = NULL; // Not working ??
}

int main() {
  int a = 8; 
  int* a_ptr = &a;
  cleanup(a_ptr);
  printf("%p", a_ptr); // Unexpected: Does not print NULL
}

이것은 예상대로 작동하지 않습니다. 근거:a_ptr는 포인터이지만 실제로는 값을 포함하는 변수일 뿐입니다. 포함된 값은 가상 메모리 주소이기 때문에 약간 특별하지만 그래도 값입니다.이 이 값 전 다 될 달 때 로로 넘어갈 때.cleanup변수와 로 다른변처럼들수럼cleanup해당 값의 로컬 복사본을 만듭니다.그래서 만약에a_ptr가치가 있습니다.0x7ffd86656848,int_ptr은 " " " " " " 입니다.0x7ffd86656848int_ptrNULL 설정하지 않습니다.a_ptrNULL.

그래서, 만약 당신이 설정하고 싶다면.int_ptr = NULL당신은 이중 포인터를 통과해야 할 것입니다.

void cleanup(int **int_ptr) {
  free(*int_ptr);
  *int_ptr = NULL;
}

신호 SIGABRT를 포착하는 함수를 작성합니다.

이렇게 해야 합니다.

bool pointer_allocated(void* ptr) {
  return ptr != NULL;
}

편집: 이 답변은 매우 잘못되었으므로 수정하겠습니다.

포인터의 할당 해제 여부를 확인하려면 포인터를 해제한 후 NULL로 설정하면 됩니다.

free(ptr);
ptr = NULL;

// You can use ptr != NULL or ptr != 0, its pretty much the same thing
if(ptr) {
    // Pointer is set
} else {
    // Pointer has been freed
}

포인터를 다시 사용하지 않을 경우 포인터를 NULL로 설정할 필요가 없습니다.이 경우에는 의미가 없으며 CPU 시간만 낭비합니다.

언급URL : https://stackoverflow.com/questions/8300853/how-to-check-if-a-pointer-is-freed-already-in-c

반응형