2012-02-19 4 views
2

Хорошо, я уверен, что это просто до неузнаваемости статического анализатора кода в Visual Studio, но я решил, что больше на него смотреть не повредит.VS2010 Ошибка анализа статического кода?

Я написал собственную коллекцию контейнеров в векторном стиле. Они, кажется, работают нормально, но я заметил следующие предупреждения от Visual Studio статического анализатора кода:

предупреждение C6386: Переполнение буфера: обращающегося «аргумент 1», то записываемый размер «Newspace * 4» байтов , но могут быть записаны байты «4194240».

Вышеуказанное предупреждение появляется в последней строке следующего кода (memcpy) и выделяет все предыдущие строки. Все возможные типы, которые может иметь этот конкретный векторный класс, - POD. mSpace содержит количество элементов, которые может иметь доступная память в векторе, и mSize Текущее количество товаров. mDynamic указывает на блок памяти, который в настоящее время управляется вектором.

Bool Insert(UInt32 index, TYPE value, UInt32 count = 1) 
{ 
    if(index < mSize) 
    { 
     UInt32 newsize = mSize + count; 

     if(newsize > mSpace) 
     { 
      UInt32 newspace = std::max(Align(newsize, 8), mSpace << 1); 
      TYPE* ptr = new TYPE[ newspace ]; 

      if(ptr) 
      { 
       memcpy(ptr, mDynamic, index * sizeof(TYPE)); 
       // The remainder of the code copies the second half of the 
       // existing data and inserts the new values... 

Я никогда смотрел на это, пока мой глаз обрез (ну, почти) и не может понять, почему анализатор будет генерировать предупреждение. Я видел то же предупреждение в других местах и ​​с довольно странным значением 4194240, поэтому я предполагаю, что это еще одна ошибка в анализаторе.

Может кто-нибудь подтвердить, что это известная ошибка в анализаторе (очень быстрый поиск соединения не дал никаких результатов), или есть явная ошибка в моем коде, которую я просто не вижу?

+0

4194240 - 2^22 - 2^6. Не уверен, что это релевантно ... –

+0

Похож на довольно ложное предупреждение для меня ... Предупреждает ли это предупреждение только при создании экземпляра определенного типа? Например, будет ли это отображаться, если вы изолируете свой класс в проекте без клиентов? –

+0

И, возможно, попробуйте запустить свой код через другой инструмент [http://stackoverflow.com/questions/141498/what-open-source-c-static-analysis-tools-are-available) ... –

ответ

0

Не уверен, что это связано с предупреждением, но здесь вы указали ошибку. Если mSize равен 2^32 - 1, то для Newsize будет установлено значение 0 из-за переполнения целых чисел, которое закончится переполнением буфера. Аналогичная ошибка возникает, когда вы делаете index * sizeof(TYPE), не проверяя, что результат будет соответствовать 32 битам.

Более незначительный, но вы действительно должны использовать size_t, а не UInt32, в противном случае, если вы хотите скомпилировать 64-битном вы будете иметь предупреждение о типах не совпадающих по размерам тетсра занимает size_t в качестве 3-го аргумента, и size_t является 64 бит на 64-битной Windows.

+0

На самом деле, я столкнулся с ошибками переполнения задолго до того, как mSize ударит 2^32-1. (Вероятно, примерно в то время, когда mSize * sizeof (TYPE) достигает 2^32.) К тому времени, хотя у меня будет много других проблем, таких как отсутствие памяти для кода. ;) На самом деле в Windows XP довольно сложно выделить единую память объемом около 700 МБ сразу после запуска вашего процесса. Это число несколько увеличивается в Vista/7, но оно все еще нигде не приближается к 32-разрядному предельному адресу. –

+0

Что касается 64-битного, я строил на Win64, так как первые 64-битные компиляторы были доступны от Microsoft. Использование size_t - это то, что я избегаю, когда могу.Мне пришлось исправлять слишком много ошибок от других людей, где они смешали size_t с int с веселыми последствиями (в основном из ожиданий файлов и сетевых подключений, чтобы магически все еще работать в разных архитектурах). Добавьте к этому тот факт, что 64-разрядные типы требуют двойной памяти без уважительной причины (я не * нуждаюсь в 64-битных размерах здесь), и факт, что 64-битные инструкции префиксны на AMD64, что также излишне увеличивает размер кода. –