메모리 힙영역 질문입니다.

angak의 이미지

heap영역이 어떻게 작동하는지 잘 몰라서요. 보통 메모리 동적할당이 이루어지면 heap영역에 쌓인다고들 하는데... 명확하게 설명해주실 수 있나요,?

하나더 ..동적할당이 3번일어나고 2번째 할당해준것을 해제해주면 어떻게 되는건가요?????????

kukyakya의 이미지

보통은 링크드 리스트나 RB트리로 메모리를 관리합니다.

http://g.oswego.edu/dl/html/malloc.html 를 참고하세요.

ifree의 이미지

힙 영역은 컴퓨터 내의 비어 있는 임의의 메모리 영역이 될 수 있습니다. 스택 영역이 프로그램 시작 시에 정해짐에 반해, 힙 영역은 런 타임에 프로그램이 OS에 요청하여 할당됩니다. 힙 영역은 할당 시마다 반드시 연속되어 할당되는 것이 아니기 때문에 할당 순서에 상관없이 해제할 수 있습니다.

dltkddyd의 이미지

프로그램 실행시 메모리가 할당되는 것을 동적할당이라고 합니다. 그리고 이 때 사용되는 메모리를 개념적으로 heap이라고 하는 것이고요. 그리고 동적할당된 메모리가 3개라면 그 3개를 모두 해제해주어야 합니다. 만약 하나라도 덜 해제해준다면, 메모리 누수라 하여 메모리가 회수되지 않을 경우가 생깁니다. 운영체제에 따라서는 자동으로 해제되기도 하는데, 운영체제가 해제해주기를 바라고 동적할당된 메모리를 해제해주지 않는 프로그램은 그 메모리의 회수가 운영체제에 종속적이기 때문에 좋은 프로그램이라고 할 수 없죠. 만약 운영체제가 메모리를 회수하지 않는 경우가 생긴다면, 정말로 메모리 누수가 발생하게 됩니다. 메모리 누수라 함은 메모리가 회수되지 않는 것을 의미합니다. 즉 메모리를 제대로 회수하지 않는 프로그램은 플랫폼에 종속적인 프로그램이 돼버립니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

DarkSide의 이미지

본인이 무슨 말을 하는지나 알고 글을 쓰시는지 모르겠군요.
메모리 회수 여부와 플랫폼 종속 여부는 아무 관계가 없어요.
또, 프로그램이 종료하면 대부분의 메모리가 회수됩니다만,
실행 시에 OS가 메모리를 회수하는 경우는 없습니다.

dltkddyd의 이미지

오타군요. 해제를 회수로 정정해야겠습니다. 그런데 실행시 OS가 회수한다고 한 적은 없습니다. 그 부분은 잘 못 이해하신 것 같습니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

익명 사용자의 이미지

it's irrelevant.

익명 사용자의 이미지

Quote:
프로그램 실행시 메모리가 할당되는 것을 동적할당이라고 합니다. 그리고 이 때 사용되는 메모리를 개념적으로 heap이라고 하는 것이고요. 그리고 동적할당된 메모리가 3개라면 그 3개를 모두 해제해주어야 합니다.

맞습니다. heap이 뭔지 아는 말은 아니지만.

Quote:
만약 하나라도 덜 해제해준다면, 메모리 누수라 하여 메모리가 회수되지 않을 경우가 생깁니다.

(프로그램의 버그 등으로) 메모리가 회수되지 않는 현상 그 자체를 메모리 누수라 합니다.

Quote:
운영체제에 따라서는 자동으로 해제되기도 하는데,

리눅스, 윈도우 등의 통상적 운영체제들은 프로세스가 종료할 때 해당 프로세스가 사용하던 메모리 공간 전체를 회수합니다. 그러나 이 "회수"와, 프로그램이 제가 가진 힙에서 동적으로 할당한 메모리를 "회수"하는 것은 글자만 같을 뿐 전혀 다른 것을 의미합니다. 추상적 층위에서 추론하지 마세요. 즉 상상하지 마세요. 그건 학습과 practice를 대신한 게으름일 뿐입니다. 그 상상의 결과를 질문과 관계없는 답으로 다는 행동은 어떻게 보아도 좋게 볼 수 없군요.

