LINUX.ORG.RU

fork(), wait()

 ,


0

1

Всем привет!

Помогите разобраться в чем ошибка. Принцип программы прост: пройти по всем подкаталогам заданного каталога(argv[1]) и вывести путь до каждого файла. Но путь до файла должен выводить отдельный процесс. Главный процесс запускает функцию SearchFile, для вывода пути к файлу, ГЛАВНЫЙ процесс порождает дочерний, и тот в свою очередь выводит путь. Колличество дочерних не должно превышать N(argv[3]).

Вот функция SearchFile:

void SearchFile(char *catalog_name, char *argv[], FILE *file_proc)
{
        DIR *current_catalog;
        struct dirent *current_element;
        char *current_way = NULL;
        int proc_count = atoi(argv[3]);
        pid_t pid;
        errno = 0;

        if(strcmp(catalog_name, "/proc") != 0) {
        /*if the directory can be opened*/
        if (current_catalog = opendir(catalog_name)) {
                while(TRUE) {
                        current_element = readdir(current_catalog);
                        if (current_element)
                                if ((strcmp(current_element->d_name,"..") != 0) && (strcmp(current_element->d_name,".") != 0)) {
                                        /*Add new element`s name to the path*/
                                        current_way = EditAdress(catalog_name, current_element->d_name);
                                        if (current_element->d_type == 4) 
                                                SearchFile(current_way, argv, file_proc);
                                        else
                                                if (current_element->d_type == 8) {
                                                        state = TRUE;
                                                        if (pr_c < proc_count) 
                                                                pr_c++;
                                                        else {

                                                                wait();
                                                                pr_c--;
                                                        }
                                                        pr_c++;

                                                        //current_way = EditAdress(catalog_name, current_element->d_name);
                                                        pid = fork();
                                                        if (pid == 0) {
                                                                //sleep(1);
                                                                printf("%s\n", current_way);                                                               //sleep(10);
                                                                exit(0);
                                                        }
                                                        //current_way = EditAdress(catalog_name, current_element->d_name);
                                                        success = TRUE; 
                                                }
                        }
                        /*if the error, when openenig file, occured - pass it*/
                        if (errno) {
                                fprintf(stderr, "%s: %s: %s\n", argv[0], current_way, strerror(errno));
                                errno = 0; 
                        }
                        /*leave when reached catalog`s end*/
                        else
                                if (current_element == NULL)
                                        break;
                }
                if (closedir(current_catalog) == -1)
                        fprintf(stderr, "%s: %s: Couldn`t close catalog\n", argv[0], catalog_name);
        }
        else 
                fprintf(stderr, "%s: %s: Couldn`t open catalog\n", argv[0], catalog_name);      

        }       
}

Функция SearchFile (присоединяет название нового каталога к пути до текущего каталога):

char *EditAdress(char *catalog_name, char *file_name)   
{
        char *current_way = NULL;

        current_way = (char *) malloc(strlen(catalog_name) + strlen(file_name) + 2);//2
        strcpy(current_way, catalog_name);
        if(strlen(catalog_name) != 1)
                current_way[strlen(catalog_name)] = '/';
        current_way[strlen(catalog_name) + 1] = '\0';
        strcat(current_way, file_name);

        return current_way;
}

Теперь вопрос: почему после того как выполняется wait(), в current_way удаляются последние символы, и после нескольких прочитанных файлов, возникает Error: malloc(): memory corruption?

Пробовал в функции EditAdress выделять больше памяти (т.е не +2, а +10 к примеру), тогда ошибка с malloc() не возникает, но все равно в current_way удаляются последние символы. Если не создавать дочерние процессы, то все работает правильно, даже когда выделяю +2 элемента.

Вот на всякий случай весь код( пример вызова программы: ./prog /usr f 4, f ни на что не повлияет, просто нужно будет потом доделать программу до конца.):

pastebin.com/mvuaL7DV

Колличество дочерних не должно превышать N(argv[3]).

В код не вглядывался, потому что его много и вникать в конце пятницы лень, но на твоем месте я бы сделал пул процессов (по аналогии с пулом потоков) с числом процессов N, и имя файла отправлял бы туда (а дальше уж пул сам разберётся, какому потоку это дело вывести). [Г-ди, что за содомия]

В общем мой посыл в том, чтобы сначала отделить зерна от плевел и написать по-нормальному, а не так, как сейчас.

Напишешь внятный код - будет сложнее ошибиться и проще отыскать ошибку, если вдруг.

yoghurt ★★★★★ ()

facepalm.png

скомпилил, запустил — конечно там все зацикливается, и черт знает что и как печатается, и утекает куча памяти, но такой ошибки «Error: malloc(): memory corruption» нет


if (pr_c < proc_count) 
    pr_c++;
else {
    wait();
    pr_c--;
}
pr_c++;

double facepalm.png

итого: убей себя об стену и не пиши больше программы никогда

anonymous ()
Ответ на: комментарий от anonymous

но такой ошибки «Error: malloc(): memory corruption» нет

Ясен пень, это же от реализации аллокатора зависит, да и ещё от до кучи других факторов. ИМХО, тут даже GDB не поможет

stopitplease ()
Ответ на: комментарий от CraigB

как минимум фиксить логику работы с процессами:

// счётчик процессов - volatile
// и может быть отрицательным
volatile int pr_c=0; 
...
// уменьшаем его в обработчике сигнала
void sigchild_handler(int) {
   // чтоб было совсем хорошо,
   // в след.версии разберёшся с причиной SIGCHILD
   // он передаётся не только при завершении 
   pr_c--;
}
...
// как разберёшся, переделай на sigaction
signal(SIG_CHLD,sigchild_handler);
...
while(pr_c>=proc_count) // ожидаем уменьшения pr_c
  wait(); // wait срабатывает на любой сигал
...
pid=fork();
if (pid<0) {
   exit(EXIT_FAILURE);
} else if (pid) {
   pr_c++;
} else /* pid=0 */ {
  // child code
  ...
  exit(EXIT_SUCCESS);
}

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

Прошу прощения, забыл упомянуть, что знаю о плохой логике работы с процессами. Но меня интересует, почему возникает ошибка обращения к памяти, и почему при выводе пути к файлу, удаляются несколько последних символов?

CraigB ()
Ответ на: комментарий от CraigB

забыл упомянуть, что знаю о плохой логике работы с процессами. Но меня интересует, почему возникает ошибка обращения к памяти, и почему при выводе пути к файлу, удаляются несколько последних символов?

БЛДЖАТ!! топик «fork(),wait()» если мне глаза не изменяют?

Но на вопрос всё-же отвечу - ошибка с памятью возникает потому что ВСЁ х@#$во.

в вашем случае можно вообще обойтись без дин.памяти в лице malloc/free и проч. - ненужны оне.

далее malloc и free ходят парами - если где-то что-то выделялось, то где-то оно должно освобождаться

в EditAddress() какой-то бред. Он пишется в две строки, и вы там явно перемудрили. char *EditBlinAddress(char *a,char *b) { char *p=NULL;return asprintf(&p,«%s/%s»,a,b)<0?NULL:p}.

ps. и как-то надо привыкать к внятному именованию сущностей и какому-нить codestyle. Видя в вашем коде «current_way» на ум приходит только «communizm» и «electrofication»

MKuznetsov ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.