Соединение буквально и зачистка - PullRequest
0 голосов
/ 16 января 2020

Я использую атрибут переменной очистки , чтобы освободить мьютекс, используя этот макрос:

#define LOCK()                                                          \
    pthread_mutex_lock(&mutex);                                         \
    int32_t tmpv_ __attribute__((cleanup(mutexUnlock))) = 0;            \
    (void)tmpv_

mutexUnlock - это пользовательская функция, которая просто освобождает mutex ,

void mutexUnlock(int32_t* dummy)
{
    (void)dummy;
    pthread_mutex_unlock(&mutex);
}

После изучения составного литерала я хотел избавиться от переменной tmpv_, поскольку в этом контексте она не нужна:

#define LOCK()                                                          \
    pthread_mutex_lock(&mutex);                                         \
    (void)(int32_t __attribute__((cleanup(mutexUnlock)))){0}

Но компилятор дает мне предупреждение для каждого места, где используется макрос:

warning: 'cleanup' attribute does not apply to types [-Wattributes]

Я не уверен, как это интерпретировать. Также макрос не работает как положено (mutexUnlock не вызывается). В чем проблема с этим кодом?

1 Ответ

2 голосов
/ 17 января 2020

Я использую атрибут переменной очистки для освобождения мьютекса с помощью этого макроса [...]

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

Не говоря уже о том, что использование языковых расширений, особенно таких уникальных c, как атрибуты G CC, очень тесно связывает вас с конкретной реализацией C. Возможно, вас это не волнует, но если это я, я, по крайней мере, хочу получить что-то очень ценное взамен, и я не вижу этого здесь.

Узнав о составных литералах, Я хотел избавиться от переменной tmpv_, так как она не нужна в этом контексте.

Но это необходимо , или, по крайней мере, что-то нужно, чтобы повесить атрибут на. Я предполагаю, что вы пытаетесь повесить атрибут на составном литерале, но G CC не документирует эту поддержку:

Ключевое слово __attribute__ позволяет вам задавать специальные свойства переменных, параметры функции или структура, объединение и, в C ++, члены класса. [...] Другие атрибуты доступны для функций (см. Атрибуты функций), меток (см. Атрибуты меток), перечислителей (см. Атрибуты перечислителей), операторов (см. Атрибуты операторов) и для типов (см. Атрибуты типов).

( G CC электронная документация )

Составной литерал не является ни одним из элементов, документированных для поддержки атрибутов G CC.

Вы продолжаете,

#define LOCK()                                                          \
    pthread_mutex_lock(&mutex);                                         \
    (void)(int32_t __attribute__((cleanup(mutexUnlock)))){0}

Но компилятор выдает мне предупреждение для каждого места, где используется макрос:

warning: 'cleanup' attribute does not apply to types [-Wattributes]

Я не уверен, как это интерпретировать.

Единственная конструкция syntacti c в этом коде, к которой предположительно может быть прикреплен атрибут, - это имя типа int32_t. Как предупреждает G CC, атрибут cleanup не применяется к типам (хотя есть и другие атрибуты, которые применяются к типам). В результате использование атрибута не будет иметь никакого эффекта, как вы уже заметили (еще одна причина, чтобы не пытаться быть милым / волшебным). G CC решает предупредить вас об этой проблеме, вместо того, чтобы либо вообще прекратить компиляцию, либо игнорировать атрибут без уведомления.

В чем проблема с этим кодом?

Если Вы можете прикрепить атрибуты к составным литералам, я ожидаю, что G CC потребует, чтобы они предшествовали или следовали за литералом, а не появлялись внутри него. Но опять же, насколько я могу судить, G CC не поддерживает атрибуты для составных литералов.

В общем, единственный удаленно разумный способ использовать атрибут __cleanup__ - это прикрепить его к объекту. Вы хотите очистить - mutex в этом случае. Присоединение его к прокси-объекту с целью использования области действия этого объекта для запуска случайного поведения, связанного с другим объектом, является печальным злоупотреблением этой функцией. Я бы порекомендовал отказаться от всей идеи и вместо этого явно разблокировать мьютекс.

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