Quote:
운영체제가 해제해주기를 바라고 동적할당된 메모리를 해제해주지 않는 프로그램은 그 메모리의 회수가 운영체제에 종속적이기 때문에 좋은 프로그램이라고 할 수 없죠. 만약 운영체제가 메모리를 회수하지 않는 경우가 생긴다면, 정말로 메모리 누수가 발생하게 됩니다. 즉 메모리를 제대로 회수하지 않는 프로그램은 플랫폼에 종속적인 프로그램이 돼버립니다.

상상 위에 쌓아 올린 허구입니다.

dltkddyd의 이미지

Quote(니 말)>
프로그램이 제가 가진 힙에서 동적으로 할당한 메모리를 "회수"

해제가 안 된 메모리가 다른 프로그램에서도 사용할 수 없는 상태가 돼버린 겁니다. 그런데 이것을 또 회수라고 말씀하시면 안되죠. 완전히 무개념이군요. OS는 회수. 그런데 프로그램이 회수? 잘 생각해보시길 바래.

종속적이라는 말에 대해 이해가 충분하지 않군요. 어떤 변수에 따라 그 결과가 변동될 경우를 종속적이라고 하는 것입니다. 먼저 종속이라는 것에 대한 사전적인 이해가 필요하겠군요. 국어공부를 도대체 어떻게 하셨길래 저런 개념을 모르나.

프로그램 공부하기 전에 국어 공부를 더 하셔야 겠어요. ㅋㅋ.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

익명 사용자의 이미지

자기 공부 덜 된 걸 남 탓 해봐야 소용없어요.

dltkddyd의 이미지

아직도 종속이 뭔지 개념이 안 잡히나. x라는 변인에 의해 변하는 y를 종속적이라고 합니다. 소멸자 처리를 하지 않았을 때 플랫폼에 따라 메모리 누수가 생길 수도 있고 아닐 수도 있으니 플랫폼이라는 변인에 따라 메모리 누수라는 변인은 종속적이라고 할 수 있습니다. 그래서 종속이라 할 수 있다. 좀 종속에 대한 개념이 뭔지 공부를 하시라니까. 그리고 저 포인터 접근에 대한 것은 님이 아는 이상으로 나도 압니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

익명 사용자의 이미지

아닙니다. 리눅스, 윈도우 같은 현대적인 OS에서는 한 프로그램에서 메모리릭이 발생해도 그게 곧바로 다른 프로그램의 메모리 가용 여부에 영향을 주지는 않습니다. 주소 공간이 다르기 때문입니다. 그래서 virtual address죠 ㅎㅎ

음...

실력이 부족해도 악으로 도전해오는 사람을 제가 많이 좋아하는데요, 이제 님과는 꺼려지네요 ㅎㅎ. 세 가지 이유입니다.

첫번째, 제 짐작이긴 하나 님은 이미 한 번 제가 도발하는 말에 정말로 상처 받았습니다. 더 이상은 서로 위험하고요.

둘째, 제가 님께 달아드린 gdb 답변 중에 틀린 게 하나 있습니다. 달고 나서도 긴가 민가 해서 확인했더니 틀려서 아차 싶었는데, 님 성격에 그냥 이죽대기만 하고 넘어가시더군요. 찾아보지도 않았다는 거죠.

셋째, 저는 님이 "잠시 착각"하신 걸 세 번 지적했습니다.

첫번째는 님께 하는 말도 아닌 제 말에 뜬금없는 반말로 달려드셨는데, 뭐 상황 상 그럴 수 있다 생각하고 또 저도 그걸 핑계로 거칠게 잘 놀았으니 됐습니다.

