6 minute read

6주차 퀴즈 정리하기 - 당신이 포인터를 쓰며 만나는 오류들

Dangling pointer

포인터가 여전히 해제된 메모리 영역을 가리키고 있을때, 이 포인터를 dangling pointer 라고 한다.

a = 10;
int * ptr = (int*)malloc(sizeof(int));
*ptr = 5;
free(ptr);

*ptr = 10 // error! 결과는 예측할 수 없다!

memory leak

동적으로 할당된 메모리가 free가 될 수 없는 상태가 된 것. 메모리를 할당 해 사용한 뒤 해제를 해주지 않으면 메모리 사용량이 계속 증가하게 되고, 결국 시스템의 메모리가 부족해져 운영체제가 프로그램을 강제로 종료시키거나, 메모리 할당에 실패하기 때문.

char *a = malloc(20);
char *b = malloc(10);

b = a;
free(a);
free(b);//를 하게되면, b가 아니라, b가 가리키고 있던 a 가 메모리 해제 됨.
// 따라서 b는 메모리 할당 해제가 불가능한 상태가 된다.

👾해결방법 메모리 할당 상태를 assert()로 모니터링

uninitialized pointer

초기화 되지 않은 포인터.

문제가 생길수도있고 생기지 않을수도있다(이게 더 위험). 때문에 포인터를 초기화하지 않을거면 NULL로 초기화 하고 사용하는것을 권장한다.

int *p ; // 초기화 되지않으면 무작위로 값이 들어감. 우연히 프로그램에서 중요한 부분을 가리키게 된다면 ?
*p = 123;
printf("%d",n*p);

👾해결방법 : 포인터를 사용할때는 반드시 초기화를 한다. 초기화를 못할경우 NULL로 초기화한다.

explicit, implicit, segregated 에 대하여 다시 공부!

implicit 가용 리스트는 ,

맨앞에 해딩, 그다음에 prologue header, prologue footer, epilogue header로 이루어진 블럭들로 이루어진 구조이다. 가용리스트는 할당 리스트 사이사이에 있을 수도 있고 아닐 수도있다. 정렬에 대한 규칙이 따로 없다. 장점은 간단하고 심플한것, 단점은 힙의 영역이 커질수록, 탐색의 비용이 커진다는 것이다.

explicit 가용리스트는,

기본 구조는 implicit 과 유사하나, 페이로드 안에 다음 가용블록과 이전 가용블록의 포인터를 저장한다는 점에서 차이가 있다. 때문에 가용블록끼리 연결이 되어있기 때문에 가용블록을 탐색하는것이 용이하다. 하지만 prev(predecessor) , next(successor) 각각 1워드씩 총 2워드의 공간을 더 사용하게 된다.

segregated 리스트는,

가용리스트를 무작위로 연결하는게 아니라, 크기별로 class 를 나눠서 각 class 별 Linked 가용 리스트를 만드는 방식이다. 할당하고자 할때 가용 리스트 탐색시 시간이 빠르다는 장점이 있다. 하지만 여러개의 가용 블록 리스트를 관리해야하는 단점이 있다.

블럭 단위로 메모리를 할당하는 이유???

cpu 레지스터의 크기에 따라 한번에 읽고 쓰는 범위가 정해져 있다. 때문에 블록단위로 맞추는것이 연산이나 메모리 관리에 있어 효율적이다.

지난주 퀴즈도 정리해보자 - 5주차 rb tree 퀴즈

//"다음 프로그램에서 string ""abc"", ""def"", ""ghi""는
// 각각 어느 메모리 영역으로 할당되는가?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
  char *s1 = "abc";
  char s2[] = "def";
  char *s3 = (char *) malloc(4);
  strncpy(s3, "ghi", 4);
  printf(""%s %s %s\n"", s1, s2, s3);
  free(s3);
  return 0;
}

// 5번: "abc" - data, "def" - stack, "ghi" - heap

이 문제를 풀기 위해선 data segment 에 대해서 공부할 필요가 있다.

data segment 는 전역변수와 정적변수가 저장되는 메모리 공간이다. 추후 메모리 접근 공간으로 사용 가능하다. 즉 프로그램 런타임에 자유롭게 수정 및 변경이 가능하다.

스크린샷 2023-09-14 21.07.21.png

  • data segment 에는 전역변수 그리고 값을 가지고 있으며, 수정이 가능한 지역변수들이 저장된다.
  • bss(block stated symbol) segment 에는 초기화 되지않은 변수나 상수가 저장된다. 초기화없이 정적으로 할당된 변수는 0 이나 NULL로 초기화 된다. 이런 작업이 여기서 진행된다.
  • heap 에는 동적으로 할당된 메모리가 포함되어있음. bss segment 끝에서 시작하여 커진다. 이 크기를 조정하기 위해 sbrk/brk시스템 호출을 사용할 수 있는 malloc, calloc, realloc ,free 에 의해 관리된다. 런타임에 크기가 결정된다. 힙영역은 동적으로 런타임에 사용자 요구에 맞게 메모리를 할당하기 위한 영역이다.
  • 스택 스택포인터인 register는 스택의 상단을 추적한다. 스택 segment 에는 프로그램이 실행하고있는 동안에 만들어지는 데이터(지역변수, 매개변수)등을 스택처럼 쌓아서 저장하는 세그먼트 영역이다. 스크린샷 2023-09-14 21.28.58.png 🔆stack의 모든 영역이 할당되어 다른 공간을 침범하게 되는경우 = stack overflow 스택영역은 컴파일 타임에 크기가 결졍된다.

6주차 회고

  • 정글에 들어오고나서 제일 힘들었던 주였다. 😇 왜그런지 생각해봤다.
  • CSAPP읽는것에 대한 어려움
  • 책읽는게 어려웠다 . 왜냐? 번역이 좋지 않았다. 어려운 내용이었다..
  • 어떻게 해결할꺼야 ? 책을 보다가 너무 어렵거나 이해가 안되면 블로그나 다른 자료(유튜브)를 참고하자
  • 물론 그 자료에 대한 신빙성을 100프로 라고 볼 순 없겠지만, 어떤 내용이겠거니~ 참고하는것
  • 그래도 모르겠으면 다른사람에게 물어보자. 다만 내가 뭘 모르겠는지 정도는 생각하고 물어봐야 시간 낭비가 적다.
  • 영어로 보되 너무 어려우면 챗지피티로 번역을 돌려서 보자.
  • 챗지피티를 적극 사용!!!!!!
  • 3번을 봤는데도 모르면 넘어가자. 다음 챕터에서 내가 몰랐던 내용이 이해가 될 수도 있다.
  • 하루에 집중할 시간이 정해져있다지만 그래도 내 루틴은 지키자. 챗지피티에게 물어보는 한이 있어도 앉아있기.

소확행

  • 깃헙블로그에 댓글을 다는 기능을 만들었다.
  • utterances 를 이용했는데, 깃헙 아이디와 연동해서 댓글을 달 수 있다. 그리고 댓글을 달 경우 나에게 알림이 오는 점도 좋았다.(github issue로 알림이 온다!)
  • 댓글달 수있는 화면이 딱 생겼을때의 즐거움이란.. 누가 댓글좀 달아줬음 좋겠다(써주세요제발)

Updated:

Leave a comment