Это хорошая практика, чтобы вернуть указатель из функции в с? - PullRequest
7 голосов
/ 08 ноября 2010

Например:

int *point() {
 int *q = malloc(sizeof(int));
 *q=20;
 return q;
}

int main() {
    int *a = point();
    free(a);
}

Интересно, хорошая ли это практика в с?

Ответы [ 7 ]

13 голосов
/ 08 ноября 2010

Возвращение указателей довольно распространено.Проблема, или необходимая дисциплина, состоит в том, чтобы быть уверенным, где лежит ответственность за освобождение памяти.Этот пример пахнет, потому что не ясно, что его нужно было free'd в main ().

8 голосов
/ 08 ноября 2010

Я думаю, что проблема бесплатна (а);Я думаю, что вы должны добавить функцию release_point ().

5 голосов
/ 08 ноября 2010

Посмотрите пример C на странице в Википедии для непрозрачных указателей . Это способ структурирования кода, при котором вы полностью управляете памятью на одной стороне интерфейса.

3 голосов
/ 08 ноября 2010

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

Причина этого заключается в том, что если вы измените структуру возвращаемого вами содержимого таким образом, что простого free больше не будет достаточно (поскольку вы добавляете к возвращаемым указателям на выделенную память, которые сами должны быть освобождены ) клиентам не нужно менять свой код; Вы можете просто изменить существующую бесплатную функцию.

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

3 голосов
/ 08 ноября 2010

Единственная реальная опасность, которую я знаю о возвращении указателя на выделенную память, заключается в следующем: если ваша библиотека скомпилирована в Windows и связана, например, с одним экземпляром библиотеки времени выполнения Visual C ++ (MSVCRT), она статически связана сэто, и клиентская программа связана с другим экземпляром, например, она связана с DLL, тогда у каждого из них есть своя арена malloc, и указатели, возвращаемые библиотекой, не могут быть освобождены программой.Любая попытка сделать это может привести к сбою программы.

1 голос
/ 08 ноября 2010

Если у вас есть согласованная система определения того, какие функции возвращают указатели, которые должны быть освобождены (например, использование слова create или new в имени функции), тогда вам будет проще управлять вашей памятью.

int *createPoint()
{
    int *q = malloc(sizeof(int));
    if (*q)
       *q = 20;
    return q;
}
0 голосов
/ 08 ноября 2010

Часто это хорошая практика, но ваш пример - один из немногих случаев, когда это очень плохая практика.Вы никогда не должны использовать динамическое размещение и указатели для отдельных объектов, которые являются маленькими и не содержат (и никогда не должны будут содержать) сами указатели.Для получения 4-байтового int с malloc необходимо использовать не менее 16 байт, если учесть затраты на ведение бухгалтерского учета, но, возможно, гораздо важнее, это означает, что вам нужно беспокоиться о возможных сбоях выделения (и о том, как с ними обращаться)чтобы освободить объект.

Некоторые примеры объектов, которые вы не должны размещать следующим образом:

  • любой базовый тип
  • упорядоченные пары / координаты / векторы / матрицы/так далее.(при условии, что они имеют фиксированное измерение)
  • IP-адреса
  • значения цвета

Конечно, один раз может иметь смысл выделить и вернутьуказатель на такие объекты, когда вы выделяете массив из них.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...