Visual Studio не может показать значение std :: string - PullRequest
0 голосов
/ 16 января 2020

В компании, в которой я работаю, на некоторых из нас повлияла ошибка / ошибка в Visual Studio. Отладчику не удается отобразить значение / содержимое std :: string. Он говорит: «Ошибка чтения символов строки.»

Некоторые фотографии проблемы: Простые строковые переменные Значения в отладчике

Следующая строка будет всегда воспроизводить проблему, но, как правило, каждая строка в коде (по крайней мере, ~ 1'000'000 строк) будет иметь проблему.

std::string testVar = "Something";

Редактировать: Попытка сделать минимальный воспроизводимый пример в ближайшее время, но сейчас я не могу сделать один. Проблема возникает только в одном решении, состоящем из 93 проектов. До сих пор пробовал: Новое решение с той же версией компилятора (v120), любой версией компилятора, одинаковыми определениями препроцессора, VS2013 и VS2017 (обе проблемы возникают в Professional и Enterprise). Теперь устанавливаю VS2019, чтобы протестировать его.

Я строю строку из const char *, так что это, вероятно, не имеет ничего общего с распределением памяти, et c ... И, самое главное, код работает. Итак, сама std :: string работает так, как должна, но отладчик не может показать ее значения. Размер правильный, насколько я вижу, но емкость всегда 0x cccccccccccccccc. Для символов в строке написано: «Невозможно прочитать память». Подробное представление строки в отладчике

Эта проблема возникает только с std :: string, а не с std :: wstring или char * или чем-либо еще. Кроме того, когда я открываю новое решение, std :: string будет отображаться правильно. Он не отображается только в решении с более чем 91 проектом. Воспроизводится в VS2017 и VS2013, но мы используем компилятор v120. Пробовал константные переменные и имел переменную в куче или в стеке, это не имеет значения.

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

Эта ошибка присутствует с этой недели, мы не могли наблюдать ничего подобного раньше или даже больше, чем за неделю go. У 3 из нас есть эта проблема, но у некоторых других нет. Мы все работаем в основном на одних и тех же машинах с одинаковыми настройками и обновлениями. Единственное отличие состоит в том, что рабочая VS - это Professional, и мы используем версию Enterprise.

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

Редактировать: Может быть важно, что при отладке с помощью пошаговых инструкций отладчик не входит в конструктор или любую из функций std :: string (в xstring), он просто переходит это как бы простое присваивание переменной int, а не вызов функции. Но установка точки останова в исходном коде std :: string на самом деле будет работать, и отладчик на этом остановится.

EDIT2 - найдена причина ошибки, но пока нет реального решения

После анализа значений указателей в std :: string я обнаружил, почему отладчику не удается извлечь строку. Отладчик ищет его со смещением +8 байт. Чтобы объяснить это: допустим, я создал std :: string и получил его указатель.

std::string testStr = "test";
std::string* strPtr = &testStr;

Затем strPtr = 0x0000000001bdf4a8. Теперь, когда я смотрю в окно «Локальные» отладчика, смотрю необработанное представление строки и нахожу указатель в объединении _Bx, то: _Buf = 0x0000000001bdf4b0 Это strPtr + 8. Вот почему он не может декодировать содержимое строки. потому что он пытается интерпретировать это не по адресу. Если бы я сделал это:

std::string* fixedStr = reinterpret_cast<std::string*>(reinterpret_cast<char*>(&testStr)-8);

Итак, когда я вручную уменьшу указатель на 8 байт и преобразую его в строку, отладчик будет правильно отображать его содержимое. (Конечно, эта строка повреждена и не будет работать, только отображение отладчика исправлено)

Когда я открываю новое решение и смотрю на адреса строки таким же образом, отладчик показывает тот же адрес для _Buf как указатель строки, который является нормальным поведением. Разница между ними заключается в том, что когда он не может декодировать строку, std :: _ Container_base имеет тип std :: _ Container_base12 и имеет содержимое, а когда он работает, он имеет std :: _ Container_base0 и имеет нулевое содержимое. Это дополнительное содержимое, вероятно, вызывает дополнительные 8 байтов.

Связанные вещи, которые я нашел, но не предлагал решения (пробовал методы здесь, но проблема не устранена): Visual C ++ 2010 отказывается показывать std :: string значение при отладке. шоу

В отладчике Visual Studio неправильно отображается std :: string при отладке

https://developercommunity.visualstudio.com/content/problem/782573/visual-studio-debugger-doesnt-display-stdstring-pr.html

Также попытался возиться с natvis в соответствии с этим: Как визуализировать простую строку std :: string с natvis?

1 Ответ

0 голосов
/ 16 января 2020

Решение: проблема была вызвана этим определением препроцессора:

_HAS_ITERATOR_DEBUGGING=0

Это вызвало разницу в наследовании std :: string с std :: _ Container_base12 и std :: _ Container_base0. Это намеренно и, конечно, работает по замыслу. Но по какой-то причине отладчик не знал об этом и пытался интерпретировать std :: string как обычно.

Я не мог удалить макрос, так как из-за него много кода сорвалось, но когда Я посмотрел в его документы, я понял, что это устарело. Новое препро c. определение:

_ITERATOR_DEBUG_LEVEL

Определение этого значения равным 0, а не старое, не решило проблему, но определение 1 равняло ее (по умолчанию 2). В результате мне пришлось отключить какое-то предупреждение, которое я должен рассмотреть позже, но проблема решена.

OLD:

Не удалось чтобы выяснить причину проблемы root, но ее удалось решить с помощью VS2013 / VS2017 с инструментами сборки v120 до VS2019 v142.

Скорее всего, старые инструменты сборки как-то связаны с этим.

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