두번째는 서로 좋게 이야기 되었죠.

세번째는 인정 안하고 도망가셨죠. 음.. 여전히 상황 파악이 안되었을 수도 있겠으나 님의 마지막 댓글로 보건대 그건 아니라고 판단합니다 ㅎㅎ

인터넷으로 토론하다 혹은 감정싸움하다 도망가는 거 비일비재하고 또 그게 뭐 대수도 아닙니다만.. 글쎄 ㅎㅎ 무척 실망스러웠습니다.

제 판단이.

dltkddyd의 이미지

익명 뒤에 숨어서 함부로 말하기 때문이죠라고 그쪽이 말씀했지만, 그렇지 않아요. 님이 남을 무시하는 어조로 말씀하셨지. 본인이 한 일을 기억못하는 까마귀이시군요.

님 의 quote> 첫번째, 제 짐작이긴 하나 님은 이미 한 번 제가 도발하는 말에 정말로 상처 받았습니다. 더 이상은 서로 위험하고요.

라고 말씀하셨는데. 천만에요. 상처 전혀 안 받았습니다. 님은 답변 달지 말라는 말에도 계속 답변만 달더군요. 님은 타자(나)에게 인정받고 싶은거에요. 그게 당신의 문제입니다. 싫으면 그냥 답변 달지 않으면 돼요. 당신한테 답변 달아달란 말 하지 않았으니. 본인이 상처 받아놓고 자신이 받은 상처 받은만큼 상대방이 상처받았으면 하는 너의 마음 상태가 문제인거에요. 아셨죠?

님의 quote> 둘째, 제가 님께 달아드린 gdb 답변 중에 틀린 게 하나 있습니다. 달고 나서도 긴가 민가 해서 확인했더니 틀려서 아차 싶었는데, 님 성격에 그냥 이죽대기만 하고 넘어가시더군요. 찾아보지도 않았다는 거죠.

마치 본인의 실수가 남의 실수인양 몰아붙이고 있죠? 그게 당신의 문제입니다. 님의 실수는 너의 실수로 끝나야죠. 그게 내 실수는 아니죠. 그리고 이죽대기 누가 이죽댑니까? 당신이 깐죽댄 적은 있어도.

님의 quote> 셋째, 저는 님이 "잠시 착각"하신 걸 세 번 지적했습니다.

님이 세 번 지적했는지 알 거 없어요. 님 같은 사람한테 물어본 것도 아닌데. 그리고 익명이 어디 한 둘인가? 님이 몇 번 지적한 것을 내가 기억할 수도 없을 뿐더러 기억할 필요도 없습니다.

여하튼 님의 문제를 남한테 떠넘기지 마세요. 사회에서 깨지기 쉬운 유형입니다. 가차없이 떼거리로 말입니다.

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

익명 사용자의 이미지

네, 맞습니다. 구체적으로 들어가지 못해 문제인 사람에게 벽만 더 높이는 이에게 한마디 했다가, 첨엔 뭐 이런 게 다 있지? 싶었지만, 뭐 옛날 생각도 나고 ㅎㅎ 역시 내 방식이 맞다는 걸 확인해보고 싶었습니다. 좀 더 나아가보지 못한 건 아쉽지만, 이 정도로 만족합니다.

익명 사용자의 이미지

기우였던 건 다행이네요 ㅎㅎ

ㅅㅂ 더러워서 못 보겠네의 이미지

상대가 잘 모르는 것 같으면 친절히 알려 줄 생각을 해야지 시발 모른다고 무시하는것도 아니고 뭐 하는 놈들이야...

니들보다 더 뛰어나고 잘난 사람도 많다.

친절해라. 제발.

익명 사용자의 이미지

님이 상상의 결과를 사실인 양 써대는 한 님은 kldp에서 개무시 당할 겁니다, 님이 누구건.
성실하게 공부하는 학생의 자세를 보이는 한 존중받을 겁니다, 님이 누구건.

