malloc 한 포인터 뒷처리 방법.

매그넘의 이미지


char *p,*q,*r;
 
p=(char *)malloc(sizeof(char) * 10);
if(p==NULL){
    return NULL;
}
 
q=(char *)malloc(sizeof(char) * 10)
if(q==NULL){
    free(p);
    return NULL;
}
 
r=(char *)malloc(sizeof(char) * 10)
if(r==NULL){
    free(p);
    free(q);
    return NULL;
}
 
뭔가.. 줄줄이 작업
 
free(p);
free(q);
free(r);
 
return 뭔값;

함수안에서 malloc 을 여러 포인터에 해줘야 할일이 많이 있습니다. malloc 을 할때마다.. 메모리가 할당이 잘 되었는지

꼭 NULL 검사를 하라고 C책에 잘 설명이 나와 있어서.. 항상 NULL 포인터 검사를 합니다.

NULL 일경우에는 별다른 처리없이(메모리가 할당될 수 있게 쓰지 않는 메모리 블럭을 free 시킨다던지..) 함수를 그냥 return 을 시켜야합니다.(해야 한다기 보다는.. free 시킬 사용하지 않는 메모리 블럭이 없어서.. 어쩔수 없이 그냥 NULL 을 리턴시키는 상황)

함수를 return 을 시키기 전에.. 메모리 블럭이 할당된 부분들은 전부 free 를 시켜주고... return 을 시켜야하는데...

malloc 을 엄청나게 많이 쓰는 상황이라면... 각 null 체크 조건문에.. 전부 free를 적어줘야하는데.. 치기도 힘들거니와

보기에도 지저분해보이고.. 그닥.. 좋은 처리 같아 보이지는 않아 보입니다..(그래도 확실하기는 합니다..)

고수 님들은.. 저런 경우에 어떤식으로 처리를 하는지..조언 부탁드립니다...

----

박현우님 답변 고맙습니다...

지금 만들고 있는게..

데몬에 붙어서 돌아가는 모듈을 만드는중이어서 메모리릭과 세그멘테이션 폴트가 나면 절대 안되는 상황입니다. ^^.

그래서..일일히.. NULL 체크 다해주고.. 문제 있을경우에는.. 바로 함수 return 시키고..모듈 동작을 정지시켜야 되는 상황입니다.

Hyun의 이미지

경험상 malloc에서 NULL이 나올경우는
1. 잘못된 인자값으로 인해 너무 많은 메모리가 요구된 경우
2. 프로그램 버그로 인해 메모리가 새는 경우, 더이상 할당할 메모리가 없을 경우
이더군요...
그래서 전 그냥 간단히 만드는 프로그램의 경우는 NULL검사를 안합니다. 어차피 NULL이면 뒤에 세그먼트폴트나서 죽을꺼구 core만들어서 어디서 죽었는지 나올꺼구요, NULL검사하더라도 똑같이 프로그램이 오동작할꺼니깐요...

하지만 서버대몬이나 죽지 말아야 하는 프로그램은... 검사 다 해야죠... 어쩔수 있나요뭐...
가끔은 예외상황 처리때문에 동작에 해당하는 양만큼의 코드가 쓰이죠...

bushi의 이미지

예외 처리 부분을 함수 마지막으로 모아놓고 goto/label 꽃밭.

----------

리눅스 vm 의 over commit ... 어지간한 크기가 아니라면 malloc() 이 웬만해선 널리턴하지 않습니다. 그렇게 게기다가 실제로 read/write 하는 시점에서 가용 메모리가 없으면 ... seg.fault 보다 OOM kill 님이 먼저 등장하십니다. 엄한 놈이 sig 15 맞고 운명하십니다. 임베디드 쪽에선 아주 골치아픕니다. 중요한 어플리케이션들은 OOM kill 방어막을 치고 돌려야 될 정도입니다.
/proc/sys/vm/* 을 사용해서 튜닝이 가능합니다.
뭐... 사정이야 이렇지만, 전 항상 NULL 검사를 합니다.

무혼인형의 이미지

저도 oomkiller 때문에 골치 아픈 일이 많은데요.
방어막을 친다는 것이 어떻게 하는 것인지 설명 부탁 드리겠습니다.

익명사용자의 이미지

저 정도로 간단하면 한번에 모아서 하시면 됩니다.

null ptr 을 free 해도 상관없습니다.

    char *p,*q,*r;
 
    p=(char *)malloc(sizeof(char) * 10);
    q=(char *)malloc(sizeof(char) * 10);
    r=(char *)malloc(sizeof(char) * 10);
 
    if(!p || !q || !r) {
 
        free(p);
        free(q);
        free(r);
 
        return 0;
    }
cinsk의 이미지

free(3)는 인자로 들어온 값이 0일 경우 아무것도 하지 않습니다. 따라서 이 경우 다음과 같이 쓰는 것도 좋습니다:

    char *p,*q,*r;
 
    p = q = r = 0;
    p = malloc(sizeof(char) * 10);
    q = malloc(sizeof(char) * 10);
    r = malloc(sizeof(char) * 10);
 
    /* TODO: ... */
 
    free(r);
    free(q);
    free(p);
 
    return 0;

