Запуск кода под любым программным обеспечением не имеет никакого значения.
Вы должны исправить код, который работает, а не запускать его под valgrind.
В Си все отлично работает:
pthread_cleanup_pop( 0 );
r = pthread_mutex_unlock( &mutex );
if ( r != 0 )
{
/* Explicit error handling at point of occurance goes here. */
}
Но поскольку c ++ - программный аборт, просто нет разумного способа с какой-либо степенью уверенности справляться с поточно-закодированными сбоями. Идеи мертвого мозга, такие как обертывание pthread_mutex_t в класс, который добавляет какую-то переменную состояния, - это просто - мозг мертв. Следующий код просто не работает:
Locker::~Locker()
{
if ( pthread_mutex_unlock( &mutex ) != 0 )
{
failed = true; // Nonsense.
}
}
И причина этого в том, что после того, как pthread_mutex_unlock () вернет этот поток, он может быть нарезан из процессора с вытеснением. Это означает, что публичная переменная .failed будет по-прежнему ложной. Другие потоки, просматривающие его, получат неверную информацию - переменная состояния сообщает об отсутствии ошибок, а pthread_mutex_unlock () - нет. Даже если по счастливой случайности эти два оператора выполняются за один раз, этот поток может быть прерван до того, как ~ Locker () вернется, а другие потоки могут изменить значение .failed. В итоге эти схемы не работают - не существует атомарного механизма тестирования и установки для переменных, определенных приложением.
Некоторые говорят, что у деструкторов никогда не должно быть кода, который дает ошибку. Все остальное - плохой дизайн. Хорошо. Мне просто любопытно посмотреть, что такое хороший дизайн, чтобы быть 100% -ным исключением и поточно-ориентированным в c ++.