Книга: Программирование для Linux. Профессиональный подход

Листинг 11.2. (common.c) Функции общего назначения

Листинг 11.2. (common.c) Функции общего назначения

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "server.h"
const char* program_name;
int verbose;
void* xmalloc(size_t size) {
 void* ptr = malloc(size);
 /* Аварийное завершение, если выделить память не удалось. */
 if (ptr == NULL)
  abort();
 else
  return ptr;
}
void* xrealloc(void* ptr, size_t size) {
 ptr = realloc(ptr, size);
 /* Аварийное завершение, если выделить память не удалось. */
 if (ptr == NULL)
  abort();
 else
  return ptr;
}
char* xstrdup(const char* s) {
 char* copy = strdup(s);
 /* Аварийное завершение, если выделить память не удалось. */
 if (сору == NULL)
  abort();
 else
  return copy;
}
void system_error(const char* operation) {
 /* Вывод сообщения об ошибке на основании значения
    переменной errno. */
 error(operation, strerror(errno));
}
void error(const char* cause, const char* message) {
 /* Запись сообщения об ошибке в поток stderr. */
 fprintf(stderr, "%s: error: (%s) %sn", program_name,
  cause, message);
 /* Завершение программы */
 exit(1);
}
char* get_self_executable_directory() {
 int rval;
 char link_target[1024];
 char* last_slash;
 size_t result_length;
 char* result;
/* Чтение содержимого символической ссылки /proc/self/exe. */
 rval =
  readlink("/proc/self/exe", link_target,
 sizeof(link_target));
 if (rval == -1)
 /* Функция readlink() завершилась неудачей, поэтому выходим
    из программы. */
 abort();
 else
  /* Запись нулевого символа в конец строки. */
  link_target[rval] = '';
 /* Удаление имени файла,
    чтобы осталось только имя каталога. */
 last_slash = strrchr(link_target, '/');
 if (last_slash == NULL || last_slash == link_target)
 /* Формат имени некорректен. */
 abort();
 /* Выделение буфера для результирующей строки. */
 result_length = last_slash - link_target;
 result = (char*)xmalloc(result_length + 1);
 /* Копирование результата. */
 strncpy(result, link_target, result_length);
 result[result_length] = '';
 return result;
}

Приведенные здесь функции можно использовать в самых разных программах.

? Функции xmalloc(), xrealloc() и xstrdup() являются расширенными версиями стандартных функций malloc(), realloc() и strdup(), в которые дополнительно включен код проверки ошибок. В отличие от стандартных функций, которые возвращают пустой указатель в случае ошибки, наши функции немедленно завершают работу программы, если в системе недостаточно памяти.

Раннее обнаружение нехватки памяти — хорошая идея. Если этого не делать, пустые указатели будут появляться в самых неожиданных местах программы. Ситуации, связанные с нехваткой памяти, непросто воспроизвести, поэтому их отладка будет затруднена. Ошибки выделения памяти обычно имеют катастрофические последствия для программы, так что аварийное ее завершение — вполне приемлемый вариант реакции.

? Функция error() сообщает о фатальной ошибке, произошедшей в программе. При этом в поток stderr записывается сообщение об ошибке, и работа программы завершается. Для ошибок, произошедших в системных вызовах или библиотечных функциях, предназначена функция system_error(), которая генерирует сообщение об ошибке на основании значения переменной errno (см. раздел 2.2.3, "Коды ошибок системных вызовов").

? Функция get_self_executable_directory() определяет каталог, в котором содержится исполняемый файл текущего процесса. Это позволяет программе находить свои внешние компоненты. Функция проверяет содержимое символической ссылки /proc/self/exe (см. раздет 7.2.1, "Файл /proc/self).

В файле common.c определены также две полезные глобальные переменные.

? Переменная program_name содержит имя выполняемой программы, указанное в списке аргументов командной строки (см. раздел 2.1.1, "Список аргументов").

? Переменная verbose не равна нулю, если программа работает в режиме выдачи развернутых сообщений. В таком случае многие компоненты будут записывать в поток stdout сообщения о ходе выполнения задачи.

Оглавление книги


Генерация: 2.278. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз