codememo

free()는 메모리를 제로로 만드는 것입니까?

tipmemo 2023. 8. 1. 20:33
반응형

free()는 메모리를 제로로 만드는 것입니까?

오늘까지 나는 전화하는 것이free()메모리 공간에서는 추가 할당을 위해 다른 수정 없이 해제합니다.특히, 이 SO 질문을 고려할 때, 그것은 분명히 다음과 같습니다.free()메모리를 제로로 만들지 않습니다.

그러나 다음 코드를 고려해 보겠습니다(test.c).

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

int main()
{
    int* pointer;

    if (NULL == (pointer = malloc(sizeof(*pointer))))
        return EXIT_FAILURE;

    *pointer = 1337;

    printf("Before free(): %p, %d\n", pointer, *pointer);

    free(pointer);

    printf("After free(): %p, %d\n", pointer, *pointer);

    return EXIT_SUCCESS;
}

컴파일 중(GCC 및 Clang 모두):

gcc test.c -o test_gcc
clang test.c -o test_clang

결과:

$ ./test_gcc 
Before free(): 0x719010, 1337
After free(): 0x719010, 0
$ ./test_clang
Before free: 0x19d2010, 1337
After free: 0x19d2010, 0

그것은 왜 그럴까?제가 지금까지 거짓말 속에 살았나요, 아니면 제가 몇 가지 기본적인 개념을 잘못 이해했나요?아니면 더 나은 설명이 있습니까?

일부 기술 정보:

Linux 4.0.1-1-ARCH x86_64
gcc version 4.9.2 20150304 (prerelease) (GCC)
clang version 3.6.0 (tags/RELEASE_360/final)

당신의 질문에 대한 결정적인 대답은 하나도 없습니다.

  • 첫째, 자유 블록의 외부 동작은 시스템에 릴리스되었는지 아니면 프로세스 또는 C 런타임 라이브러리의 내부 메모리 풀에 자유 블록으로 저장되었는지에 따라 달라집니다.현대의 OS에서 "시스템에 반환된" 메모리는 프로그램에 액세스할 수 없게 됩니다. 즉, 프로그램이 0으로 설정되었는지 여부에 대한 문제는 해결되지 않습니다.

(나머지는 내부 메모리 풀에 보존된 블록에 적용됩니다.)

  • 둘째, 빈 메모리를 특정 값(액세스하면 안 되기 때문에)으로 채우는 것은 의미가 거의 없지만 이러한 작업의 성능 비용은 상당할 수 있습니다.이것이 대부분의 구현이 메모리 확보에 아무런 영향을 미치지 않는 이유입니다.

  • 세 번째로, 디버깅 단계에서 미리 결정된 가비지 값으로 프리 메모리를 채우는 것은 오류를 잡는 데 유용할 수 있습니다(이미 프리 메모리에 대한 액세스와 같은). 이것이 표준 라이브러리의 많은 디버그 구현이 미리 결정된 값이나 패턴으로 프리 메모리를 채우는 이유입니다.(0, BTW는 이러한 값에 대한 최선의 선택이 아닙니다. 같은 거.0xDEADBABE패턴이 훨씬 더 말이 됩니다.)그러나 이 작업은 성능에 영향을 미치지 않는 라이브러리의 디버그 버전에서만 수행됩니다.

  • 넷째, 힙 메모리 관리의 많은 (대부분의) 일반적인 구현은 내부 목적을 위해 해제된 블록의 일부를 사용합니다. 즉, 일부 의미 있는 값을 저장합니다.즉, 블록의 해당 영역은 다음과 같이 수정됩니다.free그러나 일반적으로 "제로"는 아닙니다.

물론 이 모든 것은 구현에 크게 의존합니다.

일반적으로, 당신의 원래 믿음은 완벽하게 맞습니다: 코드의 릴리스 버전에서 해방된 메모리 블록은 블록 전체에서 수정되지 않습니다.

free()일반적으로 메모리를 0으로 설정하지 않습니다.나중에 전화할 때 재사용할 수 있도록 간단히 릴리스합니다.malloc()특정 구현은 메모리를 알려진 값으로 채울 수 있지만 이는 순전히 라이브러리의 구현 세부 정보입니다.

Microsoft의 런타임은 빈 메모리와 할당된 메모리를 유용한 값으로 표시하는 데 유용합니다(Visual Studio C++에서 메모리 할당 표현은 무엇입니까? 참조).자세한 내용은)을 참조하십시오.저는 또한 그것이 실행될 때 잘 정의된 함정을 야기할 수 있는 값들로 가득 찬 것을 보았습니다.

더 좋은 설명이 있습니까?

있어.포인터가 끝난 후 참조 해제free()d는 정의되지 않은 동작을 초래하므로, 구현은 메모리 영역이 0으로 채워졌다고 속이는 행위를 포함하여 원하는 모든 것을 수행할 수 있는 권한을 가집니다.

여러분이 실제로 알지 못했을 수도 있는 함정이 여기에 있습니다.

free(pointer);

printf("After free(): %p \n", pointer); 

가치를 읽는 것만으로도pointer먼저 가세요.free포인터가 불확실해지기 때문에 정의되지 않은 동작입니다.