HDNua의 이미지

http://kldp.org/node/142690
위 링크는 제가 나름대로 힙 메모리 영역을 구현한 것입니다.
(자료구조상의 힙이 아니라는 것은 인정합니다.)
처음에는 이걸 참고로 하면 힙을 이해하는 데 도움을 드릴 수 있을 것 같다는 생각을 했지만,
덧글들을 보니 문득 저도 제 맘대로 상상한 결과를 진짜라고 말해버릴 수 있겠다는 생각을 했습니다.

답변이 아니지만, 이걸 가지고 얘기를 나눠보면 저처럼 잘 모르는 사람들이 더 올바르게 힙을 이해할 수 있지 않을까 합니다.

저는 이렇게 생각했습니다.

익명 사용자의 이미지

doc 파일 열어만 보고 코드 분석은 안했습니다.

원 글에서 어떤 분이 이미 잘 말씀해주셨듯, 메모리 관리자로서의 힙을 구현하셨다면 (별다른 버그가 없는 한) 그냥 제 기능을 잘 수행하는 힙이고, 아무 문제 없겠죠.

자료구조 상의 힙은 아니지만 이런 식의 구현은 어떨까라고 한다면, 코드 작성자로서 의사 코드와 그림 좀 그려서 발제해주시면 이야기 나누기 쉽지 않을까 합니다.

군 복무 중이신 것 같은데, 공부 열심히 하시네요.

HDNua의 이미지

코드 양이 길지 않아서 괜찮지 않을까 했는데 잘못 생각했습니다. 그림은 지금 좀 어려워서 어떻게 프로그램이 돌아가는지만 표현해봤습니다.

1. 시뮬레이션

void *hd_alloc(size_t size);	// malloc
void hd_free(void *ptr);	// free
char *hd_get_start_of_memory();	// 메모리의 시작 지점을 얻습니다.
char *hd_get_end_of_memory();	// 메모리의 끝 지점을 얻습니다.
char mem[32] = {0};
 
> <Program Start>	// mem의 모든 원소는 0으로 초기화되어있습니다.
> int size = 0;
mem[34]   | ____ ____ ____ ____ ____ ____ ____ ____ __
hptr      | 0
size      | 0
 
> char *mem1 = (char *)hd_alloc(2); size = *(int *)(mem1 - sizeof(int));
mem[34]   | 0006 ____ ____ ____ ____ ____ ____ ____ __
hptr      | 0 + (4+2) = 6
size      | 6
<retVal>  | mem+4
mem1      | mem+4
 
> char *mem2 = (char *)hd_alloc(8); size = *(int *)(mem2 - sizeof(int));
mem[34]   | 0006 __00 12__ ____ ____ ____ ____ ____ __
hptr      | 6 + (4+8) = 18
size      | 12
<retVal>  | mem+10
mem1      | mem+4
mem2      | mem+10
 
> char *mem3 = (char *)hd_alloc(sizeof(int)); size = *(int *)(mem3 - sizeof(int));
mem[34]   | 0006 __00 12__ ____ __00 08__ ____ ____ __
hptr      | 18 + (4+4) = 26
size      | 8
<retVal>  | mem+22
mem1      | mem+4
mem2      | mem+10
mem3      | mem+22
 
> hd_free(mem2); size = *(int *)(mem2 - sizeof(int));
mem[34]   | 0006 __-0 12__ ____ __00 08__ ____ ____ __
hptr      | 26
size      | -12
<retVal>  | 
mem1      | mem+4
mem2      | mem+10
mem3      | mem+22
 
> char *mem4 = (char *)hd_alloc(3); size = *(int *)(mem4 - sizeof(int));
mem[34]   | 0006 __-0 12__ _000 1_00 08__ __00 07__ __
hptr      | 26 + (4+3) = 33
size      | 7
<retVal>  | mem+30
mem1      | mem+4
mem2      | mem+10
mem3      | mem+22
mem4      | mem+30
 
