[c] C에서 malloc을 언제 사용해야하고 언제 사용하지 않아야합니까?

malloc ()이 어떻게 작동하는지 이해합니다. 내 질문은 다음과 같은 것을 보게 될 것입니다.

#define A_MEGABYTE (1024 * 1024)

char *some_memory;
size_t size_to_allocate = A_MEGABYTE;
some_memory = (char *)malloc(size_to_allocate);
sprintf(some_memory, "Hello World");
printf("%s\n", some_memory);
free(some_memory);

간결함을 위해 오류 검사를 생략했습니다. 내 질문은 메모리의 일부 정적 저장소에 대한 포인터를 초기화하여 위의 작업을 수행 할 수 없다는 것입니다. 혹시:

char *some_memory = "Hello World";

유지해야하는 값을 선언 / 초기화하는 대신 실제로 메모리를 직접 할당해야하는 시점은 무엇입니까?



답변

char *some_memory = "Hello World";

문자열 상수에 대한 포인터를 만들고 있습니다. 즉, “Hello World”문자열이 메모리의 읽기 전용 부분 어딘가에 있으며 포인터 만 있으면됩니다. 문자열을 읽기 전용으로 사용할 수 있습니다. 당신은 할 수없는 그것을 변경합니다. 예:

some_memory[0] = 'h';

문제를 요구하고 있습니다.

반면에

some_memory = (char *)malloc(size_to_allocate);

char 배열 (변수)을 할당하고 some_memory는 할당 된 메모리를 가리 킵니다. 이제이 배열은 읽고 쓸 수 있습니다. 이제 다음을 수행 할 수 있습니다.

some_memory[0] = 'h';

배열 내용이 “hello World”로 변경됩니다.


답변

정확한 예를 들어 malloc은 거의 사용되지 않습니다.

malloc이 필요한 주된 이유는 코드 범위와 다른 수명을 가져야하는 데이터가있을 때입니다. 코드는 하나의 루틴에서 malloc을 호출하고 포인터를 어딘가에 저장하고 결국 다른 루틴에서 free를 호출합니다.

두 번째 이유는 C가 할당을 위해 스택에 충분한 공간이 남아 있는지 알 수 없기 때문입니다. 코드가 100 % 견고해야하는 경우 malloc을 사용하는 것이 더 안전합니다. 그러면 코드가 할당 실패를 알고 처리 할 수 ​​있기 때문입니다.


답변

malloc은 컴파일 타임에 처리되므로 크기를 변경할 수없는 hello world 예제와 같은 정적 선언과 비교할 때 런타임에 메모리를 할당, 재 할당 및 해제하는 훌륭한 도구입니다.

따라서 Malloc은 파일 내용 읽기 또는 소켓 처리와 같이 임의 크기의 데이터를 처리 할 때 항상 유용하며 처리 할 데이터의 길이를 알지 못합니다.

물론, 당신이 준 것과 같은 사소한 예에서 malloc은 마법의 “올바른 작업에 적합한 도구”는 아니지만 더 복잡한 경우 (예 : 런타임에 임의의 크기 배열 생성)의 경우 유일한 방법입니다. 가다.


답변

사용해야하는 정확한 메모리 크기를 모르는 경우 동적 할당 ( malloc) 이 필요합니다 . 예를 들어 사용자가 애플리케이션에서 파일을 여는 경우가 있습니다. 파일의 내용을 메모리로 읽어야하지만 물론 사용자가 런타임에 그 자리에서 파일을 선택하기 때문에 파일의 크기를 미리 알 수 없습니다. 따라서 기본적으로 malloc작업중인 데이터의 크기를 미리 모를 때 필요 합니다. 적어도 이것이 .NET을 사용하는 주요 이유 중 하나입니다 malloc. 컴파일 타임에 이미 크기를 알고있는 (수정하고 싶지 않은 경우) 간단한 문자열이있는 예제에서는 동적으로 할당하는 것이별로 의미가 없습니다.


주제에서 약간 벗어 났지만 … .NET Framework를 사용할 때 메모리 누수가 발생하지 않도록 매우주의해야합니다 malloc. 이 코드를 고려하십시오.

int do_something() {
    uint8_t* someMemory = (uint8_t*)malloc(1024);

    // Do some stuff

    if ( /* some error occured */ ) return -1;

    // Do some other stuff

    free(someMemory);
    return result;
}

이 코드에 무엇이 잘못되었는지 보십니까? malloc와 사이에 조건부 반환 문이 free있습니다. 처음에는 괜찮아 보이지만 생각해보십시오. 오류가 있으면 할당 한 메모리를 해제하지 않고 돌아갑니다. 이것은 메모리 누수의 일반적인 원인입니다.

물론 이것은 매우 간단한 예이며 여기서 실수를 쉽게 알 수 있지만 포인터, mallocs, frees 및 모든 종류의 오류 처리로 가득 찬 수백 줄의 코드를 상상해보십시오 . 상황이 정말 빨리 지저분해질 수 있습니다. 이것이 내가 적용 가능한 경우 C보다 현대적인 C ++를 선호하는 이유 중 하나이지만, 그것은 완전히 다른 주제입니다.

따라서를 사용할 때마다 malloc항상 메모리가 free가능한 한 d 일 가능성이 있는지 확인하십시오 .


답변

char *some_memory = "Hello World";
sprintf(some_memory, "Goodbye...");

는 불법이며 문자열 리터럴은 const.

이것은 스택에 또는 전역 적으로 (선언 된 위치에 따라) 12 바이트 문자 배열을 할당합니다.

char some_memory[] = "Hello World";

추가 조작을위한 공간을 남겨 두려면 배열의 크기를 더 크게 지정하도록 지정할 수 있습니다. (하지만 스택에 1MB를 넣지 마십시오.)

#define LINE_LEN 80

char some_memory[LINE_LEN] = "Hello World";
strcpy(some_memory, "Goodbye, sad world...");
printf("%s\n", some_memory);


답변

메모리를 할당해야하는 한 가지 이유는 런타임에 메모리를 수정하려는 경우입니다. 이 경우 스택의 malloc 또는 버퍼를 사용할 수 있습니다. 포인터에 “Hello World”를 할당하는 간단한 예제는 “일반적으로”런타임에 수정할 수없는 메모리를 정의합니다.


답변