programing

특히 malloc가 하나 이상 있을 때 C에서 malloc 고장을 어떻게 올바르게 처리할 수 있습니까?

telebox 2023. 7. 26. 21:48
반응형

특히 malloc가 하나 이상 있을 때 C에서 malloc 고장을 어떻게 올바르게 처리할 수 있습니까?

이것이 내 코드의 일부라고 가정합니다.

 int foo()
 {  
    char *p, *q ;
    if((p = malloc(BUFSIZ)) == NULL) {
        return ERROR_CODE;
    }
    if((q = malloc(BUFSIZ)) == NULL) {
        free(p)
        return ERROR_CODE;
    }
    /* Do some other work... */

    free(p);
    free(q);  
 }

첫번째가 가능하기 때문에malloc했지만 두 번째는 는 성적이두실번다니패합, 사합니다용저는공만지째를 사용합니다.free(p)두 번째 "오류 처리기"에 있습니다. 만약에 더 많은 요?malloc's I to (, 추가 삭제)'를 수정합니다malloc)?

C++는 RAII와 예외 안전 등이 있는 것으로 알고 있습니다.그러나 일반적으로, 올바른 처리 방법은 무엇입니까?mallocC에서의 실패? (아마도 일부를 사용할 것입니다.)goto?)

코드는 괜찮지만 변수가 많은 경우 다음을 선호합니다.

int
foo()
{
    char *p = NULL;
    char *q = NULL;
    int ret = 0;

    if (NULL == (p = malloc(BUFSIZ)))
    {
        ret = ERROR_CODE;
        goto error;
    }

    // possibly do something here

    if (NULL == (q = malloc(BUFSIZ)))
    {
        ret = ERROR_CODE;
        goto error;
    }

    // insert similar repetitions

    // hopefully do something here

  error:
    free (p);
    free (q);
    return ret;
}

freelay 고: 해제에 하십시오.NULL.no -opp로 됩니다.

이렇게 하면 피할 수 있습니다.n의 수준n마찬가지로 할 수 . (단, 파일 핸들 .)close()).

한 번에 모든 것을 할당할 수 있다는 것을 안다면 dasblinkenlight는 좋은 대답을 할 수 있지만, 여기 다른 방법이 있습니다.

int
foo()
{
    int ret = 0;
    char *p = malloc(BUFSIZ);
    char *q = malloc(BUFSIZ);
    char *r = malloc(BUFSIZ);
    if (!p || !q || !r)
    {
        ret = ERROR_CODE;
        goto exit;
    }

    // do something

  exit:
    free(p);
    free(q);
    free(r);
    return ret;
}

최종 가능성: 실제로 프로그램을 종료하려면malloc 패실, 사고려를 사용하는 것을 합니다.malloptM_CHECK_ACTION선택.이것은 만듭니다.malloc()되면 장애확및호출을 합니다.abort()유용한 메시지를 인쇄할 수 있습니다.

맨 페이지에서:

이름.

mallopt 변수 설정

개요

  #include <malloc.h>

  int mallopt(int param, int value);

묘사

mallopt()함수의 변수를 합니다( ).malloc(3) , ). 그.param인수는 수정할 매개 변수를 지정합니다.value해당 매개 변수의 새 값을 지정합니다.

다값을 지수있다니습에 대해 다음과 할 수 .param:

M_CHECK_ACTION

이 매개 변수를 설정하면 다양한 종류의 프로그래밍 오류가 감지될 때(예: 동일한 포인터를 두 번 해제) glibc가 응답하는 방식이 제어됩니다.이 파라미터에 할당된 값의 최하위 3비트(2, 1 및 0)는 다음과 같이 glibc 동작을 결정합니다.

비트 0: 이 비트가 설정되어 있으면 다음에 한 줄 메시지를 인쇄합니다.stderr오류에 대한 세부 정보를 제공합니다.는 " 지는문자로시다니작합열메시다니시▁string합▁the▁the▁with▁starts" 문자열로 시작합니다."*** glibc detected ***"프로그램 이름, 오류가 탐지된 메모리 할당 함수의 이름, 오류에 대한 간단한 설명 및 오류가 탐지된 메모리 주소가 뒤에 나옵니다.

비트 1: 이 비트가 설정된 경우, 비트 0으로 지정된 오류 메시지를 인쇄한 후 프로그램이 호출되어 종료됩니다.abort(3) 오류 중단 에 2.4 이 glibc 도 0 정 를 지 인 메 고 하 쇄 중 사 프 다 램 인 다 니 추 합 쇄 을 스 적 같 택 방 로 후 으 식 은 과 음 은 버 그 로 의 이 에 전 는 하 트 단 시 되 류 면 에 서 비 설 오 ▁in ▁a ▁tracebacktrace(3)프로세스의 메모리 매핑을 다음과 같은 방식으로 인쇄합니다./proc/[pid]/maps)proc(5)).

비트 2: (glibc 2.4 이후) 비트 0도 설정된 경우에만 이 비트가 적용됩니다.이 비트가 설정된 경우 오류를 설명하는 한 줄 메시지가 오류가 감지된 함수의 이름과 오류에 대한 간단한 설명만 포함하도록 단순화됩니다.

