2010-03-20 1 views
26

У меня есть довольно серьезная ошибка в моей программе - случайные вызовы new() throw bad_alloc.Стратегия отладки, чтобы найти причину bad_alloc

Из документации можно найти на bad_alloc, это, кажется, брошена по этим причинам:

  1. Когда компьютер работает из памяти (что, безусловно, не происходит, у меня есть 4 Гб оперативной памяти, программа бросает bad_alloc при использовании менее 5 МБ (проверяется в taskmanager), ничего серьезного не работает в фоновом режиме).

  2. Если память становится слишком фрагментированной, чтобы выделять новые блоки (что, опять же, маловероятно), блок наибольшего размера, который я когда-либо выделял, был бы около 1 КБ, и это не будет сделано более 100 раз, прежде чем произойдет сбой).

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

Однако приложение, в котором выполняется приложение, запускает более одного потока, что может быть связано с проблемой. Проверяя все объекты в одном потоке, все работает нормально. Единственное, что я могу подумать об этом, это может быть какое-то гоночное условие, вызванное вызовом new() в нескольких местах одновременно, но я попытался добавить мьютексы, чтобы предотвратить это поведение нет эффекта.

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

Я использую Microsoft Visual Studio 2008 с Poco для потоковой передачи.

ответ

16

Другая возможная проблема заключается в том, что, в то время как вы говорите, что программа использует меньше, чем 5MB, не говоря уже о том, сколько места он пытается выделить. У вас может быть какое-то состояние гонки, которое искажает значение, которое вы используете для определения размера распределения, и оно может пытаться выделить 37 ТБ или что-то бессмысленное.

Не особенно вероятно, я полагаю, но стоит проверить.

+0

На самом деле это была проблема ... не знаю, где именно была проблема, но есть много искалеченных переменных, блуждающих по странным местам - похоже, что где-то было условие гонки. Спасибо! – Salami

+0

Это было мое дело ... Я думал, что я вызываю 'new char [_len]', но я вызывал 'new char [len]', когда 'len' еще не был инициализирован, поэтому, вероятно, какое-то огромное количество. Это действительно помогло задуматься о том, сколько пространства я прошу и посмотреть на ценности ближе. Спасибо за ответ. – flcoder

3

Несколько уточнений:

Каждый процесс в окнах получает виртуальную память 4 Гб, из которых 2 Гб для пользовательского пространства и остальные для пространства ядра. 4 ГБ оперативной памяти не будет вносить вклад в виртуальную память, но она предназначена для физической памяти.

В памяти 2 ГБ загружается вся EXE, DLL и почти 1,6 - 1,7 ГБ для распределения памяти. В этой памяти, если для выделения нет смежной памяти, распределение памяти не выполняется.

+0

Знаете ли вы о системах linux/unix, сколько они выделяют? – anish

20

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

Наиболее распространенной причиной этого является то, что вы пишете прошлое до конца выделенного блока памяти (или до начала, но это менее распространено). Почти так же часто записывается блок памяти после его освобождения. Это называется кучевой коррупцией.

Также следует отметить, что 32-разрядный процесс в Windows имеет не более 2 ГБ адресного пространства (3 ГБ для программ с большим адресом). Это независимо от того, сколько оперативной памяти вы установили, память виртуальная, а распределение не прерывается, пока вы не исчерпали адресное пространство, даже если у вас всего 1 ГБ ОЗУ.

Вот хорошее обсуждение коррупции памяти в C++ http://www.eventhelix.com/RealtimeMantra/Basics/debugging_software_crashes_2.htm

+0

Благодарим вас за информацию здесь. – Salami

1

bad_alloc может быть выброшен другим кодом.

Я видел, как он использовался ограниченным пулом памяти, предназначенным для использования с контейнерами STL. Когда предел размера был поражен, он бросил bad_alloc, и программное обеспечение просто должно было его обработать.

0

У меня на самом деле была эта проблема раньше, и это было исправлено путем очистки и восстановления проекта. Всегда стоит попробовать, когда у вас странное поведение (если это не огромный проект, требующий много времени для компиляции).