Изменения значения параметра C ++ между кадрами стека в std :: vector - PullRequest
4 голосов
/ 11 января 2009

Я столкнулся с действительно странной ошибкой, которую, надеюсь, кто-нибудь сможет объяснить. У меня есть простой std::vector<V3x>, где V3x - это трехмерный вектор (тип линейной алгебры). Следующий код вызывает исключение std::length_error:

std::vector<V3x> vertices;
int vertexCount = computeVertexCount();
vertices.resize(vertexCount); // throws std::length_error

Я подтвердил, что computeVertexCount() возвращает значение 35, что намного ниже vector::max_size(), поэтому нет никакого способа запросить слишком много памяти.

Я проследил исключение до определения std::vector для следующих двух функций.

void resize(size_type _Newsize, _Ty _Val)
    {   // determine new length, padding with _Val elements as needed
    if (size() < _Newsize)
        // NOTE: here, _Newsize - size() = 35
        _Insert_n(end(), _Newsize - size(), _Val); 
    else if (_Newsize < size())
        erase(begin() + _Newsize, end());
    }

void _Insert_n(const_iterator _Where,
    size_type _Count, const _Ty& _Val)
    {   // insert _Count * _Val at _Where
        // NOTE: here, _Count = 3435973836
        ...
    }

Поэтому, когда параметр _Count передается между resize() и _Insert_n(), значение изменяется с 35 на 3435973836. Я предполагаю, что память каким-то образом испортилась, но я понятия не имею, как это могло быть.

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

Кто-нибудь знает, что может вызвать что-то подобное?

РЕДАКТИРОВАТЬ: РЕШЕНИЕ

нобугз, я могу тебя поцеловать.

Размер std :: vector внутри моего .dll менялся из-за _HAS_ITERATOR_DEBUGGING в VS2008. Поиск привел меня к кому-то с такой же проблемой , и это было исправлено путем добавления следующего в начало моего проекта:

// fix stack corruption errors caused by VS2008
#define _HAS_ITERATOR_DEBUGGING 0
#define _SECURE_SCL 0

Ответы [ 5 ]

21 голосов
/ 11 января 2009

Значение 3435973836 является значимым. В шестнадцатеричном формате это 0xcccccccc. Это значение, назначаемое локальным переменным в режиме отладки кодом инициализации фрейма стека. Когда вы видите это во время отладки, вы говорите «ах, переменная не инициализирована». Может быть, это немного приблизит вас к решению этой проблемы.

Вы упомянули DLL. Это тоже актуально. Отладка итератора может привести к неприятностям, вы не можете смешивать код, который его отключил, с кодом, который этого не делает. Поскольку DLL, вероятно, компилируется без него, попробуйте #define _HAS_ITERATOR_DEBUGGING 0.

2 голосов
/ 11 января 2009

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

Простой способ отладки:

  1. Загрузите вашу программу в отладчик.
  2. Вставить точку останова в первой строке кода в функции-нарушителе.
  3. Выполнять программу, пока она не достигнет точки останова.
  4. Установить часы для переменной, которая неожиданно меняется.
  5. Выполняйте пошаговое выполнение функции, пока не произойдет неожиданное изменение.

Изменение произойдет при записи нераспределенной (или неправильно выделенной) памяти. Целью записи является ошибочная переменная.

0 голосов
/ 11 января 2009
0 голосов
/ 11 января 2009

Я предлагаю рассмотреть параметры C ++, настроенные для вовлеченных проектов. Убедитесь, что все они имеют одинаковые настройки выравнивания и времени выполнения. Вы строите .DLL участвует?

0 голосов
/ 11 января 2009

опубликованный код верен, и вы можете предположить, что в std :: vector нет ошибок. повторить исключение в самой чистой возможной среде (новый пустой проект). может ли это быть что-то глупое , как это в ComputeVertexCount ()?

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