Информационный портал по безопасности » Программирование » Game Development » Об одном трюке для возврата кода ошибки из функции

 

Об одном трюке для возврата кода ошибки из функции

Автор: admin от 8-03-2015, 23:25, посмотрело: 457

Ядро Linux — кладезь как применяемых алгоритмов, так и некоторых хакерских или полухакерских трюков, призванных убыстрить и / или уменьшить размер в памяти (memory footprint). Об одном из таких полухахерских трюков я хочу рассказать далее.


В нашем убогом мире языке Си как таковых ссылок и классов не существует, но есть указатели и структуры. Часто возникает вопрос, что выбрать в качестве возращаемого значения функции, которая должна вернуть вызывающему указатель на живущий объект? Есть два как минимум варианта прототипов:
выше и сравните):
struct obj *get_obj(..., int *ret);
int get_obj(..., struct obj **);


Но теперь задача уменьшить количество аргументов функции, так как это сильно влияет и на скорость исполнения, и на объёмы расходуемой памяти на стеке (ведь мы же о ядре ОС говорим, да? :-) ).

Для этого было придумано такое решение. Поскольку void * у нас всё-таки число, то давайте разделим возможные значения на три отрезка (рассмотрим 32-битный случай):

  • 0x00…0x10

  • 0x11…0xffffffff — MAX_ERRNO

  • 0xffffffff — MAX_ERRNO + 1…0xffffffff


Первый — NULL pointer, второй — обычное адресное пространство, третий же — невалидный указатель или код ошибки. Соответственно появилось несколько макросов для проверки:
ZERO_OR_NULL_PTR();
IS_ERR();
IS_ERR_OR_NULL();

И люди начали ими пользоваться!

Результирующий прототип превратился в:
struct obj *get_obj(...);

И пример использования:
struct obj *get_obj(...)
{
  struct obj *obj = malloc(sizeof(*obj));
  int ret;

  if (!obj)
    return ERR_PTR(-ENOMEM);

  ret = do_smth(obj, ...);
  if (ret) {
   free(obj);
   return ERR_PTR(ret);
  }
  return obj;
}

int whatever(...)
{
  struct obj *obj = get_obj(...);
  if (IS_ERR(obj))
    return PTR_ERR(obj);
  printf("Cool object %pn", obj);
  return 0;
}

Встречаются однако и проблемы с этим подходом, например, из-за неправильного применения макроса IS_ERR_OR_NULL для тех частей кода, где NULL — валидный возврат, например, когда объёкт отвечает за некую функциональность в ядре, которая в данной сборке ядра выключена. Тогда возвращается NULL pointer, который надо обрабатывать по-другому!

Источник: Хабрахабр

Категория: Game Development / Linux

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Добавление комментария

Имя:*
E-Mail:
Комментарий:
  • bowtiesmilelaughingblushsmileyrelaxedsmirk
    heart_eyeskissing_heartkissing_closed_eyesflushedrelievedsatisfiedgrin
    winkstuck_out_tongue_winking_eyestuck_out_tongue_closed_eyesgrinningkissingstuck_out_tonguesleeping
    worriedfrowninganguishedopen_mouthgrimacingconfusedhushed
    expressionlessunamusedsweat_smilesweatdisappointed_relievedwearypensive
    disappointedconfoundedfearfulcold_sweatperseverecrysob
    joyastonishedscreamtired_faceangryragetriumph
    sleepyyummasksunglassesdizzy_faceimpsmiling_imp
    neutral_faceno_mouthinnocent