합격해도 완벽하게 괜찮으니까요.NULLfree()필요한 모든 것을 "연속선"으로 할당하고, 모든 것을 한 번에 확인한 다음, 실제로 작업을 수행했는지 여부에 관계없이 완료되면 모든 것을 해방할 수 있습니다.

char *p = malloc(BUFSIZ);
char *q = malloc(BUFSIZ);
char *r = malloc(BUFSIZ);
if (p && q && r) {
    /* Do some other work... */
}
free(p);
free(q);
free(r);

이것은 중간 종속성이 없는 한, 즉 다단계 종속성을 가진 구조물이 없는 한 작동합니다.이 경우, 모든 메모리 블록이 비메모리 블록이라고 가정하지 않고 이러한 구조를 해제하기 위한 함수를 정의하는 것이 좋습니다.NULL.

많은 양의 할당의 경우 할당을 추적하는 메모리 관리자를 만드는 데 시간을 투자합니다.이렇게 하면 기능의 성공 여부에 관계없이 누출에 대해 걱정할 필요가 없습니다.

일반적인 아이디어는 다음을 위한 래퍼를 만드는 것입니다.malloc성공적인 할당을 기록한 다음 요청 시 해당 할당을 해제합니다.메모리를 확보하려면 특수 크기를 래퍼 함수에 전달하기만 하면 됩니다. 기사 용크용 사용0메모리를 확보하는 것이 적절합니다. 만약 당신이 당신의 실제 할당 중 어떤 것도0크기가 큰 블록그렇지 않으면 다음을 사용할 수 있습니다.~0ULL무료로 요청할 수 있는 크기로.

다음은 무료 간에 최대 100개의 할당을 허용하는 간단한 예입니다.

#define FREE_ALL_MEM 0

void *getmem( size_t size )
{
    static void *blocks[100];
    static int count = 0;

    // special size is a request to free all memory blocks
    if ( size == FREE_ALL_MEM )
    {
        for ( int i = 0; i < count; i++ )
            free( blocks[i] );
        count = 0;
        return NULL;
    }

    // using a linked list of blocks would allow an unlimited number of blocks
    // or we could use an array that can be expanded with 'realloc'
    // but for this example, we have a fixed size array
    if ( count == 100 )
        return NULL;

    // allocate some memory, and save the pointer in the array
    void *result = malloc( size );
    if ( result )
        blocks[count++] = result;

    return result;
}

int foo( void )
{
    char *p, *q;

    if ( (p = getmem(BUFSIZ)) == NULL ) {
        return ERROR_CODE;
    }
    if ( (q = getmem(BUFSIZ)) == NULL ) {
        getmem( FREE_ALL_MEM );
        return ERROR_CODE;
    }

    /* Do some other work... */

    getmem( FREE_ALL_MEM );
    return SUCCESS_CODE;
}

습관의 문제지만, 저는 다음을 선호합니다.

int returnFlag = FAILURE;

if ((p = malloc...) != NULL)
{
    if ((q = malloc..) != NULL)
    {
        // do some work
        returnFlag = SUCCESS; // success only if it is actually success

        free(q);
    }
    free(p);
}

return returnFlag; // all other variants are failure

많은 수의 항목을 할당해야 하는 경우, 지저분해질 수 있습니다.'이동' 접근 방식을 피하도록 합니다.오래된 'go to is bad' 윤리 때문이 아니라, 그런 식으로 하면 정말로 광기와 기억 유출이 있을 수 있기 때문입니다.

소수의 말록들에게는 약간 과잉 살상이지만, 다음과 같은 접근법을 고려할 수 있습니다.

void free_mem(void **ptrs, size_t len)
{
    for (size_t i = 0; i < len; ++i)
    {
        free(ptrs[i]);
        ptrs[i] = NULL;
    }
}

int foo(...)
{
    void *to_be_freed[N];
    int next_ptr = 0;
    for (size_t i = 0; i < N; ++i) to_be_freed[i] = NULL;

    p = malloc(..);
    if (!p)
    {
        free_mem(to_be_freed,N);
        return ERROR_CODE;
    }
    to_be_freed[next_ptr++] = p;

    // Wash, rinse, repeat, with other mallocs
    free_mem(to_be_freed,N)
    return SUCCESS;
}

실제로, 여러분은 아마도 이것을 추적하는 무언가로 malloc을 감쌀 수 있을 것입니다.배열 및 배열 크기를 구조에 넣고 원하는 할당 크기로 전달합니다.

첫 번째 답변은 말록으로 인한 오류 이외의 오류에도 사용할 수 있기 때문에 가장 일반적인 목적이라고 생각합니다.하지만 저는 고토를 제거하고 그렇게 루프하는 동안 단일 패스를 사용할 것입니다.

int foo()
{
  char *p = NULL;
  char *q = NULL;
  int ret = 0;
  do {
    if (NULL == (p = malloc(BUFSIZ)))
    {
      ret = ERROR_CODE;
      break;
    }

    // possibly do something here

    if (NULL == (q = malloc(BUFSIZ)))
    {
      ret = ERROR_CODE;
      break;
    }

    // insert similar repetitions

    // hopefully do something here
  } while(0);
  free (p);
  free (q);
  return ret;
}

언급URL : https://stackoverflow.com/questions/27451220/how-can-i-correctly-handle-malloc-failure-in-c-especially-when-there-is-more-th

반응형