Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > Visual C++/MFC/WTL > Проблема с функциями SysAllocString/SysFreeString |
Автор: ParaPik 30.9.2011, 22:10 | ||||
У меня имеются 2 переменные типа BSTR. Инициализирую их следующим образом:
Потом вторая переменная в цикле изменяется так:
Проблема в том, что спустя буквально 2-3 итераций цикла адрес, хранящийся в second, становится равный значению переменной first. Т.е. теперь они указывают на одну и ту же строку, first хранит some_value и second хранит some_value!!! Пожалуйста, помогите разобраться. |
Автор: Estranged 1.10.2011, 11:41 |
Да ладно, чудес не бывает. Код цикла приложите. |
Автор: ParaPik 1.10.2011, 13:02 | ||
Так, в том то и дело, что это и есть код цикла. Но если в более подробном варианте:
Т.е. изменение переменной second происходит только в конце цикла. Нигде она больше не изменяется. |
Автор: Estranged 1.10.2011, 16:25 |
Просто, как копейка. Как вариант, может быть переполнение буфера где-то или чтение за границей буфера. Приложите весь код функции. Да не может такого быть, чтобы first совпал с новым SysAllocString. Потому что это слишком не правдоподобно. |
Автор: ParaPik 1.10.2011, 22:29 | ||
Я тоже удивился. Функцию полностью показывать нет смысла. В приложении один поток. Проверял работу кода отладчиком. Именно после очередного вызова SysAllocString происходит приравнивание адресов.
|
Автор: mes 1.10.2011, 22:55 |
да и вопрос на форуме задавать смысла нет, тут телепатов нет.. |
Автор: ParaPik 2.10.2011, 10:10 | ||
Вот:
|
Автор: Estranged 2.10.2011, 11:59 | ||||||
А где здесь first? Я бы заменил
на
Зачем грызть всю строку... Зачем тут _T? Ведь wstring t_result.
|
Автор: ParaPik 2.10.2011, 14:14 | ||||||||||
По поводу _T. Я просто убрал из примера препроцессорные директивы, в которых проверяется _UNICODE. По поводу strlen согласен. Что-то я поспешил... Простите, что забыл описать макрос START_PERROR. Он вызывает следующую функцию:
m_error - это и есть first. Я уже пробовал оберткой _bstr_t воспользоваться. Думал, мало ли я что-то не так делаю. Результата ноль. |
Автор: ParaPik 2.10.2011, 23:08 |
Да, в цикле вызывается Func. При первом вызове функции m_error указывает на "". После первой итерации m_result принимает правильное значение, m_error свое значение не изменяет. То же самое и во второй итерации. Но на третьей итерации SysAllocString возвращает адрес, который содержится в m_error. Этот адрес присваевается m_result. Т.е. теперь обе переменные указывают на одну и ту же строку, строку, верную для m_result. То же самое происходит, даже если m_error указывает на строку не нулевой длины. |
Автор: Estranged 3.10.2011, 10:40 |
А на третьей итерации в SysAllocString что подается, чему равно t_result? Какая строка? И как я понял, m_error на третьей итерации все еще не меняет свое значение, т.е. равен "". Иными словами должно получаться, что в m_result теперь тоже лежит "" и это верно. Так? Т.е. и m_result, и m_error равны "". Я правильно понимаю? |
Автор: ParaPik 3.10.2011, 13:38 |
t_result практически всегда не нулевая строка. И на третьей итерации она тоже не нулевая. Значение m_error не меняется, а SysAllocString на третьей итерации возвращает значение, содержащиеся в m_error, т.е. ячейка памяти, на которую указывает m_error перезаписывается на содержимое t_result. Еще я заметил, что такое происходит только тогда, когда при первой инициализации m_result SysAllocString передать пустую строку. Я не знаю, может, это проявилось бы при больших итерациях и при начальной инициализации m_result не пустой строкой. Но самый явный баг в первом случае. |
Автор: Estranged 3.10.2011, 16:38 | ||
Теперь понятно. Такая багофича есть. А для m_error SysFreeString не вызывается где-нибудь скрыто и незаметно без парного SysAllocString до вызова m_result = SysAllocString(t_result.c_str())? Потому что после SysFreeString строка не уничтожается, а висит в памяти до ближайшего вызова SysAllocString, отчего два указателя указывают на одну память, но уже с другими данными, и один из указателей невалидный. Убедитесь сами:
Если SysFreeString снести вниз за второй SysAllocString, то и bs, и bs2 хранят свои строки. Отчего я думаю, у Вас есть SysFreeString для m_error без пары SysAllocString, отчего система думает, что строка некогда лежавшая в m_error свободна, отчего использует этот регион памяти повторно, и как бы кажется, что m_error как бы принимает значение t_result, хотя в действительности m_error хранит уже некорректный адрес. Вот как-то так... |
Автор: ParaPik 3.10.2011, 17:23 |
SysAllocString и SysFreeString вызывались только парами. Скрыто ничто не может изменить значение. Я уже все заменил на _bstr_t. С этой оберткой вопрос о неправильном освобождении памяти точно отпадает(ничего из-за этого не изменилось). Но я все-таки решил эту проблему. Я теперь просто инициализирую m_error не "", а nullptr. Все равно мне нужно будет получить лишь одну строку: либо m_error, либо m_result. Больше я не вижу решений. В любом случае, спасибо, Estranged, за участие в решении моей проблемы. |