C 裡面 fork() 的奇怪行為?

在寫 OS 的 fork 作業時,遇到了一個奇怪的行為,明明型態為 void 的函式執行到尾端應該要自己返回的,但是卻疑似沒有返回,直接一路又往下跑,就像寫組語的時候,寫了 Branch ,卻漏了 MOV PC, LR 一樣。

先附上整段 code

//
//  main.c
//  fork-homework
//
//  Created by Ikaros on 2016/10/15.
//  Copyright © 2016年 Ikaros. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define STR_BUFFER_SIZE 100
#define STR_LIST_SIZE 100

const char* delim = "/\n";

void listDir(char* path, int depthRemaining){  
    if(depthRemaining == 0) return;

    int fileListItems = 0;
    char** fileList = (char**)malloc(sizeof(char*) * STR_LIST_SIZE);
    char* filepath = (char*)malloc(sizeof(char) * STR_BUFFER_SIZE);
    strcpy(filepath, path);
    strcat(filepath, "/list");
    FILE *file = fopen(filepath, "r");
    if(!file) {printf ("File not found!\n"); exit(1);}

    while(!feof(file)){
        char* str = (char*)malloc(STR_BUFFER_SIZE);
        fgets(str, STR_BUFFER_SIZE, file);
        if(*str == '0' || *str == '1'){ // Ensure it is not an empty line.
            *(fileList+fileListItems) = str;
            fileListItems++;
        }
    }
    fclose(file);

    int i;
    for (i = 0; i < fileListItems; i++){
        char* item = *(fileList+i);
        if (*item == '1') { // File
            char *tmp = NULL;
            char* currentFileName = strtok_r(item, delim, &tmp);  // Discard the first one.
            currentFileName = strtok_r(NULL, delim, &tmp);
            printf("%s/", path); printf ("%s\n", currentFileName);
        }
        else { // Folder
            char *nextFolder = NULL;
            char *tmp = NULL;
            nextFolder = strtok_r(item, delim, &tmp); // Discard the first one.
            nextFolder = strtok_r(NULL, delim, &tmp);
            char* nextPath = (char*)malloc(STR_BUFFER_SIZE);
            strcpy(nextPath, path);
            strcat(nextPath, "/");
            strcat(nextPath, nextFolder);
            printf("%s\n", nextPath);

            pid_t child = fork();
            if(child == 0){ // in child process.
                listDir(nextPath, depthRemaining-1);
                exit(0);
            }
            else
                wait(NULL);
        }
    }
    return;
}

int main(int argc, const char * argv[]) {  
    int depth = 0;

    do {
        printf ("請輸入最多查詢幾層: ");
        scanf("%d", &depth);
        if(depth >= 1 && depth <= 6){
            printf ("最多查詢層數為: %d\n", depth);
            break;
        }
        printf ("查詢層數僅限 1~6 \n");
    } while (1);

    listDir(".", depth);
    return 0;
}

在裡面的這段

if(child == 0){ // in child process.  
    listDir(nextPath, depthRemaining-1);
    exit(0);
}

如果沒有 exit(0) 的話,整段程式就會變成一個 fork bomb ,不斷的 fork 下去,但是照理說這題應該要最後讀到全部都是檔案,然後 return 的,不會有無限讀到資料夾的情況發生才是。

可是看別人網路上的範例,如果裡面只做個 printf() ,不放 exit(0) 好像又不會出錯,怪怪。

總之,做個筆記,如果會產生 fork bomb 的話,用 exit(0) 幫她冷靜一下。

Ikaros

Read more posts by this author.