Значение сообщения об ошибке C ++ / pthread / join "what (): неверный аргумент" - PullRequest
0 голосов
/ 19 декабря 2018

Это часть более крупного приложения, простого потока таймера, который корректно работает перед попыткой его завершения:

boost::asio::io_service io_service;
shared_ptr<thread> loop;
// it is not initialised here, just shows the idea
boost::asio::deadline_timer timer(io_service, interval);

void Timer::spin() {
    loop = make_shared<thread>(&Timer::run, this);
}
void Timer::unspin() {
    io_service.stop();
    loop.get()->join();
}
void run() {
   timer.async_wait(bind(&Timer::callbackWrapper, this, _1));
   // restart
   io_service.run();    
}

Поток, созданный в spin, теоретически завершен и присоединен вunspin().В случае, когда приложение заканчивается с join() закомментированным, появляется сообщение об ошибке

terminate called without an active exception

, которое, если я его «расшифровал», означает «основной поток завершен, когда некоторые другие потоки все еще работают»(Я не знаю C ++ lingo.)

Если, в свою очередь, вызывается unspin(), может появиться следующее сообщение об ошибке spotty :

terminate called after throwing an instance of 'std::system_error'
  what():  Invalid argument

который наиболее вероятно брошен thread.join().Проблема в том, что я искал вокруг Stackexchange, но не смог объяснить другое сообщение.Я понимаю, что проблема может быть за пределами небольшого фрагмента кода (приложение довольно большое, поэтому я не включаю его).Но даже если это так, я бы просто спросил значение второго сообщения об ошибке и его возможных причин.

Ответы [ 2 ]

0 голосов
/ 19 декабря 2018

Этот код в его текущей форме не может быть отлажен.Это связано с тем, что у него есть правила интерфейса (например, не вызывать spin два раза подряд), которые не обнаруживаются кодом.Это делает код очень сложным для тестирования, отладки и сопровождения.

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

  1. Сделайте так, чтобы ваш код обнаруживал такие нарушения его требований к интерфейсу, чтобы вы могли легко найти и исправить их.Это легко здесь.Функция unspin может reset shared_ptr.Функция spin может проверить, что shared_ptr не установлен.

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

  3. Если вы столкнулись с проблемой, которую не можете исправить, код и модульное тестирование могутзатем в одиночку покажите проблему, и вы точно поймете, какой аспект кода дает сбой.

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

0 голосов
/ 19 декабря 2018

Возможных причин для чего-то, чтобы бросить std::system_errorEINVAL, как здесь, или с некоторым другим значением) множество.

Вы можете либо:

  1. Google для экземпляров std::system_error на cppreference.com или
  2. Проинструктируйте ваш отладчик прерывать на бросок, тогда вы сможете точно увидеть, что вызвало исключение - затем перейдите к документации для этой вещи и прочитайтепочему бы это выкинуть.

Эти сообщения не являются загадочными per se , они просто косвенные из-за того, как работает вся экосистема C ++.Могло ли оно быть разработано для вызова какой-то определенной функции завершения, предназначенной исключительно для случая, когда вы забыли присоединиться к потоку?Конечно.

Но это было бы действительно громоздко, увеличивая размер модуля времени выполнения, потому что не было никакой выгоды.Когда вы пишете больше кода, вы приобретете опыт и начнете просто вспоминать или «чувствовать», какие вещи могут вызывать какие-то проблемы.Все, что касается std::system_error или std::terminate в многопоточном коде, почти наверняка связано с неправильной обработкой указанных потоков.Вы просто узнаете, что через некоторое время.

В этом случае вы можете запомнить два следующих объяснения:

завершить вызов без активного исключения

Что-то называется std::terminate напрямую.Опять же, вы можете найти эти высказывания в документации библиотеки и выяснить возможные причины, которые относятся к вашему коду.

завершение вызова после выброса экземпляра 'std :: system_error'

Было сгенерировано исключение , но в вашей программе, которая его перехватила, нет try / catch, поэтому система исключений вызвала std::terminate.Опять же, вы можете исследовать, какие функции вы используете, можете выбросить std::system_error, а также рассмотреть возможность добавления некоторой безопасности исключений в ваш код, пока вы на нем.

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