Как освободить динамическую выделенную переменную с помощью 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, поэтому я не должен его называть. Но как освободить () эту переменную?

Большое спасибо за ваши ответы...

РЕДАКТИРОВАТЬ: valgrind также показывает достижимую переменную:

==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.

person izidor    schedule 02.05.2009    source источник
comment
Огромная мышь? Это какой-то крупный доисторический грызун? :-)   -  person JesperE    schedule 02.05.2009
comment
Прошу прощения, там, в Словакии, немного поздновато, так что я ошибся. Спасибо за уведомление.   -  person izidor    schedule 02.05.2009


Ответы (3)


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

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

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

person Steve Jessop    schedule 02.05.2009
comment
Так почему же valgrind показывает еще доступную память? (Возможно, вы правы, и мусор, показанный valgrind, сделан неправильным типом измерения valgrind) - person izidor; 02.05.2009
comment
valgrind пытается предупредить вас, что вы не освободили память перед выходом. Он по-прежнему освобождается ОС сразу после этого. Обычно этот отчет от valgrind вызывает у вас подозрение, что, возможно, ваша программа потеряла память. Но в случае выхода SIGTERM вы можете игнорировать это: вы знаете, что не прошли обычную очистку, поэтому ожидаете ложных заявлений об утечке памяти. - person Steve Jessop; 03.05.2009
comment
Хорошо спасибо. Мне было интересно, можно ли исправить эту проблемную вещь. Большое спасибо! - person izidor; 03.05.2009
comment
Я добавил абзац, который может помочь, если вам нужен чистый отчет valgrind. Однако, в зависимости от того, как ваш ребенок работает, это может быть больше проблем, чем пользы. - person Steve Jessop; 03.05.2009

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

person RichieHindle    schedule 02.05.2009

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

person karunski    schedule 02.05.2009