new, delete 와 malloc, free의 혼용

ddoman의 이미지

이래저래 글들을 읽어보다가
new로 생성한것을 free로 해제한다던지,
malloc을 delete로..

그런 코드는 위험하다고 하는데, 제 코드에는 그런문제가 없을까
생각을 해보아서 코드를 grep 해보았습니다.

같은 함수안에서는 모두 malloc 한 부분이 있으면 free를 쓰고,
new했으면 delete를 맞게끔 호출 하게끔 코딩이 되어있었습니다만..
눈에 뻔히 보이니까요..일부러 섞어 쓰는 사람은 드물것 같습니다.

그런데, 그렇게 사용될 소지가 있는부분은

--------------a.cpp------------
void GetBuf( char* buf )
{
	buf = ( char* )malloc( 30 );
}

--------------b.cpp------------
int main()
{
	char* abc;
	GetBuf( abc );

	.....
	......

	delete abc;
}

위와 같은 부분이었습니다.
이곳저곳에 쓸 요람으로 a.cpp를 만들어 뒀었는데

만약 팀 프로젝트의 경우,
해당 함수를 호출 하는 쪽 코드에서 이 함수를 통해 얻은 메모리를
짝이 맞지않는 메모리 해제 함수를 사용하지 않는다는 보장을 할 수 없다는
생각이 들었습니다.

항상 소스를 보면서 확인해야하는지....만약 이를 철저히 지키지 않는다면
에러가 발생하는지 궁금합니다.

만약 외부라이브러리를 가져다 쓸 경우, 위의 경우에 해당되는지 않되는지
확인하기위해 꼭 소스를 따라가서 이놈이 new로 한건지 malloc으로
한건지 확인해봐야 합니까?

물론, C++로 짠다면 가능한 new/delete만 사용해야하지만
혼자 모든 코드를 짜는것도 아니고( 다른 라이브러리도 가져다 쓰는경우가 많으니깐.. ) 항상 그것을 지킨다고 보장 할 수가 없을것 같습니다.

좋은 해결책이 없을까 궁금합니다.

그리고, g++/x86 에서

int main()
{
	char* ab = ( char* )malloc( 3 );
	delete ab;
}

위의 코드를 돌린 결과 segment fault같은 것은 나지 않았습니다만,
구체적으로 어떤 위험을 유발 시킬 수 있는지 궁금합니다.

doldori의 이미지

C++ 표준에 의하면 malloc으로 할당한 메모리를 delete로 해제하는 결과를
'정의되지 않음(undefined)'로 규정합니다. 그 뜻은 프로그래머의 의도대로
될 수도 있고 그렇지 않을 수도 있다는 것입니다. 그래서 더욱 위험합니다.
항상 에러를 낸다면 개발 과정에서 충분히 고칠 수 있지만, 정의되지 않은
결과를 유발하는 코드를 작성했을 경우 개발과 테스트에서 잡지 못한 버그가
배포 후에 나타날 수도 있기 때문입니다. 일종의 시한폭탄이죠.

잘 아시겠지만 new/delete는 생성자와 소멸자를 호출하지만 malloc/free는
그렇지 않습니다. built-in type에서는 차이가 없어 보일 수도 있으나 클래스
형이라면 크게 달라지죠. 만약 malloc과 delete를 섞어 썼는데도 아무런
이상이 없었다면 그냥 운이 좋았다고 생각하십시오.

djstop의 이미지

질문하신 것과는 다른 것입니다만,

main 함수의 abc는 메모리가 할당된 곳을
가리키고 있지 않고, 쓰레기값을 가지고 있습니다.
아래와 같이 수정하셔야 됩니다.

char *GetBuf(void) 
{
    char *buf;

    buf = (char *)malloc(30);
    return buf;
}

int main(void)
{
    char *abc = 0;

    abc = GetBuf();

   /* Do anything */
    ........
    ........
}    

