2009-05-02 2 views
0

Я работаю на коде что-то вроде этогоКак освободить динамическую выделенную переменную от SIGTERM?

... HEADERS ... 

int *var; 

void child() { 
    ... //some work 
    free(var); 
    exit(EXIT_SUCCESSFUL); 
} 

int main(void) { 
    ... 
    //allocate variable 
    var = (int *) malloc(N*sizeof(int)); 
    ... //work with var 

    for(int i; i<PROC_COUNT; i++) { 
    pid_t child = fork(); 
    if(pid == 0) { 
     child(); //main function of new proces 
     break; 
    } 
    elseif(pid < 0) { 
     //there is enormous problem -> kill every proces 
     kill(0, SIGTERM); 
     waitpid(0, NULL, 0); //wait for children 
     free(var); 
     exit(EXIT_FAILURE); 
    } 

    } 
    free(var); 
    return EXIT_SUCCESS; 
} 

Когда процесс разветвляется, все переменные клонированного тоже. В обычном случае все копии var освобождаются.

Если есть ошибка fork(), я посылаю сигнал SIGTERM всем созданным процессам. И мне нужно написать обработчик сигналов для SIGTERM, который освобождает приложение var и завершает работу. Однако free() не signal safe function - поэтому я не должен его называть. Но как освободить() эту переменную?

Огромное спасибо за ваши ответы ...

EDIT: Valgrind также по-прежнему показывает reacheable переменную:

==5928== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 15 from 1) 
==5928== malloc/free: in use at exit: 20 bytes in 1 blocks. 
==5928== malloc/free: 1 allocs, 0 frees, 20 bytes allocated. 
==5928== For counts of detected errors, rerun with: -v 
==5928== searching for pointers to 1 not-freed blocks. 
==5928== checked 49,164 bytes. 
+0

Enourmouse? Это какой-то крупный доисторический грызун? :-) – JesperE

+0

Прошу прощения, немного поздно, в Словакии, поэтому я ошибся. Спасибо за уведомление. – izidor

ответ

4

Я сомневаюсь, что вам нужно. Любая ОС, которая поддерживает fork(), также автоматически освобождает выделение от malloc(), когда процесс завершается, независимо от того, как он это делает (включая завершение).

Существуют такие среды, в которых программы C не запускаются в процессах, и где вы должны быть очень осторожны, что вы оставите при обходе. Но эти среды не являются POSIX и не поддерживают fork(). В этом случае они могут не поддерживать сигналы. Если вы пишете для какой-либо такой необычной среды, проверьте свою документацию ...

Если вы хотите увидеть чистый отчет valgrind, вы можете заставить обработчик вставить событие в цикл событий ребенка (или установить флаг и разместить семафор или что-то еще) и обработать событие как чистый выход. Это то, что вы сделали бы, если бы ваша программа была интерактивным приложением, и вы хотели сохранить данные пользователя на SIGTERM, предполагая, что ваш интерфейс пользовательского интерфейса еще не перевел SIGTERM в событие для вас.

+0

Итак, почему valgrind показывает еще доступную память? (Может быть, вы прав, а мусор, показанный valgrind, сделан неправильным типом valgrind meassurment) – izidor

+0

valgrind пытается предупредить вас, что вы не освободили память до выхода. После этого он сразу освобождается ОС. Обычно этот отчет от valgrind заставит вас подозревать, что, возможно, ваша программа потеряла память. Но в случае выхода SIGTERM вы можете игнорировать это: вы знаете, что вы не прошли обычную очистку, поэтому вы ожидаете ложных утверждений о «утечке памяти». –

+0

Хорошо, спасибо. Мне было интересно, можно ли исправить эту проблематичную вещь. Большое спасибо! – izidor

0

Я может быть что-то недоразумение, но, конечно, после того, как SIGTERM весь процесс будет исчезать, взяв с собой переменную?

0

Вы можете использовать exec, чтобы запустить дочерний процесс из main, а не напрямую обращаться к функции child(). Используйте аргумент командной строки, чтобы уведомить дочернюю программу о выполнении основной работы. Тогда дочерний процесс сможет правильно очистить.