[완료]c 동적 할당 관련 질문입니다..

goguma의 이미지

바보같은 질문은 없다고들 하시지만...
제가 바보같은 질문을 하게 되는것 같습니다..ㅋ

c 언어에서 포인터 변수 선언시..
void *ptr; 이런식으로 하지 않고 앞에 타입을 적어주는 이유는..
그 포인터 변수를 이용하여 메모리에 접근시..
그 포인터 변수가 가리키는 타입의 크기 만큼만
메모리에서 읽기/쓰기등을 하기 위해서라 알고 있습니다.
그래서.. 동적 할당을 하여 메모리 사용 후, 그 메모리를 해제 할때도..
그 포인터 타입의 크기만큼만 OS에 반환한다고 생각하고 있었습니다..
그런데 문제가 여기서 발생합니다..ㅡㅡ
코드 중 일부 입니다..

--------------------------------------------------
#define SIZE 5

int *board = (int*)malloc(sizeof(int) * SIZE);

free( (void)board );
--------------------------------------------------

제가 board라는 포인터를 이용해서 int타입의 데이터를 처리해야 하는데..
마지막에 할당 해제시 동적할당된 메모리, 즉 4*SIZE 바이트가 모두 해지가 되나요?
아니면.. 메모리 누수현상이.... 발생하나요?
그리고.. 만약 동적할당된 메모리가 모두 해지가 된다면, 메모리에 동적할당 시작 부분과
끝부분을 가리키는 무엇인가가 있는지도 알려주시면 감사하겠습니다..^^
바보같은 질문이지만... 답변 부탁드립니다..ㅎㅎ

익명 사용자의 이미지

free()의 함수 선언을 생각해 보신다면 금방 답이 나왔을텐데...

void free(void * ptr);

어차피 free함수로 넘어가는 과정에서 void *형으로 형변환이 이루어지기 때문에 ptr의 타입은 상관이 없습니다.
즉, 타입이 뭐가 되었건 주소값만 올바르다면 제대로 잘 작동합니다.

하지만 C++에서는 다중상속 덕분에 아닐 수도 있습니다.

struct A { };
struct B { };

struct C : public A, public B { };

C * pc = new C;
B * pb = pc;

pb는 pc와 주소값이 다르기 때문에, delete pb를 했다간 당장에 문제가 발생합니다.

간단하게 요약하자면,
C의 malloc/free는 어차피 void * 형 포인터를 사용하기 때문에
주소값만 올바르다면 제대로 된 동작이 이루어집니다.

하지만 C++의 new/delete는 타입 또한 엄격하게 지켜져야 합니다.

Testors의 이미지

delete pb 가 왜 문제가 생기나요?

twinwings의 이미지

"pb는 pc와 주소값이 다르기 때문에, delete pb를 했다간 당장에 문제가 발생합니다."

의 표현은 틀린 것 같지만,
(엄밀히 말하면 C++ 컴파일러에 따라서 up-casting 시 주소가 바뀌는 경우가 있긴 있습니다.)

일반적으로는

상속시킬때는 소멸자를 반드시 가상함수로 선언해야 하기 때문에 틀렸습니다.

#include <string>
#include <iostream>
 
class _Logger
{
public:
    _Logger(std::string f) :m_f(f)
    {
        std::cout << m_f << "() has been called" << std::endl;
    }
    ~_Logger()
    {
        std::cout << m_f << "() has been ended" << std::endl << std::endl;
    }
private:
 
    std::string m_f;
};
 
#define LOGGER  _Logger __logger(__FUNCTION__)
 
class A
{
public:
    ~A()
    {
        LOGGER;
    }
};
 
class B
{
public:
    ~B()
    {
        LOGGER;
    }
};
 
class C: public A, public B
{
public:
    ~C()
    {
        LOGGER;
    }
};
 
void test1()
{
    LOGGER;
 
    C *c = new C;
 
    delete c;
 
    return;
}
 
void test2()
{
    LOGGER;
 
    C *c = new C;
    A *a = c;
 
    delete a;
 
    return;
}
 
int main()
{
    test1();
    test2();
 
    return 0;
}
dingkyu의 이미지

메모리 영역이 아니라 프로그래밍할때 원하는 양만큼 확보하고 확보가 됬으면
그 확보한 메모리의 시작번지만을 반환할뿐입니다.

그리고 free라는 명령어는 결과적으로는 처음 malloc의 결과로 다른 프로세스가
건드리지 못하도록 한것을 다른 프로세스가 건드릴 수 있도록 반환하는
명령입니다. 따라서 free를 안하면 그 프로세스는 죽었음에도 불구하고
계속 다른 프로세스가 건드리지 못하도록 함으로 활용할 수 있는 메모리가
점점 줄어드는 것이구요. (그게 누수 죠)

해제를 했다고 해서 메모리에 직접적인 변화가 일어나기보단
접근권한이 바뀌었다고 생각하면 맞을껍니다.

고민이 많아 고민인 애늙은이 입니다.

sunyzero의 이미지

프로세스를 종료하면 free()와는 상관없이 메모리는 해제됩니다.
메모리누수(memory leak)은 프로세스가 살아있는데, 메모리를 free()하지 않고
계속해서 할당하는 경우를 말합니다.

보호모드에서 작동하는 모든 OS에서는 프로세스가 종료되면 모든 자원은 반환됩니다.
그렇지 않은 경우는 OS의 버그입니다.
========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

goguma의 이미지

간단한 코드 작성시..
free() 다음에 바로 프로그램이 종료한다면..
굳이 free()를 할 필요는 없다고 봐도 되는 건가요?
free()는 프로그램 상에서 메모리를 할당한 후 그 메모리를 다 사용하고..
계속해서 다른 함수 등에서 메모리를 더 할당받을 시에만 사용해도 된다는 말씀이신지?
--------------------------------
스물셋.. 독립.. 열심히 살아보자!!
--------------------------------

--------------------------------
스물셋.. 독립.. 열심히 살아보자!!
--------------------------------

haze11의 이미지

프로그램 종료시 할당 받은 메모리는 반환되기 때문에 종료 전에 free()를 안해도 되겠지만, 메모리 할당 후 free()를 하여 명확하게 해주는게 좋겠죠.

goguma의 이미지

그럼 굳이 free( (void)board ); 할 필요 없이..
free(board)하면 되겠군요...
두분 모두 감사합니다..^^
덕분에 잘 이해했습니다..ㅋ
--------------------------------
스물셋.. 독립.. 열심히 살아보자!!
--------------------------------

--------------------------------
스물셋.. 독립.. 열심히 살아보자!!
--------------------------------

익명 사용자의 이미지

궁금한게 있는데요 c언어 프로그램을 작성하다보면 막 메모리 번지에 뭐가 들어가고 그러잖아요
그럼 그 프로그램을 종료해도 그 메모리번지에는 제가 저장한 정보가 그대로 있는건가요?

twinwings의 이미지

보통은, 그대로 있습니다.

하지만 A라는 프로그램(프로세스)에서의 100번지 주소와

B라는 프로그램(프로세스)에서의 100번지 주소는 값이 다를 수 있습니다.

Virtual Address Space를 참조하세요.
(* 윈도에서 말하는 가상메모리와는 다른 개념입니다.)

댓글 달기

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