Распределение памяти включено в API - PullRequest
0 голосов
/ 25 марта 2010

Если есть «struct foo» и API, которые обрабатывают foo, какой более гибкий и удобный API?

1) API только инициализирует foo. Пользователь должен объявить foo или выделить память для foo. Этот стиль похож на pthread_mutex_init / pthread_mutex_destroy.

пример 1)

struct foo a;
init_foo(&a);'

пример 2)

struct foo *a;
a = malloc(sizeof(struct foo));
init_foo(a);

2) API распределяет память и пользователь получает указатель. Это как getaddrinfo / freeaddrinfo.

пример)

struct foo *a;
get_foo(&a);
put_foo(a);

Ответы [ 6 ]

3 голосов
/ 25 марта 2010

Это действительно зависит от API. Первое имеет преимущество в том, что пользователь может встраивать тип библиотеки в свои собственные структуры без какого-либо косвенного обращения, если это выгодно; с другой стороны, тип структуры должен быть полностью известен пользователю библиотеки, который делает любые изменения интерфейса, которые могут изменить двоичную совместимость.

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

2 голосов
/ 25 марта 2010

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

При подходе, выделенном вызывающим абонентом, вызывающий абонент получает больше гибкости. Вызывающий может выбрать размещение структуры в стеке или может использовать другой распределитель. Недостаток - особенно с точки зрения вызываемой библиотеки - состоит в том, что структура не является непрозрачной. Если вызывающий отвечает за распределение, вызывающий должен знать, насколько велика структура. Это может быть нежелательно, если автор библиотеки хочет иметь больше свободы для изменения внутренних элементов структуры.

1 голос
/ 26 марта 2010

Исходя из моего опыта, я рекомендую следующий способ:

struct foo *p = foo_init();
foo_destroy(p);

особенно, когда "struct foo" сложна и имеет элементы с динамической памятью. Для небольшого "struct foo" этот путь стоит несколько дополнительных байтов для указателя; тогда предпочтительнее путь. Обратите внимание, что pthread_mutex_t имеет 24 байта в 32-битной системе, относительно небольшой.

0 голосов
/ 25 марта 2010

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

0 голосов
/ 25 марта 2010

Win32 часто использует третий подход: вызывающая программа создает структуры и инициализирует поля вручную, включая параметр «size», который действует как версия, а также для размещения членов переменной длины - обычно строк - в структуре, а не в отдельной памяти распределение.

0 голосов
/ 25 марта 2010

Первый API, потому что вы можете выделить память для структуры из стека или кучи. Во втором API должно использоваться динамическое выделение, и вы не можете контролировать способ выделения памяти для структуры.

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