> char *mem5 = (char *)hd_alloc(4); size = *(int *)(mem5 - sizeof(int));
> // 이후에 할당할 공간이 부족하므로 처음 위치부터 추적 시작
mem[34]   | 0006 __00 08__ _000 1_00 08__ __00 07__ __
hptr      | 6 + 4 = 10
size      | 8
<retVal>  | mem+10
mem1      | mem+4
mem2      | mem+10
mem3      | mem+22
mem4      | mem+30
mem5      | mem+10

2. free

void hd_free(void *ptr) {
    char *mp = (char *)ptr - sizeof(int);  // 포인터가 가리키는 위치 이전에 할당한 메모리의 크기를 기록합니다.
    int offset = *(int *)mp;               // 다음 메모리까지의 위치를 저장하는 값이라 이름을 offset으로 했습니다. (offset == memory_size + sizeof(int))
    if (offset > 0)                        // 메모리가 할당되어있다면
        *(int *)mp = -offset;              // offset 값을 음수로 바꿔 할당을 해제한 것처럼 만듭니다.
}

3. alloc

void *hd_alloc(size_t size) {
    static char *hptr = hd_get_start_of_memory();
    size_t space = size + 2*sizeof(int);
    int offset;
    const char *end_of_memory = hd_get_end_of_memory();
    if (hptr + size >= end_of_memory) {
        hptr = hd_get_start_of_memory();
    }
    for (; hptr + size < end_of_memory; hptr += offset) {
        offset = *(int *)hptr;
        if (offset == 0) {
            offset = (int)size + sizeof(int);
            *(int *)hptr = offset;
            hptr += offset;
            return hptr - size;
        } else if (offset < 0                   // deallocated memory
                   && space <= -offset) {       // and enough space
            char *next_hptr = hptr - offset;
            offset = (int)size + sizeof(int);
            *(int *)hptr = offset;
            hptr += offset;
            *(int *)hptr = (int)(next_hptr - hptr);
            return hptr - size;
        }
    }
    return NULL;
}

4. 결과

mem1 = alloc(2)
[[   ][    ][    ][    ][   X][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ]]
[[   6][   0][   0][   0][  88][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0]]
mem2 = alloc(8)
[[   ][    ][    ][    ][   X][    ][   A][    ][    ][    ][   t][   e][   s][   t][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ][    ]]
[[   6][   0][   0][   0][  88][   0][  12][   0][   0][   0][ 116][ 101][ 115][ 116][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0][   0]]
mem3 = alloc(sizeof(int))
[[   ][    ][    ][    ][   X][    ][   A][    ][    ][    ][   t][   e][   s][   t][    ][    ][    ][    ][   ][    ][    ][    ][   @][   0][    ][   ][    ][    ][    ][    ][    ][    ][    ][    ]]
[[   6][   0][   0][   0][  88][   0][  12][   0][   0][   0][ 116][ 101][ 115][ 116][   0][   0][   0][   0][   8][   0][   0][   0][  64][  48][  32][  16][   0][   0][   0][   0][   0][   0][   0][   0]]
free(mem2)
[[   ][    ][    ][    ][   X][    ][   A][   A][   A][   A][   t][   e][   s][   t][    ][    ][    ][    ][   ][    ][    ][    ][   @][   0][    ][   ][    ][    ][    ][    ][    ][    ][    ][    ]]
[[   6][   0][   0][   0][  88][   0][ -12][  -1][  -1][  -1][ 116][ 101][ 115][ 116][   0][   0][   0][   0][   8][   0][   0][   0][  64][  48][  32][  16][   0][   0][   0][   0][   0][   0][   0][   0]]
mem4 = alloc(3)
[[   ][    ][    ][    ][   X][    ][   A][   A][   A][   A][   t][   e][   s][   t][    ][    ][    ][    ][   ][    ][    ][    ][   @][   0][    ][   ][   ][    ][    ][    ][   H][   I][    ][    ]]
[[   6][   0][   0][   0][  88][   0][ -12][  -1][  -1][  -1][ 116][ 101][ 115][ 116][   0][   0][   0][   0][   8][   0][   0][   0][  64][  48][  32][  16][   7][   0][   0][   0][  72][  73][   0][   0]]
mem5 = alloc(4)
[[   ][    ][    ][    ][   X][    ][   ][    ][    ][    ][   B][   Y][   E][    ][   ][    ][    ][    ][   ][    ][    ][    ][   @][   0][    ][   ][   ][    ][    ][    ][   H][   I][    ][    ]]
[[   6][   0][   0][   0][  88][   0][   8][   0][   0][   0][  66][  89][  69][   0][   4][   0][   0][   0][   8][   0][   0][   0][  64][  48][  32][  16][   7][   0][   0][   0][  72][  73][   0][   0]]

