WIL/스터디

Red-Black Tree Extra Questions

아크리미츠 2024. 8. 21. 23:43

1. Segmentation Fault (Core dumped)

"Segmentation Fault (Core dumped)"라는 에러 메시지는 프로그램이 허용되지 않은 메모리 영역에 접근하려고 할 때 발생합니다. 이 메시지는 다음과 같은 문제들로 인해 발생할 수 있습니다:

  • 잘못된 포인터 참조 (예: NULL 포인터 참조, 초기화되지 않은 포인터 사용)
  • 배열 범위를 초과한 접근
  • 이미 해제된 메모리 접근
  • 스택 오버플로우

core dumped는 프로세스가 비정상 종료되었을 때, 시스템이 해당 시점의 메모리 상태를 파일로 저장했다는 의미입니다. 이 파일을 사용해 프로그램이 종료된 시점의 상태를 분석할 수 있습니다.

2. Core dumped ?

core 파일은 프로세스가 비정상 종료될 때 메모리의 상태를 덤프한 파일입니다. 일반적으로 현재 작업 디렉토리 또는 시스템이 설정한 특정 디렉토리에 생성됩니다. ulimit 명령어를 통해 core 파일 생성 여부와 위치를 제어할 수 있습니다.

core 파일을 사용하면, 프로그램이 종료된 시점의 상태를 분석할 수 있습니다. 이를 통해 어떤 코드가 문제를 일으켰는지, 어떤 데이터가 잘못되었는지를 조사할 수 있습니다. gdb와 같은 디버거를 사용해 이 파일을 로드하고 분석할 수 있습니다.

3. Valgrind & Gdb

  • Valgrind: 메모리 관리 오류를 감지하는 도구입니다. 프로그램이 메모리 접근을 잘못하거나, 메모리 누수를 일으키는지 등을 체크합니다. 예를 들어, 초기화되지 않은 메모리를 사용하거나, 메모리 누수가 발생하는지 확인할 수 있습니다.
  • Gdb (GNU Debugger): 프로그램을 실행하는 동안 디버깅할 수 있게 해주는 도구입니다. 코드에서 중단점을 설정하고, 변수 값을 조사하며, 함수 호출 스택을 확인하는 등의 작업을 할 수 있습니다. core 파일과 함께 사용해 프로그램의 비정상 종료 원인을 분석하는 데 유용합니다.

4. char *s1 = "abc";와 char *s2 = malloc(4);라는 문장에서 s1과 s2가 저장된 주소, malloc이 return 하는 주소는 어떤 메모리 세그먼트에 할당할까?

  • s1이 저장된 주소: s1은 문자열 리터럴 "abc"를 가리키는 포인터입니다. 이 문자열 리터럴은 보통 프로그램의 데이터 세그먼트(특히 읽기 전용 데이터 영역)에 저장됩니다. 이 메모리 영역은 프로그램이 실행될 때 미리 할당됩니다.
  • s2가 저장된 주소: s2는 malloc에 의해 동적 메모리를 가리키는 포인터입니다. 이 메모리는 힙(Heap) 영역에 할당됩니다. malloc(4)는 4바이트 크기의 메모리를 할당하고, 그 주소를 s2에 저장합니다.
  • malloc이 return 하는 주소: malloc이 반환하는 주소는 힙 영역에 할당된 메모리의 시작 주소입니다.

5. C에서는 return "abc"; 같은 짓을 하면 왜 안될까?

return "abc";는 문자열 리터럴을 반환하는 코드입니다. 이 문자열 리터럴은 전역적으로 유효하므로 호출된 함수가 종료된 후에도 메모리에 남아있습니다. 하지만, 리터럴이 아닌, 예를 들어 함수 내에서 동적으로 할당된 메모리를 반환하거나 지역 변수의 주소를 반환하면, 함수가 종료되면서 해당 메모리가 해제되거나 무효화되므로 위험합니다. 이런 코드들은 쉽게 메모리 오류를 일으킬 수 있습니다.

6. malloc을 해 두고 free를 안 하면 어떻게 될까?

malloc으로 할당한 메모리를 free하지 않으면 메모리 누수가 발생합니다. 메모리 누수는 프로그램이 실행되는 동안 사용할 수 있는 메모리가 점점 줄어드는 문제를 일으킵니다. 메모리 누수가 지속되면 결국 프로그램이 사용할 수 있는 메모리가 부족해지고, 시스템 전체의 성능에 악영향을 미칠 수 있습니다. 심각한 경우 시스템의 메모리가 고갈되어 프로그램이 비정상 종료될 수 있습니다.

7. free한 이후에도 포인터 변수로 값을 바꾸면 어떻게 될까?

free한 메모리 영역에 접근하는 것은 정의되지 않은 행동(Undefined Behavior)을 유발합니다. 메모리 해제 후 해당 포인터는 더 이상 유효하지 않으며, 이 영역에 접근하거나 값을 변경하려고 하면 예측할 수 없는 결과를 초래할 수 있습니다. 최악의 경우, 프로그램이 즉시 충돌할 수 있으며, 심지어 특정 상황에서는 정상적으로 동작하는 것처럼 보일 수도 있습니다. 이는 Dangling Pointer를 만들고 디버깅을 매우 어렵게 만듭니다.

8. Dangling Pointer 란?

C와 같은 저수준 프로그래밍 언어에서 자주 발생하는 메모리 관리 문제 중 하나로, 해제된 메모리 영역을 여전히 가리키고 있는 포인터를 의미합니다.

 

댕글링 포인터는 다음과 같은 상황에서 발생할 수 있습니다:

 

메모리 해제 후 포인터 사용: 동적으로 할당한 메모리 블록을 free로 해제한 후, 해당 메모리를 가리키고 있던 포인터를 계속 사용하려고 할 때, 이 포인터는 더 이상 유효한 메모리 주소를 가리키지 않으므로 댕글링 포인터가 됩니다. 이 포인터로 메모리에 접근하려고 하면, 프로그램이 비정상적으로 동작하거나 충돌할 수 있습니다.

 

스택에서 해제된 메모리: 함수가 종료되면서 스택에 할당된 지역 변수가 해제되지만, 해당 변수의 주소를 다른 포인터에 저장해 두고 함수가 끝난 후에도 사용하려 할 때, 이 포인터 역시 댕글링 포인터가 됩니다.

9. 왜 sizeof(struct node { char color; struct node *next; })가 9가 아니고 16이 되는 이유

구조체 크기가 예상보다 큰 이유는 메모리 정렬(Memory Alignment) 때문입니다. 메모리 정렬은 프로세서가 데이터를 효율적으로 읽고 쓰기 위해 메모리를 특정 경계(보통 4바이트 또는 8바이트)로 맞추는 것을 말합니다.

struct node의 경우, char color는 1바이트, struct node *next는 보통 8바이트입니다. 이 구조체의 크기를 계산할 때, char 타입 뒤에 오는 포인터가 8바이트 경계에 맞추어지기 위해 추가적인 패딩이 필요할 수 있습니다. 따라서:

  • char color는 1바이트.
  • 나머지 7바이트는 패딩.
  • struct node *next는 8바이트.

이로 인해 전체 구조체의 크기는 16바이트가 됩니다. 메모리 정렬이 구조체 크기에 큰 영향을 미칠 수 있기 때문에 이러한 현상이 발생합니다.

'WIL > 스터디' 카테고리의 다른 글

인터넷 지식  (1) 2024.08.27
Thread & Process  (0) 2024.08.25
Malloc Lab  (0) 2024.08.25
Virtual Memory  (0) 2024.08.23
Pintos Extra Questions  (0) 2024.08.22