물론 아래 예시와 같이 자유 포인터는 참조 해제가 허용되지 않습니다.

free(pointer);

printf("After free(): %p, %d\n", pointer, *pointer);

으로 ps로 때. 일반적으로 주소를 인쇄할 때%p(의 경우처럼)printf▁)다던지.(void*)를 들어, 예를 들어, 기호입니다.(void*)pointer되지 않은 .

free()는 메모리를 제로로 만드는 것입니까?

아니요. glibc malloc 구현은 내부 하우스키핑 데이터를 위해 이전 사용자 데이터의 포인터 크기의 최대 4배까지 덮어쓸 수 있습니다.

세부 정보:

은 다음다과같다니습음은▁the다▁the.malloc_chunkglibc의 구조(여기 참조):

struct malloc_chunk {

  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

할당된 메모리 청크의 사용자 데이터에 대한 메모리 영역은 다음으로 시작합니다.size 장입 뒤에. 후이후free가 빈 될 수 . 첫 번째 메모리 청크 목록에 사용할 수 있습니다.4 * sizeof(struct malloc_chunk *)이전 사용자 데이터의 바이트를 덮어쓰므로 이전 사용자 데이터 값과 다른 값이 인쇄됩니다.정의되지 않은 동작입니다.할당된 블록이 더 크면 분할 결함이 있을 수 있습니다.

다른 사람들이 지적했듯이, 당신은 어떤 것도 할 수 없습니다.freed 포인터(항상 피해야 하는, 정의되지 않은 무시무시한 동작인 경우, 이 항목을 참조하십시오.)

실제로는 단순히 코딩하지 않는 것이 좋습니다.

free(ptr);

하지만 항상 코딩을 합니다.

free(ptr), ptr=NULL;

(실질적으로 말해서 이것은 이중을 제외하고 일부 버그를 잡는 데 많은 도움이 되기 때문입니다.free

한다면ptr. 컴파일러는 " 이에않습그다니후를 합니다. 컴파일러는 할당을 건너뛰어 최적화합니다.NULL

실로컴파는다알있습다니에 대해 있습니다.free그리고.malloc(표준 C 라이브러리 헤더는 GCC와 Clang/LLVM 모두가 이해하는 적절한 함수 속성으로 이러한 표준 함수를 선언할 것이기 때문에) 코드를 최적화할 수 있습니다.malloc&free ...의 시행.malloc그리고.freeC 표준 라이브러리(예: Linux의 경우 매우 자주 GNU glibc 또는 musl-libc)에 의해 제공되므로 실제 동작은libc(컴파일러 자체가 아님).해당 설명서, 특히 무료(3) 맨 페이지를 읽습니다.

BTW, 리눅스, »glibc그리고.musl-libc는 자유 소프트웨어이므로 사용자의 동작을 이해하기 위해 소스 코드를 연구할 수 있습니다.때때로 mmap(2)와 같은 시스템 호출을 사용하여 커널에서 가상 메모리를 얻곤 했지만(나중에 munmap(2)를 사용하여 커널로 메모리를 다시 릴리스합니다), 일반적으로 이전에 재사용하려고 합니다.free를 d mallocs

실로는.free할 수 있었다munmap당신의 기억력 (큰 기억력을 위한 기억력)malloczones) - -ated zones) - 그면당신그얻것될게것입다니을은러▁-).SIGSEGV감히 (나중에) 그것을 언급하지 않는다면.freed 포인터, 그러나 종종 (작은 메모리 영역에 사용됨) 나중에 해당 영역을 다시 사용할 수 있습니다.정확한 동작은 구현에 따라 다릅니다.보통free방금 해제된 영역을 지우거나 쓰지 않습니다.

사용자는 자신의 데이터를 재정의(즉, 재구현)할 수도 있습니다.malloc그리고.free당신의 구현이 C99 또는 C11 표준이 말하는 것과 호환되는 동작을 가지고 있다면 libtcmalloc와 같은 특수 라이브러리를 링크함으로써 가능할 것입니다.

Linux에서는 메모리 오버커밋을 사용하지 않도록 설정하고 valgrind를 사용합니다.컴파일 대상gcc -Wall -Wextra 아마)-g디버깅할 때; 패스하는 것도 고려할 수 있습니다.-fsanitize=addressgcc또는clang적어도 장난꾸러기 벌레들을 사냥하기 위해서.)

BTW, 가끔은hm의 보수적인 쓰레기 수집기가 유용할 수 있습니다; 당신은 (당신의 전체 프로그램에서) 사용할 것입니다.GC_MALLOCmalloc그리고 당신은 신경쓰지 않을 것입니다.free-잉 메모리.

free()실제로 메모리를 운영 체제에 반환하고 프로세스를 더 작게 만들 수 있습니다.일반적으로, 그것이 할 수 있는 모든 것은 공간을 재사용하기 위해 malloc에 대한 나중의 호출을 허용하는 것입니다.그 동안 공간은 프로그램에서 내부적으로 사용되는 자유 목록의 일부로 남아 있습니다.malloc.

언급URL : https://stackoverflow.com/questions/30683519/is-free-zeroing-out-memory

반응형