Memory Leak in C
νν μ€μ Project2μλ OOM ν μ€νΈκ° μλλ°, ν λΉ κ°λ₯ν μμμ λͺ¨λ μμ§ν λκΉμ§ νλ‘μΈμ€λ₯Ό forkνλ 무μ무μν ν μ€νΈμ΄λ€. νλ‘μΈμ€λ₯Ό μμ±νκ³ μ’ λ£μν€λ κ³Όμ μ 10ν λ°λ³΅νλ―λ‘μ fork κ°λ₯ν νλ‘μΈμ€μ μκ° λ§€λ² κ°μμ§, μ¦ μ’ λ£ κ³Όμ μμ λ©λͺ¨λ¦¬ λμκ° λ°μνμ§ μλμ§ μ²΄ν¬νλ€. μ΄μ체μ μ μμ€ν μ½μ μꡬμ¬νμ λν΄ μκ³ , ꡬννλ©΄ passλμλ ν μ€νΈμλ λ¬λ¦¬, μ΄ ν μ€νΈλ μ€μ λ‘ μ½λκ° μμ νκ² (λμ μμ΄) μ§μ¬μ Έ μλμ§λ₯Ό νμΈνκΈ° λλ¬Έμ 무μ보λ€λ λ Όλ¦¬μ μΌλ‘.. μ½λλ₯Ό μ μ§λ μλμ΄ μ€μνλ κ² κ°λ€.
1) λ©λͺ¨λ¦¬ ν λΉ ν¨μλ₯Ό μ°λ©΄, μ ν΄μ ν΄ μ£Όμ.
tid_t thread_create(...) {
struct thread_child *child;
struct thread *t;
tid_t tid;
ASSERT(function != NULL);
/* Allocate thread. */
t = palloc_get_page(PAL_ZERO);
if (t == NULL) return TID_ERROR;
...
/* Add to parent's child list. */
child = calloc(1, sizeof(struct thread_child));
if (child == NULL) {
palloc_free_page(t); // π₯ μ¬κΈ°
return TID_ERROR;
}
...
λΉμ°ν λ§μ΄μ§λ§, μ μ΄μ μ΄ λΆλΆμ μ κ²½μ°λ©΄μ μ½λλ₯Ό μ§μ§ μμΌλ©΄ λμ μ§μ μ μ°ΎκΈ° μ΄λ €μμ§λ κ²½μ°κ° λ§μλ€. 18λ² λΌμΈμμ palloc_free_page(t)
λ₯Ό ν΄μ£Όμ§ μμΌλ©΄ λ©λͺ¨λ¦¬ λμκ° λ°μνλ€. μ€λ₯κ° λ°μνμ λ μμΈ μ²λ¦¬λ₯Ό νλ©΄μ μ΄μ μ ν λΉλ°μλ λ©λͺ¨λ¦¬λ₯Ό μ ν΄μ ν΄ μ£Όμ΄μΌ νλ€. ν¨μκ° λ¦¬ν΄νλ λͺ¨λ μΌμ΄μ€μμ ν΄μ ν΄ μ£Όλ κ²μ μμ§ λ§μ.
2) λ©λͺ¨λ¦¬ ν λΉ μ¬λΆλ₯Ό νμΈν μ μλλ‘ ν¨μλ₯Ό μ§μ.
/* General process initializer for initd and other process. */
static bool process_init(void) {
struct thread *curr = thread_current();
/* Set as user task. */
curr->mode = USER_TASK;
/* Create file descriptor table. */
curr->fdt = palloc_get_page(PAL_ZERO);
if (curr->fdt == NULL) return false; // π₯ μ¬κΈ°
return true;
}
λ€μκ³Ό κ°μ΄, ν¨μ λ΄μμ λ©λͺ¨λ¦¬ ν λΉμ ν κ²½μ°, ν λΉ μ±κ³΅/μ€ν¨μ λ°λΌ bool
λλ int
λ°νκ°μ λ°νν΄ μ£Όμ΄μ ν¨μλ₯Ό λΆλ₯΄λ μͺ½μμ ν λΉ μ¬λΆμ λν΄ μ μ μλλ‘ μ½λλ₯Ό μμ±νλ κ²μ΄ μ’λ€. malloc
, palloc
, calloc
λ±μ ν¨μλ₯Ό μΈ λλ λ°λμ μ€ν¨ κ°λ₯μ±μ μΌλμ λμ΄μΌ νλ€. (μ΄μ μ Cλ₯Ό μ²μ λ°°μ°λ©΄μ, 'mallocμΌλ‘ ν λΉλ°μ ν¬μΈν°μ λν NULL checkλ₯Ό μ΅κ΄μ μΌλ‘ ν΄λΌ' λΌκ³ λ§ λ°°μ λλ°, κ·Έ μ΄μ μ νμμ±μ μ΄ν΄ν기보λ€λ κΈ°κ³μ μΌλ‘ μ μ©λ§ νκ³ μμλ€. Pintos νλ‘μ νΈλ₯Ό νλ©΄μ μ€μ ν λΉ μ€ν¨μ μν©μ μμΈμ²λ¦¬νλ κ²μ΄ μ λ§ λ무λ무λ.. μ€μνλ€λ κ²μ 체κ°ν μ μμλ€.)
3) μμΈ μ²λ¦¬μ μ€ν μ§μ μ μ λ°°μΉνμ.
int dup2(int oldfd, int newfd) {
if (!is_valid_fd(oldfd)) return -1;
if (!is_valid_fd(newfd)) return -1;
struct file **fdt = thread_current()->fdt;
if (oldfd == newfd) return newfd;
if (fdt[oldfd] == NULL) return -1;
/* If newfd already has a file, close. */
if (fdt[newfd]) {
close(newfd);
}
/* If standard i/o, just copy value. */
if (is_file_std(fdt[oldfd])) {
fdt[newfd] = fdt[oldfd];
return newfd;
}
...
μ ν¨μμμ standard I/O μλ³μμ κ°μ 볡μ¬ν΄μ£Όλ λΆλΆκ³Ό, fdt[newfd]
κ° μ΄λ € μλ νμΌμ΄λΌλ©΄ λ¨Όμ λ«μ μ£Όλ λΆλΆμ΄ μμκ° λ°λμ΄ μλ€λ©΄ λ©λͺ¨λ¦¬ λμκ° λ°μνλ€. μ¦μ 리ν΄νλλ‘ μμΈ μ²λ¦¬λ₯Ό ν κ²½μ° νΉνλ λ¦¬ν΄ μ μ μμμ΄ λͺ¨λ ν λΉ ν΄μ λμλμ§ νμΈνλ κ²μ΄ μ€μνλ€.
μΈλ§ν¬μ΄, λ½κ³Ό κ°μ λκΈ°ν λ©μ»€λμ¦ μμ μ μ¬νλ€. μ μμ μΈ μλ리μ€λΏλ§ μλλΌ μμΈ μ²λ¦¬ λ‘μ§μμλ λ½μ μ releaseν μ μλλ‘ ν΄μΌ νλ€. νΉν, νλ‘μΈμ€κ° λΉμ μμ μΈ μ€λ₯ (ex. segmentation fault)λ‘ μ’ λ£λ κ²½μ°, κ·Έ μ μ μμ νκ³ μλ λ©λͺ¨λ¦¬, λ½, μΈλ§ν¬μ΄ κ°μ μμμ λͺ¨λ λ°ννλλ‘ μμ±ν΄μΌ μμ νλ€.
π 무μμ λκΌλμ
μ΄μ μ λλ²κΉ λ°©λ²μΌλ‘λ λμ μ§μ μ μ°ΎκΈ° νλ€λ€λ μ μ΄ κ°μ₯ λκ°ν λΆλΆμ΄μλ€. Faultκ° λκ±°λ, μλνλ μ€ν μ§μ κΉμ§ μ½λκ° μ€νλμ§ μμ κ²½μ° logλ₯Ό μ°μ΄λ³΄λ©΄μ λλ²κΉ νκ³ , λ³΄λ€ λ³΅μ‘ν λ‘μ§μ κ²½μ° gdbλ₯Ό νμ©ν΄ ν μ€ ν μ€ κ°μ κ²μ¬ν μ μμλ€. νμ§λ§ λ©λͺ¨λ¦¬ λμμ κ²½μ°, μ½λλ₯Ό λμΌλ‘ νμ΄λ³΄λ©° λ‘μ§μ 체ν¬ν΄μΌ ν리λ λΆλΆμ΄ μμλ κ² κ°λ€. (νΉν Out of Memory ν μ€νΈλ λ©λͺ¨λ¦¬κ° νμ©νλλ§νΌ forkλ₯Ό νκΈ° λλ¬Έμ, λλ²κ±°λ‘ λ°λΌκ°κΈ°μλ λ¬΄λ¦¬κ° μμλ€.) μ½λμμ μλͺ»λ λ‘μ§μ λ°κ²¬νκ³ μμ νλ κ²μ μκ°μ΄ μκ°λ³΄λ€ ν¨μ¬ λ§μ΄ κ±Έλ Έλλ°, κ²°κ³Όμ μΌλ‘ μ₯μ₯ 5μκ°(+a)μ λλ²κΉ λμ λ°κ²¬ν λμ μ§μ μ λ€μκ³Ό κ°μλ€.
/* Open a new file. */
int open(const char *file_name) {
if (file_name == NULL) return -1;
struct thread *curr = thread_current();
int fd = allocate_fd();
struct file *file = filesys_open(file_name);
if (!is_valid_fd(fd)) return -1; // π₯ μ¬κΈ°
if (file == NULL) {
free_fd(fd);
return -1;
}
curr->fdt[fd] = file;
return fd;
}
νμλ λΌμΈμ μ½λλ₯Ό ν μ€λ§ μλ‘ μ¬λ¦¬λ©΄ λμκ° λ°μνμ§ μλλ€. file descriptor tableμ΄ λͺ¨λ ν λΉλ κ²½μ° allocate_fd()
λ -1μ λ°ννλλ°, μ΄ κ²½μ°μλ μ μμ μΌλ‘ νμΌμ μ΄μ§ λͺ»νμΌλ―λ‘ -1μ 리ν΄νλλ‘ μ½λλ₯Ό μμ±νλ€. λ¬Έμ λ κ·Έ μ μ μ΄μ΄ λ νμΌμ λ«λ λΆλΆμ΄ μλ€λ κ²μ΄λ€. λ°λΌμ fdκ°μ λν validationμ λ¨Όμ νκ³ , νμΌμ μ΄λλ‘ ν΄μΌ νλ€. μΌλ°μ μΌλ‘ νλμ μμμ ν λΉνμΌλ©΄, μ¦μ ν λΉ μ¬λΆμ λ°λΌ μμΈμ²λ¦¬λ₯Ό νλλ‘ μ½λλ₯Ό μ§λ κ²μ΄ μ’μ κ² κ°λ€.
μ΄μ μ ν μ€νΈμμλ 'λμκ°λ μ½λ'λ₯Ό νκ°νλ€λ©΄, Out of Memory ν μ€νΈλ μ½λμ μμ μ±μ νκ°νλ€λ μ μμ κΉλ€λ‘μ λ κ² κ°λ€. μμ ν λΉ/ν΄μ λ₯Ό μ κ³ λ €νλ©° μ½λλ₯Ό μ§λ κ²μ΄ μ΄λ―Έ μμ±λ μ½λμμ λμ μ§μ μ λλ²κΉ νλ κ²λ³΄λ€ ν¨μ¬ μ½λ€λ μ μμ, μ μ΄μ μ½λλ₯Ό μ μ§λ κ²μ΄ μ’λ€. νΉν 1. ν¨μκ° λ¦¬ν΄λλ λͺ¨λ μν©μμ ν λΉλ μμμ ν΄μ κ° μ΄λ£¨μ΄μ ΈμΌ ν μ μλ€λ κ²κ³Ό 2. ν λΉμ μ±κ³΅/μ€ν¨ μ¬λΆλ₯Ό λ°λμ 체ν¬νκ³ λ‘μ§μ μ§μΌ νλ€λ κ²μ κΌ κΈ°μ΅νμ. ν λΉμ μ€ν¨ν κ²½μ° λ‘κ·Έλ₯Ό λ¨κΈ°λ κ²λ λ°©λ²μΈ κ² κ°λ€.
oom ν μ€νΈλ₯Ό λ§μ§λ§μΌλ‘.. μ΄μ°μ μ° Project2μ ν μ€νΈλ₯Ό all pass νλ€.. test caseκ° λΆμ€ν κ²½μ°κ° λ§μ κ² κ°μ§λ§ μ΄μ¨λ ν΅κ³Ό..
'DevLog π¨' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[DevLog][PintOS] PRJ3 Virtual Memory/Memory Mapped Files to Copy-on-write (1) | 2023.10.24 |
---|---|
[DevLog][PintOS] PRJ3 Virtual Memory/Memory Management to Stack Growth (2) | 2023.10.17 |
[DevLog][PintOS] PRJ1 Threads/PintOS μ€λ λλ μ΄λ»κ² λμκ°κΉ? (0) | 2023.10.03 |
[DevLog][PintOS] PRJ1 Threads/Scheduling Algorithms (0) | 2023.10.03 |
[DevLog][PintOS] PRJ1 Threads/Priority Scheduling (0) | 2023.09.27 |