특히 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와 예외 안전 등이 있는 것으로 알고 있습니다.그러나 일반적으로, 올바른 처리 방법은 무엇입니까?malloc
C에서의 실패? (아마도 일부를 사용할 것입니다.)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
패실, 사고려를 사용하는 것을 합니다.mallopt
의M_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도 설정된 경우에만 이 비트가 적용됩니다.이 비트가 설정된 경우 오류를 설명하는 한 줄 메시지가 오류가 감지된 함수의 이름과 오류에 대한 간단한 설명만 포함하도록 단순화됩니다.
합격해도 완벽하게 괜찮으니까요.NULL
free()
필요한 모든 것을 "연속선"으로 할당하고, 모든 것을 한 번에 확인한 다음, 실제로 작업을 수행했는지 여부에 관계없이 완료되면 모든 것을 해방할 수 있습니다.
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
'programing' 카테고리의 다른 글
매개 변수로 char* vs const char* (0) | 2023.07.26 |
---|---|
MySQL ERROR 1231(42000):변수 'character_set_client'를 'NULL' 값으로 설정할 수 없습니다. (0) | 2023.07.26 |
콜리메이션이 이해가 안 돼요?(Mysql, RDBMS, 문자 집합) (0) | 2023.07.21 |
SQL Server 2016 - 잘못된 개체 이름 'hibernate_sequence' (0) | 2023.07.21 |
Oracle 번호 및 varchar 조인 (0) | 2023.07.21 |