이상입니다.

저는 이렇게 생각했습니다.

dltkddyd의 이미지

혹시 Effective C++읽으라고 권하셨던 분 아니신가요?

본인 맞습니다.
인증샷
우헤헤헤... 로 대신합니다.

HDNua의 이미지

그렇습니다.

저는 이렇게 생각했습니다.

익명 사용자의 이미지

HDNua의 이미지

어떤 분을 위한 링크인가요? 여기에 제가 Effective C++를 읽으라고는 하지 않았으니 저는 아닐 것 같은데.

저는 이렇게 생각했습니다.

kaeri17의 이미지

기본적으로 운영체제 책에 힙 영역 구현이 나와 있습니다. 힙영역 자체는 일정한 메모리 영역에 불과합니다. 기본적으로 정확한 이해를 위해서는 메모리 계층구조에 대한 이해가 선행해야 하나, 간단하게만 설명해 드리겠습니다. 일단 user레벨(사용자의 프로그램)에서 malloc이나 new같은걸로 메모리 요청을 하면, 운영체제는 메모리 블록(4kb정도 단위)를 그 프로그램에 할당합니다. 그리고 그 영역중에 프로그램이 요청한 크기에 맞는 메모리 주소를 돌려줍니다. 그러면 다음번 요청에는 메모리 블록에 아직 사용가능한 영역이 좀 남았다면, 그 부분에서 할당해주고, 부족하다면 메모리 블록을 계속 늘려서 할당합니다. 그리고 이건 가상메모리상의 개념이기 때문에 실제로 하드웨어적인 메모리에 올라가는것이랑은 별 상관이 없습니다. 이런 방식때문에 메모리를 큰 객체와 작은 객체에 번갈아서 할당하게 되면, 프로그램에 사용한 메모리보다 최대 2배에 달하는 메모리가 할당됩니다.
여기서 운영체제는 메모리 블락 내부에 다음번에 할당할 메모리 영역을 계속해서 추적해야 합니다. 대부분의 운영체제는 linked list로 이 구조를 유지합니다. 이때 메모리 요청이 들어오면, list를 따라가면서 현재 요청된 크기의 메모리가 남아있는 블록까지 가서 그 주소를 돌려주고, 없다면 새로운 메모리 블록을 할당하는 겁니다.
메모리 블록 할당은 기본적으로 가상메모리의 기본적인 단위자, 실제 하드웨어 메모리와 cpu 캐쉬에 들어가는 기본단위기 때문에, 실제 하드웨어에 매핑되는 정보도 있어야 할겁니다. 이걸 프로세스의 page table에 기록해 둡니다. 그리고 캐쉬영역에 관한 정보를 CPU의 TLB에 기록합니다.

더욱 자세한 내용에 대해서는 OS책에 대부분 잘 설명되어 있고요, pintos manual과 소스를 보면, 어느정도 운영체제의 메모리 할당의 기본적인 구현에 대해서 보실 수 있습니다.

HDNua의 이미지

