Могу ли я использовать STL, если я не могу позволить себе низкую производительность при выдаче исключений? - PullRequest
8 голосов
/ 03 октября 2008

Например, я пишу многопоточное критическое по времени приложение, которое обрабатывает и передает аудио в режиме реального времени. Прерывания в аудио абсолютно недопустимы. Означает ли это, что я не могу использовать STL из-за потенциального замедления при возникновении исключения?

Ответы [ 7 ]

28 голосов
/ 03 октября 2008

Как правило, единственными исключениями, которые контейнеры STL будут генерировать сами по себе, является std :: bad_alloc в случае сбоя new. Единственное другое время - когда пользовательский код (например, конструкторы, присваивания, конструкторы копирования) выбрасывает. Если ваш пользовательский код никогда не выбрасывает, вам нужно только защититься от новых бросков, которые вам, скорее всего, пришлось бы делать в любом случае.

Другие вещи, которые могут генерировать исключения: - at () функции могут генерировать std :: out_of_range, если вы обращаетесь к ним за пределами. В любом случае это серьезная ошибка программы.

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

8 голосов
/ 03 октября 2008

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

7 голосов
/ 15 августа 2009

Это не ясно написано в предыдущих ответах, поэтому:

Исключения случаются в C ++

Использование STL или нет не приведет к удалению кода RAII, который освободит выделенные вами ресурсы объектов.

Например:

void doSomething()
{
    MyString str ;
    doSomethingElse() ;
}

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

Если у вас есть проблемы с этим, то либо вы должны пересмотреть свое мышление, либо попробовать C.

Исключения должны быть исключительными

Обычно, когда возникает исключение ( и только тогда, когда ), производительность снижается.

Но тогда исключение следует отправлять только когда:

  • У вас есть исключительное событие для обработки (т. Е. Какая-то ошибка)
  • В очень исключительных случаях (т. Е. "Массивный возврат" от многократного вызова функции в стеке, например, при выполнении сложного поиска или разматывании стека до изящного прерывания потока)

Ключевое слово здесь «исключительное», что хорошо, потому что мы обсуждаем «исключение» (см. Образец?).

В вашем случае, если у вас возникло исключение, велика вероятность, что что-то настолько плохое случится, что ваша программа все равно рухнула бы без исключения.

В этом случае ваша проблема не связана с падением производительности. Он предназначен для корректной обработки ошибки или, что еще хуже, для корректного завершения вашей программы (включая окно сообщения «Извините», сохранение несохраненных данных во временный файл для последующего восстановления и т. Д.).

Это означает (если не в очень исключительных случаях), не используйте исключения в качестве «возвращаемых данных». Бросайте исключения, когда случается что-то очень плохое. Поймайте исключение, только если вы знаете, что с этим делать. Избегайте попытки / отлова (если вы не знаете, как обрабатывать исключение).

А как насчет STL?

Теперь, когда мы знаем, что:

  • Вы все еще хотите использовать C ++
  • Ваша цель - не создавать тысячи исключений каждую секунду, просто для удовольствия

Мы должны обсудить STL:

STL будет (если возможно) обычно проверять, что с ним что-то не так. И если вы это сделаете, он бросит исключение. Тем не менее, в C ++ вы обычно не будете платить за то, что не будете использовать.

Примером этого является доступ к векторным данным.

Если вы знаете , вы не выйдете за пределы, тогда вам следует использовать оператор [].

Если вы знаете , вы не будете проверять границы, тогда вам следует использовать метод at ().

Пример A:

typedef std::vector<std::string> Vector ;

void outputAllData(const Vector & aString)
{
   for(Vector::size_type i = 0, iMax = aString.size() ; i != iMax ; ++i)
    {
       std::cout << i << " : " << aString[i] << std::endl ;
    }
}

Пример Б:

typedef std::vector<std::string> Vector ;

void outputSomeData(const Vector & aString, Vector::size_type iIndex)
{
   std::cout << iIndex << " : " << aString.at(iIndex) << std::endl ;
}

Пример «доверяет» программисту, и при проверке не теряется время (и, таким образом, уменьшается вероятность возникновения исключения в это время в случае ошибки в любом случае ... Что обычно означает, что после этого обычно происходит ошибка / исключение / сбой, что не помогает при отладке и позволяет повредить больше данных).

В примере B запрашивается вектор для проверки правильности индекса и, если нет, выдается исключение.

Выбор за вами.

3 голосов
/ 03 октября 2008

Стоит отметить пару моментов:

  • Ваше приложение является многопоточным. Если один поток (возможно, с графическим интерфейсом) замедляется из-за исключения, это не должно влиять на производительность потоков реального времени.

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

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

3 голосов
/ 03 октября 2008

Не бойтесь исключений в отношении производительности.

В старые времена C ++ сборка с включенными исключениями могла быть намного медленнее на некоторых компиляторах.

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

Как правило, STL не генерирует исключения, если у вас не хватает памяти, поэтому это не должно быть проблемой для вашего типа приложения.

(Теперь не используйте язык с GC .....)

1 голос
/ 03 октября 2008

Мне трудно думать, какие части STL указывают, что они могут вызвать исключение. По моему опыту, большая часть обработки ошибок обрабатывается с помощью кодов возврата или как обязательное условие использования STL. Объект, переданный в STL, может вызвать исключение, например, Копировать конструктор, но это будет проблемой независимо от использования STL. Другие упоминали такие функции, как std::vector::at(), но вы можете выполнить проверку или использовать альтернативный метод, обычно, чтобы исключить возможность исключения.

Конечно, конкретная реализация STL может выполнять «проверки», как правило, для отладочных сборок, при использовании вами STL, я думаю, что это вызовет только утверждение, но, возможно, некоторые выльются в исключение.

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

В Visual Studio вы можете отключить использование исключений C ++, см. Project Properties -> C/C++ -> Code Generation -> Enable C++ Exceptions. Я предполагаю, что это доступно на большинстве платформ C ++.

0 голосов
/ 03 октября 2008

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

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