Правило без исключений из руководства по стилю Google C ++;STL? - PullRequest
65 голосов
/ 03 марта 2011

Руководство по стилю Google C ++ гласит: «Мы не используем исключения».Стиль не упоминает STL в отношении использования исключения.Поскольку распределители STL могут давать сбой, как они обрабатывают исключения, генерируемые контейнерами?

  1. Если они используют STL, как вызывающая сторона информируется о сбоях выделения?Методы STL, такие как push_back() или map operator[], не возвращают никаких кодов состояния.
  2. Если они не используют STL, какую реализацию контейнера они используют?

Ответы [ 7 ]

53 голосов
/ 03 марта 2011

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

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

Обычная проблема наследства. : - (

42 голосов
/ 22 марта 2013

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

Я был инженером в Google Search, работающем в C ++ с 2008 года. Мы часто используем контейнеры STL. Лично я не могу вспомнить ни одного серьезного сбоя или ошибки, которая когда-либо была связана с ошибкой vector :: push_back () или map :: operator [], когда мы говорили: «о человек, мы должны переписать этот код, потому что распределение может fail »или« dang, если бы мы только использовали исключения, этого можно было бы избежать ». Процессу не хватает памяти? Да, но это, как правило, простая ошибка (например, кто-то добавил в программу большой новый файл данных и забыл увеличить объем оперативной памяти) или катастрофический сбой, когда нет хорошего способа восстановления и продолжения. Наша система уже автоматически управляет и перезапускает задания для обеспечения их работоспособности на машинах с неисправными дисками, космическими лучами и т. Д., И это на самом деле ничем не отличается.

Итак, насколько я могу судить, здесь нет проблем.

11 голосов
/ 03 марта 2011

Я почти уверен, что они означают, что не используют исключения в их коде. Если вы проверите их сценарий cpplint , он проверяет, правильно ли вы включили заголовки для контейнеров STL (например, vector, list и т. Д.).

6 голосов
/ 16 сентября 2013

Вы не можете обрабатывать сбои выделения в современных операционных системах; в качестве оптимизации производительности они обычно перезаписывают память. Например, если вы позвоните по номеру malloc() и попросите действительно огромный кусок памяти в Linux, он преуспеет , даже если памяти, необходимой для его поддержки, на самом деле нет . Только когда вы обращаетесь к нему, ядро ​​фактически пытается выделить страницы для его поддержки, и в этот момент уже слишком поздно говорить вам, что распределение все равно не удалось.

Итак:

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

  2. Тем не менее, рекомендуется перехватывать необработанные исключения и регистрировать вывод e.what(), а затем повторно throw, поскольку это может быть более информативным, чем обратная трассировка, и типичные реализации библиотеки C ++ этого не делают автоматически для вас.

  3. Весь огромный поток выше о том, что вы не можете рассчитывать на сбой при исчерпании памяти, является полным и полным мусором. Стандарт C (++) может не гарантировать этого, но при современных сбоях систем - это only , на которую вы можете положиться, если у вас не хватает памяти . В частности, вы не можете рассчитывать на получение NULL или любого другого указания от вашего распределителя, вплоть до исключения C ++.

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

Я уточню вышесказанное, сказав, что, возможно, вы используете какой-то пользовательский распределитель или что вы находитесь в системе, которая не выполняет чрезмерную фиксацию (в качестве примера можно привести встроенные системы без swap, но не единственный пример). В этом случае, возможно, , вы сможете корректно справиться с нехваткой памяти, в вашей системе . Но в целом в XXI веке я боюсь, что вы вряд ли получите шанс; первое, что вы узнаете, что вашей системе недостаточно памяти, - это когда вещи начинают падать.

6 голосов
/ 01 апреля 2013

Я обнаружил, что Google прямо упоминает это о STL и исключениях (выделение мое):

Хотя вы не должны использовать исключения в своем собственном коде, они широко используются в ATL и некоторыхSTL, включая тот, который поставляется с Visual C ++.При использовании ATL вы должны определить _ATL_NO_EXCEPTIONS, чтобы отключить исключения.Вы должны выяснить, можете ли вы также отключить исключения в своем STL, но если нет, то можно включить исключения в компиляторе.(Обратите внимание, что это только для того, чтобы заставить STL компилироваться. Вы все равно не должны сами писать код обработки исключений. )

Мне не нравитсятакие решения (повезло, что я не работаю на Google), но они совершенно ясно о своем поведении и намерениях.

4 голосов
/ 25 декабря 2013

Сам Stl напрямую выбрасывает только в случае сбоя выделения памяти.Но обычно приложение реального мира может выйти из строя по разным причинам, сбой выделения памяти - только одна из них.В 32-битных системах сбой выделения памяти - это не то, что следует игнорировать, так как это может произойти.Таким образом, все обсуждение выше, что сбой выделения памяти не произойдет, является бессмысленным.Даже предполагая это, нужно было бы написать свой код, используя двухэтапную инициализацию.А обработка исключений в C ++ уже давно предшествует 64-битной архитектуре.Я не уверен, как далеко я должен пойти в достоинстве отрицательного профессионализма, показанного здесь Google, и только ответить на заданный вопрос.Я помню статью от IBM примерно в 1997 году, в которой говорилось о том, насколько хорошо некоторые сотрудники IBM понимали и оценили последствия обработки исключений в C ++.ОК, профессионализм не является необходимым показателем успеха.Таким образом, отказ от обработки исключений является не только проблемой, если использовать STL.Это проблема, если кто-то использует C ++ как таковой.Это означает отказ от

  • ошибки конструктора
  • возможности использовать объекты-члены и объекты базового класса в качестве аргументов для любого из следующих конструкторов базового / членского класса (без какого-либо тестирования).Неудивительно, что люди использовали двухэтапное построение до того, как появилась обработка исключений в C ++.
  • отказались от иерархических и богатых сообщений об ошибках в среде, которая позволяет предоставлять код клиентам или третьим сторонам и генерировать ошибки, которыеоригинальный автор вызывающего кода не мог предвидеть это при написании вызывающего кода и мог бы предоставить пространство для в своем диапазоне кодов возврата.
  • избегает таких хаков, как возвращение указателя на объект статической памяти на сообщениеошибка выделения памяти, которую авторы FlexLm
  • смогли использовать, используя распределитель памяти, возвращающий адреса в разреженный файл памяти.В этом случае сбой выделения происходит, когда кто-то обращается к рассматриваемой памяти. (Хорошо, в настоящее время это работает только на Windows, но Apple вынудила команду gnu предоставить необходимую функциональность в компиляторе G ++. Потребуется дополнительное давление со стороны разработчика Linux g ++, чтобы обеспечитьэта функциональность также для них) (упс - это даже относится к STL)
  • возможность оставить за собой эту кодировку в стиле C (игнорируя возвращаемые значения) и необходимость использовать отладчик с исполняемым файлом отладки, чтобы выяснить эточто не удается в нетривиальной среде с дочерними процессами и общими библиотеками, предоставленными сторонними разработчиками, или выполняющими удаленное выполнение
  • , которые могут возвращать вызывающей стороне расширенную информацию об ошибках, не просто выгружая все в stderr
2 голосов
/ 08 марта 2011

Существует только одна возможность обработать сбой выделения при предположениях, изложенных в вопросе:

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

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

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