운영체제를 공부하려고 Operating System Concepts를 샀는데 이 책을 보면 될 것 같네요.
소중한 답변 감사합니다.

저는 이렇게 생각했습니다.

jick의 이미지

쓰신 이야기에서 OS와 라이브러리의 역할 분담에 대해 약간 오해의 소지가 있어서...

Linux 같은 일반적인 운영체제를 기준으로 얘기하자면, malloc이나 new 같은 메모리 요청은 운영체제가 아니라 런타임 라이브러리에서 (Linux라면 glibc, libstdc++ 등등) 처리합니다. 여기서 기존에 할당받은 메모리 페이지 중 빈 공간이 있나 찾아보고, 있으면 그 부분을 할당해서 caller에게 돌려주고, 없을 때만 system call을 불러서 운영체제에 추가 메모리를 요청하게 됩니다.

따라서 운영체제는 이 프로그램이 어떤 메모리 주소를 사용중인지 페이지 단위로만 (일반적으로 4K) 정보를 갖고 있으며, 각각의 4K 중에서 어떤 부분이 현재 malloc/new 등으로 사용중인 부분이고 어디가 free된 부분인지는 런타임 라이브러리가 관리하는 부분이고 운영체제는 전혀 신경쓰지 않습니다.

그러니까 위의 글에서
> 이때 메모리 요청이 들어오면, list를 따라가면서 현재 요청된 크기의 메모리가 남아있는 블록까지 가서 그 주소를 돌려주고, ...
이 부분은 OS의 역할이 아닙니다. 기존의 페이지에 충분한 공간이 없어서 새로운 페이지를 할당하는 경우에만 OS가 불리게 됩니다.

이렇게 하는 주된 이유는 malloc이나 new는 굉장히 자주 불리기 때문에 그때마다 운영체제를 부르면 성능이 심각히 저하되기 때문입니다.

HDNua의 이미지

1. 동적 할당이 세 번 일어나고 두 번째 것이 해제된다면.
당연히 p1, p3는 남아있고 p2는 해제됩니다. 다만 free 함수의 원형은 void free(void *p)로 인자로 넘긴 포인터 변수 자체의 값을 바꾸는 용도로 사용하지는 않습니다.
이 경우 p2를 인자로 넘긴다고 p2의 값(p2가 가리키는 값을 말하는 게 아닙니다)이 바뀌는 것은 아닙니다. call by value인데 당연하지요?

2. 아래는 사견입니다.
저는 예전에 힙에서 메모리를 해제하면 이전에 할당되었던 메모리를 당기던지 해서 빈 공간을 없앨 것이라 생각했는데,
메모리를 해제한다고 이전에 할당된 메모리를 옮겨버리면 이미 할당된 메모리를 가리키는 변수들은 쓰레기 값을 가리키게 됩니다.
(free 함수에 이전에 할당된 메모리를 가리키는 변수의 주솟값을 전달한다면 모를까..)

결론은 메모리를 해제한다고 이전에 할당된 메모리를 옮기지는 않는다는 뜻입니다. 위에 올린 '제가 만든 Heap'은 이러한 점을 고려해서
메모리 해제는 메모리 해제대로 수행하고, 할당은 hptr이라는 정적 변수를 통해 수행하고 있습니다.
이후에 메모리가 가득 차면 처음부터 탐색해서 빈 공간이 있을 때 할당하려는 것이죠.

이상입니다. 사견이라고 한 건 실제 Heap이 이렇게 동작한다는 문서를 본 적이 없고 제가 생각해낸 것이기 때문입니다.

ps. code 태그를 이용해 코드를 올리면 그 다음 문단부터 글이 자꾸 깨지는데 저만 이런가요?
IE 8, FIrefox 10, 30에서 모두 이렇습니다. 입력 형식을 바꿔봐도 계속 그러네요.
원래 참고용 코드를 작성했다가 글이 자꾸 깨지는 바람에 관뒀습니다.

저는 이렇게 생각했습니다.

댓글 달기

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