Что может сломать отладчик в Visual Studio (может быть, std::string?)

Рассмотрите возможность установки точки останова в следующей строке и перехода к ней с помощью отладчика Visual Studio (в полностью очищенной и перестроенной отладочной сборке):

Poco::URI testUri( "http://somewhere.com/test/path" );

Оказывается, этот шаг приведет вас к этой функции:

URI::URI(const char* uri):
    _port(0)
{
    parse(std::string(uri));
}

И оказывается, что когда вы сделаете еще несколько шагов и сделаете паузу на последней строке после вызова parse(), все будет хорошо во вновь созданном объекте URI, а именно:

  • он был проанализирован правильно;
  • можно развернуть указатель this, чтобы увидеть правильно назначенные переменные-члены (например, для членов its_host, _path и _scheme установлены значения «somewhere.com», «/test/path» и «http» соответственно);
  • указатель this на этом этапе указывает на законное место в памяти (например, 0x002AEE20), и в этом месте можно увидеть то, что, как я уверен, является объектом URI (набор std::string переменных и одна int, как это происходит).

Однако, сделав еще один шаг, вы вернетесь к исходной строке кода, и вдруг:

  • расширение объекта testUri в окнах отладчика "Autos" или "Watch" приводит к std::string членам, которые не могут быть прочитаны (имеются "ошибки чтения символов строки"), и все же...
  • память, в которой находится сконструированный объект, остается неизменной, и...
  • подтверждается, что адрес testUri указывает на неизмененную память

Как это может быть? Отладчик VS не работает? Что сломало его?

Это последняя из серии странных проблем, связанных с попыткой запустить библиотеки POCO в многопоточном проекте MFC. Я понятия не имею, должны ли MFC или многопоточность оказывать какое-либо влияние на Poco, но я пережил неделю странностей - часто с задействованными std::string объектами - и я хотел бы добраться до сути. Все предложения по отслеживанию происходящего приветствуются. Я запускаю сообщество VS2015, если это имеет значение.


person omatai    schedule 01.03.2016    source источник
comment
У вас есть небольшая репродукция, которую можно опубликовать? Возможно, вам потребуется также опубликовать места загрузки конкретных сборок библиотеки Poco, которые вы используете, и параметры сборки, которые вы используете.   -  person Michael Burr    schedule 01.03.2016
comment
Может что-то — ваше приложение или библиотека — компилируется в релизном режиме? Оптимизации и отсутствие отладочной информации могут привести к тому, что отладчик покажет странные вещи. Например, ваш объект может полностью или частично находиться в регистрах и не иметь фактического представления в памяти.   -  person CygnusX1    schedule 01.03.2016
comment
Спасибо за советы... Проверяю. Что я могу сообщить, так это то, что библиотеки Poco должны автоматически выбираться и связываться в соответствии с различными переключателями компилятора. У меня есть многопоточная отладочная сборка... что должно означать, что PocoFoundationmtd.lib связан. Однако... если я переименую PocoFoundationmtd.lib, чтобы его нельзя было найти, мое приложение все равно будет собираться. Звучит как довольно серьезная подсказка :-)   -  person omatai    schedule 02.03.2016


Ответы (1)


Как упоминалось в комментариях, попытка смешивания разных сборок (т. е. как выпуска, так и отладки) в одном проекте может вызвать подобные проблемы.

Однако в данном случае это было смешение разных компиляторов — большая часть проекта была построена в условиях, которые кажутся VS2010, а библиотеки Poco — в условиях VS2015.

Я не уверен на 100% в условиях, в которых ранее компилировался более широкий проект, так как он был недавно обновлен с VS2010 до VS2015, и в процессе настройка Platform Toolset не отображалась в файле .vcxproj. Теперь я (повторно) ввел Platform Toolset для каждой конфигурации сборки и установил для него значение v100, а также пересобрал Poco с помощью сценария build_vs100.cmd. Кажется, теперь все работает так, как ожидалось.

Я отследил это, заметив, что приложение компилировалось с помощью /MDd (генерация многопоточного отладочного кода DLL), но компоновщик пытался связать "d" версии библиотек Poco, а не "mdd" версии. Когда компиляторы были приведены в соответствие, компоновщик правильно скомпоновал версии "mdd", как и следовало ожидать.

Поскольку все ссылки на библиотеки в Poco должны быть автоматическими (см. директивы #pragma в PocoFoundation.h), неправильный выбор библиотеки был вызван изменением определений препроцессора (POCO_STATIC не определялся). Я не удосужился проверить, почему это так.

person omatai    schedule 02.03.2016