만약에 메모리 할당이 연속적으로 이루어지지 않고, 어떠한 다른 작업을 할 필요가 있다면 다음과 같이 하는 것도 생각해 볼 수 있습니다:

    char *p,*q,*r;
 
    p = q = r = 0;
 
    p = malloc(sizeof(char) * 10);
    if (!p) goto err_1;
    /* Do something */
    q = malloc(sizeof(char) * 10);
    if (!q) goto err_2;
    /* Do something */
    r = malloc(sizeof(char) * 10);
    if (!r) goto err_3;
    /* Do something */
 
    /* TODO: ... */
    goto end
 
err_3:
    /* Do something */
    free(r);
err_2:
    /* Do something */
    free(q);
err_1:
    /* Do something */
    free(p);
 
end:
    return 0;

그러나 goto를 자주 쓰면 코드의 흐름이 읽기 어렵기 때문에, 추천한다고 말하기는 좀 애매하군요.
--
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Korean Ver: http://www.cinsk.org/cfaqs/

lovewar의 이미지

코드에서 메모리의 해제 순서를 최근에 얻은 순으로 구현되어 있는데,

혹시, 이부분도 메모리란 리소스에 어떤 영향이 있는건가요?

전웅의 이미지

할당 순서와 해제 순서를 정순으로 놓고 r 이전까지 할당에
성공하고 r 할당시 실패한 경우를 생각해 보시기 바랍니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

전웅의 이미지

> 그러나 goto를 자주 쓰면 코드의 흐름이 읽기 어렵기 때문에, 추천한다고 말하기는 좀 애매하군요.
>

goto 가 유용하게 쓰일 수 있는 몇 안되는 경우 중 하나입니다.
패턴만 일관되게 유지한다면 저는 추천합니다.

p.s. 코드를 보니 초기화를 열심히 하시는 것 같습니다. :-)

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

falaris의 이미지

p = malloc( sizeof(uint8_t) * 30 );

if( p == NULL)
{
error;
}

q = p + 10;
r = p + 20;

저는 이렇게 사용을..

어떤 오픈소스 보니까 malloc을 최대한 줄이고,
에러 처리 부분도 줄이더라구요.
( 그 후 줄곧 따라서 합니다. ㅡㅡ;; )

근데, 좋은 방법인지 아닌지 고수님들 답변 좀 부탁 드려요!!

--------------@@
우분투+emacs교 정착.
cell 과 vme(rtai linux)...

매그넘의 이미지


메모리 풀 개념으로 사용하는건가요??..

저런식으로..메모리 블럭을 사용하는 오픈소스 참고해서 볼만한 소스 좀..

추천해주세요!!..^^..

superkkt의 이미지

memory pool과는 개념이 좀 다른것 같군요. 저런 방법을 사용하면 malloc을 한번만 하면되고 그에 따른 에러 처리도 역시 한번만 하면 되는 장점이 있겠지만, 메모리 해제를 할때는 해당 메모리를 참조하는 모든 루틴이 종료된 상태여야만 합니다. 간단한 함수 안에서만 사용한다면 특별히 문제 될건 없겠지만 모든 메모리 할당 루틴을 저렇게 사용하면 얻는것보다 잃는것이 더 많을것 같습니다.

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

전웅의 이미지

그렇게 할당된 메모리를 사용할 type 이 문자형이 아니라면
정렬제한 문제까지 있군요. :-(

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

falaris의 이미지

superkkt, 전웅 님 답변 감사합니다.

어떤 오픈소스에서 보고 괜찮다 싶어서, (나름 처음본 방법이었기에)
종종 따라 했었는데, 조심해서 써야 겠네요..

--------------@@
우분투+emacs교 정착.

cell 과 vme(rtai linux)...

MovingSpotlight의 이미지

    char *p,*q,*r;
 
    p = q = r = 0;
 
    p = malloc(sizeof(char) * 10);
    if (!p) goto Finalize;
    /* Do something */
    q = malloc(sizeof(char) * 10);
    if (!q) goto Finalize;
    /* Do something */
    r = malloc(sizeof(char) * 10);
    if (!r) goto Finalize;
    /* Do something */
 
    /* TODO: ... */
 
 
Finalize:
    if(p)
    {
       free(p);
       p = 0;
    }
    if(q)
    {
       free(q);
       q = 0;
    }
    if(r)
    {
       free(r);
       r = 0;
    }

goto를 사용해서 에러처리를 한곳에서 해버립니다. 개인적으로 goto를 유용하게 써먹을 수 있는 유일한 경우라고 생각합니다.

----
준비하세요. 당신 차례입니다.

----
준비하세요. 당신 차례입니다.

superkkt의 이미지

저도 이 방법을 선호합니다. 그리고 포인터가 유효한지 체크하는 루틴을 아래와 같이 메크로로 만들어서 사용합니다.

#define FREE(pointer) \
    if((pointer)) { \
        free((pointer)); \
        (pointer) = NULL; \
    }

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

전웅의 이미지

여러번 언급된 내용이지만 free() 에는 null pointer 를 전달하는 것이
허용됩니다 - 이를 허락한 주 이유가 clean up 을 돕기 위한 것은
아니지만 어쨌든 사실입니다.

따라서 if ((pointer)) 검사는 필요 없습니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

superkkt의 이미지

흐음.. free()에 NULL pointer를 전달해도 된다는 사실을 이 글을 통해서 처음 알았습니다. 그 동안 if로 검사하는 루틴은 포인터 변수를 선언하고 NULL로 초기화하는것과 함께 거의 습관화 되어버린 것중에 하나라서 이 버릇이 고쳐질지 모르겠네요. :-)

======================
BLOG : http://superkkt.com

======================
BLOG : http://superkkt.com

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.