그리고,
delete 대신 free를 쓰면 Segmention fault가 나지 않을까요?
doogle의 이미지

완전한 해법은 아니지만 그런 식의 상황이 나타나지 않도록 피해가는 것도
요령이지요. ^^;;

위와같이 메모리를 기본적인 C/C++ 함수를 사용하지 않고
자체 함수로 생성한경우 삭제할 때도 그 역할을 해줄 자체 함수를 짝으로
만들어서 항상 같이 다녀야 합니다.

생성자가 있으면 당연히 그에 걸맞는 소멸자가 있어야 겠지요
C라고 해서 예외는 아닙니다.
저는 항상 C로 코딩할때 님의 샘플코드처럼 자체 함수에서 메모리를 잡고
합니다만.. 이때 해제할 함수도 만들어서 같이 짝을 이루도록 한답니다.
거의 C++의 객체와 비슷합니다. 뭐 제 개인적인 습관이긴합니다만..

ex)

 TWindow* window= NULL; 
 //CREATE 
 TWindow_Create(window); 

 //TODO... 
 TWindow_DoIt(window, ...); 

 //DESTROY 
 TWindow_Destroy(window);
 window= NULL;
 

(흐흐... 왠지 델파이냄새가 나지 않으세요 ^^;; )

bugiii의 이미지

저는 라이브러리용 클래스외에는 생으로 new 을 쓰시는 건 어떻게 하든 피하자는 주의입니다.

그리고, new 한 것을 돌려줘야 하는 경우 doogle님의 의견처럼 핸들 개념으로 바깥에서는 보이지 않게 해주는 것도 좋을 것입니다.

하나 더 있다면 auto_ptr 을 리턴값으로 사용하는 것이 있겠습니다. 새로운 auto_ptr도 꽤 유용하게 사용할 수 있었습니다.

new/delete, malloc/free 의 가장 큰 차이점은 할당하는 객체가 클래스라면 new/delete 는 생성자와 소멸자를 호출한다는 것입니다. 일반 구조체나 배열정도라면 new/delete 구현이 malloc/free를 사용하는 경우도 있어서 호환되는 것처럼 보이지만, 그렇게 사용하면 안되겠죠.

ddoman의 이미지

djstop wrote:
질문하신 것과는 다른 것입니다만,

main 함수의 abc는 메모리가 할당된 곳을
가리키고 있지 않고, 쓰레기값을 가지고 있습니다.
아래와 같이 수정하셔야 됩니다.

char *GetBuf(void) 
{
    char *buf;

    buf = (char *)malloc(30);
    return buf;
}

int main(void)
{
    char *abc = 0;

    abc = GetBuf();

   /* Do anything */
    ........
    ........
}    

그리고,
delete 대신 free를 쓰면 Segmention fault가 나지 않을까요?

생각해보니, 말도 안되는 코드를 써놨군요... :)
지적해주셔서 감사합니다.

그리고 segment fault는 linux-2.6, gcc, x86 에서는 에러가 안나는군요.
물론 new로 char를 생성했을 경우입니다.
class를 그렇게 했을 때는 구현에 따라 segment fault가 나지 않을까 싶습니다.

대부분의 c++용 class들은 각 소멸자에서 처리를 하거나, destroy_abc()
같은 함수들을 제공하는것 같습니다만,

C스타일의...예를들면 strdup같은 함수형식을 가지는 함수인 경우
bugill님 처럼 class가 아닌이상 new,delete를 쓰지 않는 쪽으로 가야하는게
그나마 나아보이긴 합니다만...생각좀해봐야겠네요..

whyseeme의 이미지

usb application을 만들면서 pc tool과 리눅스 드라이버를 함께 만들다 보니까..

pc상에서는 VC++로 타겟 보드에서는 C로 짜니까..

pc tool에서 new로 만들고.. free로 해제하는 짓을 많이 해버렸습니다.

아무 생각이 없었지 뭡니까.. -_-;;

근질 근질~~

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.