Подскажите пожалуйста, почему может возникать исключение bad_alloc при выполнении такого простого кода:

Уважаемые форумчане! Работаю над программой обработки WAV файлов, но возникла такая проблема: при.
Ошибка terminate called after throwing an instance of ‘std::bad_alloc’ what(): std::bad_alloc
Добрый день!Работаю с графами,и при больших значениях столкнулся с проблемой:ошибка в тесте.

При выполнении программы, которая миксует функции в которых создаются типовые задачи, вылезает.
Ошибка terminate called after throwing an instance of ‘std::bad_alloc’ what(): std::bad_alloc
Есть задача: Написать программу, которая считывает текст из файла и выводит его на экран, заменив.
Решение
Все так и оказалось, изменил на x64, заполнились все 16 Гб памяти.
Это не логично, логичнее убивать сам сценарий/контекст или поток.
К тому же все равно прорисовка делается та в одном окне, непонятно как с ним синхронизируются процессы.
Добавлено через 1 минуту
Это вообще как странно звучит. Не давай полномочий и не нужно будет думать о защите.
Добавлено через 15 секунд
Кроме того, как я уже говорил, когда все вкладки браузера находятся в одном адресном пространстве гораздо проще получить несанкционированный доступ к данным. В одном вкладке открыт какой-нибудь онлайн банк, а в соседней сайт злоумышленника, со зловредным скриптом, который ворует данные первой вкладки. Гипотетически сделать это проще, потому что все данные в одном адресном пространстве.
Как бороться с плохим аллоком в C++?
существует метод под названием foo это иногда возвращает следующую ошибку:
если да, то каков его синтаксис?
как еще я могу иметь дело с bad_alloc в C++?
6 ответов
вы можете поймать его, как и любое другое исключение:
то, что вы можете с пользой сделать с этого момента, зависит от вас, но это определенно возможно технически.
В общем не может и не стоит чтобы ответить на эту ошибку. bad_alloc указывает, что ресурс не может быть выделен, поскольку недостаточно памяти. В большинстве сценариев ваша программа не может надеяться справиться с этим, и прекращение вскоре является единственным значимым поведением.
хуже того, современные операционные системы часто чрезмерно выделяют: malloc и new всегда будет возвращать допустимый указатель, даже если технически нет (или недостаточно) свободная память осталась-так std::bad_alloc никогда не будет выброшен, или, по крайней мере, не является надежным признаком истощения памяти. Вместо этого пытается открыть выделенная память приведет к ошибке, которая не может быть уловлена.
единственное, что вы могли бы сделать при ловле std::bad_alloc возможно, зарегистрировать ошибку и попытаться обеспечить безопасное завершение программы, освободив выдающиеся ресурсы (но это делается автоматически в обычном процессе размотки стека после получения ошибки бросается, если программа использует RAII соответствующим образом).
в некоторых случаях программа может попытаться освободить память и повторить попытку или использовать вторичную память (= диск) вместо ОЗУ, но эти возможности существуют только в очень конкретных сценариях.
каково стандартное поведение c++ new в c++?
C++03 Раздел 3.7.4.1.3: говорит
функция распределения, которая не может выделить хранилище, может вызвать установленный в настоящее время new_handler(18.4.2.2), если таковой имеется. [Примечание: предоставленная программой функция распределения может получить адрес текущего установленного new_handler с помощью функции set_new_handler (18.4.2.3).] Если функция распределения, объявленная с пустой спецификацией исключения (15.4), throw (), не выделяет хранилище, она должна возвращать нулевой указатель. Любая другая функция распределения, которая не выделяет хранилище, должна указывать только на сбой, вызывая исключение класса std:: bad_alloc (18.4.2.1) или класс, производный от std::bad_alloc.
рассмотрим следующий пример кода:
В приведенном выше примере operator new (скорее всего) не сможет выделить место для 100,000,000 целых чисел, а функция outOfMemHandler() будет вызван, и программа будет прервана после выдача сообщения об ошибке.
параметр set_new_handler является указателем на оператор функции new должны позвонить, если он не может выделить память. Его возвращаемое значение является указателем на ранее зарегистрированную функцию обработчика или null, если не было предыдущий обработчик.
как обрабатывать из условий памяти в C++?
учитывая поведение new хорошо разработанная пользовательская программа должна обрабатывать условия из памяти, предоставляя правильный new_handler который делает одно из следующего:
сделать больше доступной памяти: это может позволить следующей попытке выделения памяти внутри цикла оператора new добиться успеха. Один из способов реализовать это-выделить большой блок памяти в программе запуск, затем отпустите его для использования в программе при первом вызове нового обработчика.
установите другой новый обработчик: если текущий новый обработчик не может сделать больше доступной памяти, и есть другой новый обработчик, который может, то текущий новый обработчик может установить другой новый обработчик на свое место (путем вызова set_new_handler ). В следующий раз, когда оператор new вызовет функцию new-handler, он получит самую последнюю установленную.
(A вариация на эту тему для нового обработчика, чтобы изменить свое собственное поведение, поэтому в следующий раз, когда он вызывается, он делает что-то другое. Один из способов добиться этого-заставить новый обработчик изменять статические, специфические для пространства имен или глобальные данные, влияющие на поведение нового обработчика.)
bad alloc — ошибки выделения памяти в C ++ без использования новых
У меня проблемы с моей программой, вызывающей большое количество исключений выделения памяти, и мне очень трудно диагностировать проблему … Я бы опубликовал код, но моя программа очень большая, и у меня есть проблемы с частной информацией, поэтому я в надежде получить помощь без публикации кода. Если вы планируете ответить с помощью какой-либо формы комментария SSCCE, просто прекратите читать сейчас и сэкономите нам обоим некоторое время. Это тот случай, когда я не могу опубликовать краткий код — я постараюсь быть максимально ясным и лаконичным с описанием моей проблемы и некоторыми конкретными вопросами.
Фон программы — моя программа в основном обработчик данных. Он принимает в качестве входных данных несколько таблиц данных, выполняет для них вычисления и выводит новые таблицы данных на основе результатов расчетов. Все мои структуры данных являются пользовательскими классами (состоящими из типов int, double и string с векторными контейнерами для массивов). Во всех случаях я инициирую экземпляры переменных класса без использования new и delete.
описание проблемы — моя программа компилируется без предупреждений и отлично работает на небольших наборах данных. Однако, как только я увеличиваю набор данных (с массива 20×80 до 400×80), я начинаю выдавать исключения bad_alloc (как только я обработал первые 35 записей или около того). Большие наборы данных работают нормально в 17 из моих 18 модулей — я выделил одну функцию, где происходят ошибки. Расчеты, необходимые для этой функции, приведут к созданию около 30 000 строк данных, тогда как другие функции в моем коде генерируют более 800 000 строк без инцидентов.
Единственный реальный уникальный атрибут в этом модуле — это то, что я много использую изменение размера (примерно 100 раз за вызов функции), и что функция использует рекурсивные циклы во время операции изменения размера (функция выделяет квадратные футы из здания одного арендатора в время, а затем обновление оставшихся футов, которые должны быть распределены после моделирования размера и продолжительности аренды каждого арендатора, пока не будут выделены все квадратные футы). Кроме того, ошибка происходит почти в одном и том же месте каждый раз (но не в одном и том же месте, потому что у меня есть генератор случайных чисел, который вносит некоторые изменения в результаты). Что меня действительно смущает, так это то, что первые
34 вызова этой функции работают нормально, и вызов
35 не требует больше памяти, чем предыдущие 34, но у меня все же есть эти исключения bad_alloc для 35-го вызова …
Я знаю, что трудно помочь без кода. Пожалуйста, просто попробуйте указать мне направление. Мои конкретные вопросы следующие:
Если я не использую «new» и «delete», и все мои переменные инициализируются ВНУТРИ локальных функций, возможно ли возникновение проблем утечки / выделения памяти из-за повторных вызовов функций? Есть ли что-нибудь, что я могу или должен сделать, чтобы управлять памятью при инициализации переменных, включающих локальную функцию, используя «vector Instance;» объявить мои переменные?
Есть ли вероятность того, что у меня не хватает памяти стека, если я делаю всю программу через стек? Возможно ли мне загрузить некоторые из моих больших таблиц поиска (карты и т. Д.) В кучу, а затем просто использовать стек для моих итераций, где важна скорость?
Есть ли проблема с использованием изменения размера, связанного с памятью? Может ли это быть случай, когда я должен использовать «new» и «delete» (во многих случаях меня предупреждали не использовать их, если нет очень веской, конкретной причины для этого)?
Любые мысли будут оценены. Я могу попытаться опубликовать некоторый код, но я уже пробовал это однажды, и все, казалось, были отвлечены тем фактом, что он не компилируется. Я могу опубликовать соответствующую функцию, но она сама не компилируется.
Вот класс, который вызывает проблему:
Кроме того, вот фрагмент из функции, где происходит рекурсия
Решение
Если ваши программы не используют много памяти в куче (поэтому они не исчерпывают кучу), bad_alloc Скорее всего, они вызваны повреждением кучи, которое обычно вызывается использованием висячих указателей в куче.
Вы упоминаете, что ваш код делает много resize операции — resize в большинстве коллекций аннулирует все итераторы в коллекции, поэтому, если вы повторно используете любой итератор после resize что может привести к куче коррупции bad_alloc исключения. Если вы используете непроверенный доступ к элементам вектора ( std::vector::operator[] ), и ваши индексы находятся вне диапазона, что также может привести к повреждению кучи.
Лучший способ отследить повреждение кучи и ошибки памяти в целом — использовать отладчик кучи, такой как Valgrind
Другие решения
Классы как std::vector а также std::string разрешено бросать bad_alloc или другие исключения. В конце концов, они должны использовать некоторую память, которая исходит откуда-то, и на любом компьютере достаточно памяти.
Операции-деструкторы, определенные в стандартной библиотеке C ++, не должны вызывать исключения. Каждый деструктор в стандартной библиотеке C ++ должен вести себя так, как если бы у него была спецификация без исключения. Любые другие функции, определенные в стандартной библиотеке C ++, которые не имеют Исключение-спецификация может генерировать определенные реализацией исключения, если не указано иное. [Сноска 1] Реализация может усилить это неявное Исключение-спецификация добавив явный.
Сноска 1: В частности, они могут сообщить об ошибке при выделении памяти, выдав исключение типа bad_alloc или класс, полученный из bad_alloc (18.6.2.1). Реализации библиотеки должны сообщать об ошибках, генерируя исключения или получаемые из стандартных классов исключений (18.6.2.1, 18.8, 19.2).
Если я не использую «new» и «delete», и все мои переменные инициализируются ВНУТРИ локальных функций, возможно ли возникновение проблем утечки / выделения памяти из-за повторных вызовов функций?
Неясно. Если все переменные, на которые вы ссылаетесь, являются локальными, нет. Если вы используете malloc (), calloc () и free (), да.
Есть ли вероятность того, что у меня не хватает памяти стека, если я делаю всю программу через стек?
Нет, если вы получите bad_alloc. Если вы получили ошибку «переполнение стека», да.
Возможно ли мне загрузить некоторые из моих больших таблиц поиска (карты и т. Д.) В кучу, а затем просто использовать стек для моих итераций, где важна скорость?
Что ж, трудно поверить, что вам нужна локальная копия таблицы поиска в каждом кадре стека рекурсивного метода.
Есть ли проблема с использованием изменения размера, связанного с памятью?
Конечно. Вы можете убежать.
Может ли это быть случай, когда я должен использовать «новый» и «удалить»
Сегодня невозможно, не зная больше о ваших структурах данных.
(Во многих случаях меня предупреждали не использовать их, если для этого нет очень веской, конкретной причины)?
Внутри проблемной функции я создаю переменную класса,
Вы создаете экземпляр класса в стеке. Я думаю. Просьба уточнить.
затем перезаписываю эту переменную около 20 раз (один раз для каждой «итерации» моей модели).
С заданием? Есть ли в классе оператор присваивания? Это правильно? Использует ли сам класс кучную память? Правильно ли он распределяется и удаляется при строительстве, разрушении и назначении?
Поскольку, как вы сказали, вы используете std::vector с распределителем по умолчанию, проблема возникает, когда вы используете много std::vector::resize(. ) и это происходит после нескольких итераций, я думаю, что вы столкнулись с проблемой фрагментации кучи.
Что такое исключение? Это ситуация, которая не предусмотрена стандартным поведением программы. Например, попытка доступа к элементу в классе Vector (который мы разбирали в статье про классы ), который не существует. То есть происходит выход за пределы вектора. В данном случае можно воспользоваться исключениями, чтобы прервать выполнение программы. Это необходимо потому, что
Для разрешения таких ситуация в C++ можно использовать технику исключений.
Рассмотрим, как написать вызов исключения в случае попытки доступа к элементу по индексу, который не существует в классе Vector.
Здесь применяется исключение out_of_range. Данное исключение определено в заголовочном файле .
Инварианты
Также блоки try catch позволяют производить обработку нескольких различных исключений, что вносит инвариантность в работу механизма исключений C++.
Например, класс вектор при создании может получить неправильный размер вектора или не найти свободную память для элементов, которые он будет содержать.
Данный конструктор может выбросить исключение в двух случаях:
Обработка исключений будет выглядеть следующим образом:
Также можно выделить свои собственные исключения.
Виды исключений
Все исключения стандартной библиотеки наследуются от std::exception.
На данный момент существуют следующие виды исключений:
std::logic_error
Исключение определено в заголовочном файле
Определяет тип объекта, который будет брошен как исключение. Он сообщает об ошибках, которые являются следствием неправильной логики в рамках программы, такие как нарушение логической предпосылки или класс инвариантов, которые возможно предотвратить.
Этот класс используется как основа для ошибок, которые могут быть определены только во время выполнения программы.
std::invalid_argument
Исключение определено в заголовочном файле
Наследован от std::logic_error. Определяет исключение, которое должно быть брошено в случае неправильного аргумента.
Например, на MSDN приведён пример, когда в объект класса bitset из стандартной библиотеки
В данном примере передаётся неправильная строка, внутри которой имеется символ ‘b’, который будет ошибочным.
std::domain_error
Исключение определено в заголовочном файле
Наследован от std::logic_error. Определяет исключение, которое должно быть брошено в случае если математическая функция не определена для того аргумента, который ей передаётся, например:
std::length_error
Исключение определено в заголовочном файле
Наследован от std::logic_error. Определяет исключение, которое должно быть броше в том случае, когда осуществляется попытка реализации превышения допустим пределов для объекта. Как это было показано для размера вектора в начале статьи.
std::out_of_range
Исключение определено в заголовочном файле
Наследован от std::logic_error. Определяет исключение, которое должно быть брошено в том случае, когда происходит выход за пределы допустимого диапазона значений объекта. Как это было показано для диапазона значений ветора в начале статьи.
std::future_error
Исключение определено в заголовочном файле
std::runtime_error
Исключение определено в заголовочном файле
Является базовым исключением для исключений, которые не могут быть легко предсказаны и должны быть брошены во время выполнения программы.
std::range_error
Исключение определено в заголовочном файле
std::overflow_error
Исключение определено в заголовочном файле
Исключение используется при ошибках при вычислении значений с плавающей запятой интегрального типа, когда число имеет слишком большое положительное значение, положительную бесконечность, при которой происходит потеря точности, т.е. результат настолько большой, что не может быть представлен числом в формате IEEE754.
std::underflow_error
Исключение определено в заголовочном файле
Исключение используется при ошибках при вычислении значений с плавающей запятой интегрального типа, при которой происходит потеря точности, т.е. результат настолько мал, что не может быть представлен числом в формате IEEE754.
std::system_error
Исключение определено в заголовочном файле
std::ios_base::failure
Исключение определено в заголовочном файле
Отвечает за исключения, которые выбрасываются при ошибках функций ввода вывода.
std::bad_typeid
Исключение определено в заголовочном файле
Исключение этого типа возникает, когда оператор typeid применяется к нулевому указателю полиморфного типа.
std::bad_cast
Исключение определено в заголовочном файле
Данное исключение возникает в том случае, когда производится попытка каста объекта в тот тип объекта, который не входит с ним отношения наследования.
std::bad_weak_ptr
Исключение определено в заголовочном файле
std::bad_function_call
Исключение определено в заголовочном файле
std::bad_alloc
Исключение определено в заголовочном файле
Вызывается в том случае, когда не удаётся выделить память.
std::bad_array_new_length
Исключение определено в заголовочном файле
Исключение вызывается в следующих случаях:
std::bad_exception
Исключение определено в заголовочном файле
Рекомендуем хостинг TIMEWEB
Рекомендуемые статьи по этой тематике
Как бороться с bad_alloc в C ++?
Если так, какой синтаксис для этого?
Как еще я могу иметь дело с bad_alloc в C++?
Вы можете поймать это как любое другое исключение:
То, что вы можете сделать с этой точки зрения, зависит от вас, но технически это определенно возможно.
В общем, вы не можете и не должны пытаться ответить на эту ошибку. bad_alloc означает, что ресурс не может быть выделен, так как недостаточно памяти. В большинстве сценариев ваша программа не может надеяться справиться с этим, и прерывание в ближайшее время является единственным значимым поведением.
В некоторых случаях программа может попытаться освободить часть памяти и повторить попытку, или использовать вторичную память (= диск) вместо RAM), но эти возможности существуют только в очень специфических сценариях.
Каково стандартное поведение C++ для new в c ++?
Обычно считается, что если оператор new не может выделить динамическую память запрошенного размера, он должен вызвать исключение типа _ std::bad_alloc _.
Однако что-то еще происходит еще до того, как возникнет исключение _ bad_alloc _:
C++ 03 Раздел 3.7.4.1.3: говорит
Функция выделения, которая не может выделить хранилище, может вызвать установленный в данный момент new_handler (18.4.2.2), если таковой имеется. [Примечание: предоставляемая программой функция выделения может получить адрес установленного в данный момент new_handler с помощью функции set_new_handler (18.4.2.3).] Если функция выделения объявлена с пустой спецификацией исключений (15.4), throw () завершается неудачно выделить память, он должен вернуть нулевой указатель. Любая другая функция выделения, которая не может выделить хранилище, должна указывать на сбой только путем генерирования исключения класса std :: bad_alloc (18.4.2.1) или класса, производного от std :: bad_alloc.
Рассмотрим следующий пример кода:
Что такое _ new_handler _ и _ set_new_handler _?
Как справиться с условиями памяти в C++?
Сделать доступной больше памяти: Это может позволить следующей попытке выделения памяти внутри цикла оператора new завершиться успешно. Одним из способов реализации этого является выделение большого блока памяти при запуске программы, а затем освобождение его для использования в программе при первом вызове нового обработчика.
Удалите новый обработчик: Это делается путем передачи нулевого указателя на _ set_new_handler _. Если не установлен новый обработчик, _ operator new _ сгенерирует исключение ((преобразуемое в) _ std::bad_alloc _), если выделение памяти окажется неудачным.




