Я думаю, что vector::max_size()
почти всегда является «жестко запрограммированной» вещью - она не зависит от того, сколько памяти система / библиотека готова динамически распределять. Кажется, ваша проблема - ошибка в векторной реализации, которая портит вещи при неудачном выделении.
«Ошибка» может быть слишком сильным словом. vector::resize()
определяется в терминах vector::insert()
, и в стандарте говорится об vector::insert()
:
Если исключение выдается не конструктором копирования или оператором присваивания T, эффекты отсутствуют
Так что, похоже, бывают случаи, когда операции resize()
разрешено повреждать вектор, но было бы неплохо, если бы операция была безопасна для исключений (и я думаю, что было бы нецелесообразно ожидать библиотека, чтобы сделать это, но, возможно, это сложнее, чем я себе представляю).
У вас, кажется, есть пара разумных вариантов:
- изменить или обновить библиотеку, в которой нет ошибки повреждения (какую версию компилятора / библиотеки вы используете?)
- вместо проверки
vector::max_size()
установите nMaxSize
на свой разумный максимум и сделайте то, что у вас выше, но вместо этого используйте этот порог.
Edit:
Я вижу, что вы используете VC6 - определенно есть ошибка в vector::resize()
, которая может иметь какое-то отношение к вашей проблеме, хотя, глядя на патч, я, честно говоря, не вижу как (на самом деле это ошибка в * 1030) *, но, как уже упоминалось, resize()
вызывает insert()
). Я предполагаю, что стоило бы посетить страницу Dinkumwares для исправления ошибок в VC6 и применить исправления.
Проблема также может быть связана с патчем <xmemory>
на этой странице - неясно, что за ошибка там обсуждается, но vector::insert()
вызывает _Destroy()
и vector<>
определяет имя _Ty
так что вы можете столкнуться с этой проблемой. Одна приятная вещь - вам не придется беспокоиться об управлении изменениями заголовков, так как Microsoft никогда больше не трогает их. Просто убедитесь, что исправления попадают в систему контроля версий и документируются.
Обратите внимание, что Скотт Мейерс из "Effective STL" предлагает использовать SGI или STLPort библиотеку, чтобы получить лучшую поддержку STL, чем в VC6. Я этого не делал, поэтому я не уверен, насколько хорошо работают эти библиотеки (но я также не очень часто использовал VC6 с STL). Конечно, если у вас есть возможность перейти на более новую версию VC, обязательно сделайте это.
Еще одно редактирование:
Спасибо за тестовую программу ...
Реализация _Allocate()
в VC6 для распределителя по умолчанию (в <xmemory>
) использует подписанное int для указания количества элементов для выделения, и если переданный размер является отрицательным (что, очевидно, то, что вы делаете - конечно, в тестовой программе вы) функция _Allocate()
устанавливает требуемый размер выделения на ноль и продолжает работу. Обратите внимание, что запрос на распределение нулевого размера будет в большинстве случаев успешным (не то, что vector
в любом случае проверяет наличие сбоя), поэтому функция vector::resize()
весело пытается переместить его содержимое в новый блок, который недостаточно велик. по меньшей мере. Таким образом, куча будет повреждена, она, скорее всего, попадет на недопустимую страницу памяти, и независимо от этого - ваша программа заблокирована.
Итак, суть в том, чтобы VC6 никогда не выделял более INT_MAX
объектов за один раз. Вероятно, не очень хорошая идея в большинстве случаев (VC6 или иначе).
Кроме того, вы должны иметь в виду, что VC6 использует стандартный стандарт возврата 0 из new
, когда выделение завершается неудачей, а не выбрасывает bad_alloc
.