Win32 и C++ library
lexa - 15/Мар/2013 22:16
А верно ли я понимаю, что если у меня есть функция с таким вот прототипом (примерно)
Someclass::somefunc(std::string *);
std::string foo("blabla");
Someclass bar;
bar(&foo);
Someclass bar;
bar(&foo);
P.S. Если че, это не я так пишу. Adobe XMP SDK, мать его за ногу, а в нем
SXMPMeta::SerializeToBuffer(string* buffer, some_enum flags);
Comments
Хорошее беспокойство. Мне думается, что обоснованное и дело
Хорошее беспокойство. Мне думается, что обоснованное и дело даже, имхо, не столько в рантаймах, сколько в окружении при компиляции, и от этого в потенциально разных структурах данных в ДЛЛ и в компилируемом коде. Ну, потому, что int, там, или enum - оно обычно и в африке int или enum, а вот string может быть принципиально разным (например, в дебуге могут быть дополнительные поля, бинарно не совместимые с релизом).
Ну за debug/release я, допустим, прослежу. А вот ситуация,
Ну за debug/release я, допустим, прослежу.
А вот ситуация, когда рантайм сменился (визуальная студия обновилась), DLL - не перекомпилировался (потому что ничего не менялось), а исполняемый файл - тоже обновился, такая ситуация же просто обязана извращенно поиметь.
Ну то есть, понятно, FILE* в такой ситуации тоже может порадовать, но FILE* и меняется реже и вообще...
Поимеет, если при смене библиотеки изменится состав полей кл
Поимеет, если при смене библиотеки изменится состав полей класса. А так там фактически только указатель на структуру передается. И тут уже лотерея.
Дополнительные подводные камни могут быть в случае MFC Extension DLL, когда dll закладывается на то, что MFC инициализировалась модулем, который ее загружает.
Вообще если ты динамически линкуешься со всякими msvcrt и ST
Вообще если ты динамически линкуешься со всякими msvcrt и STL то это вполне легально.
В смысле, что msvcrt гарантирует одинаковость std::string во
В смысле, что msvcrt гарантирует одинаковость std::string во всех версиях (от одного Visual C++)? Это где-то явно обещано?
Потому что вот конкретно с malloc()/free() (даже не C++) - я налетал прямо на debug/release builds. В DLL-ке аллоцируется память (релизным malloc()) - и при освобождении этого указателя в .EXE (debug free()) - все рушится. Мне еще тогда лечили голову, что если ты что-то породил в DLL, то там и убивай: http://blog.lexa.ru/2010/09/04/nu_kto_tak_stroit.html
Нет, если у тебя оба модуля слинкованы в динамике(т.е. стати
Нет, если у тебя оба модуля слинкованы в динамике(т.е. статического рантайма нет) и в память была загружена только одна версия msvcrt то очевидно, что она память выделяет и она же грохает, просто потому что никого другого кто это умеет нет.
Std::string не в msvcrt, а в stdчтототам, тоже обе должны быть в динамике, и да у них меняется название либы при бинарной несовместимости, на этом построена вся стабильность майкросовтовского dll-hell :)
Так тут же не линукс. DLL может использовать одну версию msv
Так тут же не линукс.
DLL может использовать одну версию msvcrt, EXE - другую.
И это, типа, "правильно"
Не может если ты только не поебался и специально их из разны
Не может если ты только не поебался и специально их из разных папок не загрузил, правило ресолвинга одинаковое.
Вот msvcrt и msvcrtd легко, или msvcrt и статический рунтайм да, но это ты ссзб
Ну вот видится мне такой сценарий - собираем someclass.dll
Ну вот видится мне такой сценарий
- собираем someclass.dll c некоей текущей версией рантайма
- обновляется студия
- собираем exe.exe (someclass.dll - не обновляется, потому что там ничего не меняется)
Запускаем это чудо. someclass.dll возьмет старый рантайм (из Windows/winsxs/...), exe.exe - новый.
Вот, к примеру, msvcr80.dll - у меня на машине в winsxs их лежит 6 штук разных, трех разных размеров.
Может, поскольку этих CRT много разных: msvcrt.dll msvcrt20.
Может, поскольку этих CRT много разных:
msvcrt.dll
msvcrt20.dll
msvcrt40.dll
msvcr70.dll
msvcr71.dll
msvcr100.dll
Нет уже давно никакой msvcrt.dll. В 2010 студии сишный ранта
Нет уже давно никакой msvcrt.dll. В 2010 студии сишный рантайм живет в msvcr100.dll, плюсовой в msvcp100.dll, в 2012 номера поменялись на 110.
Меня больше волнует случай, когда оба собраны с 100, но разн
Меня больше волнует случай, когда оба собраны с 100, но разных версий. И я тоже не вижу в этом ничего такого невозможного.
Тут зависит от наличия/состава манифеста у dll и exe. Если о
Тут зависит от наличия/состава манифеста у dll и exe. Если они создавались с манифестом, в котором явно указывалось что-то типа <assemblyIdentity type="win32" name="Microsoft.VC90.MFC" version="9.0.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity> - то каждый модуль так и будет за него держаться.
Но практика такой привязки по умолчанию закончилась с 2008 студией, сейчас в манифестах разве что к Common Controls привязка генерируется. Ну в а dll и exe без явной привязки рантайм должен загружаться один и тот же.
В _теории_ должно работать, т.к. очень часто установка VC ru
В _теории_ должно работать, т.к. очень часто установка VC runtime переписывает все системные dll новой версией. На практике народ говорит, что проблемы иногда бывают и если совсем параноик то проще кинуть в свою директорию правильные версии dll-ок.
В WinSxS есть механизм подмены, когда одна версия полностью
В WinSxS есть механизм подмены, когда одна версия полностью закрывает другую, такое используется при небольших итерациях и делалось на моей памяти при выпуске service pack-ов к Visual Studio. В остальных случаях рантаймы имеют разные версии и вполне нормально, когда сторонняя библиотека имеет другой рантайм и плохо когда это не волнует разработчиков той библиотеки. Надо либо все это оборачивать в классы или что-то типа COM делать, либо давать юзеру устанавливать свои аллокаторы.
Вобщем проблема такая есть. Иногда просто требуют - собираешь например плагин к такой-то программе - изволь взять VS такой-то версии и вперед. Multitargeting VS научилась только недавно делать, а иначе приходится держать зоопарк студий.
msvcrt и msvcr это разные dll, а номера это и есть бинарная
msvcrt и msvcr это разные dll, а номера это и есть бинарная совместимость. Замечу если у тебя проект загрузил 2 разные именованные версии это не windows плохая, а ты что так слинковал.
<em>> То в какой-то момент это меня обязательно поимеет?</em
> То в какой-то момент это меня обязательно поимеет?
Всенепременно.
И независимо от длины ночной рубашки!
И независимо от длины ночной рубашки!
Примерно так. Насколько мне помнится, стандарт ничего не об
Примерно так.
Насколько мне помнится, стандарт ничего не обещает про инстанцированные шаблоны, кроме ODR (one definition rule). А ODR работает в границах единицы компоновки.
Думаю будет проблема. Использую такой вариант - надо писать
Думаю будет проблема.
Использую такой вариант - надо писать свой класс в котором аллокация и освобождение будет делаться через пару виртуальных функций. Можно даже шаблон сделать с этими виртуальными функциями. Главное что теперь эти функции будут находиться через таблицу виртуальных функций от конкретного экземпляра этой строки.
Причем модульную безопасность с помощью такого метода могли
Причем модульную безопасность с помощью такого метода могли бы везде проделать в STL, но там есть только механизм аллокаторов, который никак не спасет, потому что аллокатор не крепится к классу, а является параметром шаблона и соответственно будет собираться в каждом модуле по своему.
В 94.674% случаях поимеет, а
В 94.674% случаях поимеет, а в високосный год - итого больше.
Проблемы - разный heap, разная реализация, разный layout данных.
Но если код somefunc(std::string *) полностью в заголовке(inline), компилируется на твоей стороне и сам границу пересекает только по lingua franca С API - то вполне легально.
И кстати, это походу как раз
И кстати, это походу как раз твой случай:
XMP-Toolkit-SDK-CS6/public/include/client-glue/TXMPMeta.incl_cpp, и дальше если нырять, то находится:
void
WXMPMeta_SerializeToBuffer_1
(
XMPMetaRef xmpObjRef,
void * pktString,
XMP_OptionBits options,
XMP_StringLen padding,
XMP_StringPtr newline,
XMP_StringPtr indent,
XMP_Index baseIndent,
SetClientStringProc SetClientString,
WXMP_Result * wResult
) /* const */
{
XMP_ENTER_ObjRead ( XMPMeta, "WXMPMeta_SerializeToBuffer_1" )
XMP_VarString localStr;
if ( newline == 0 ) newline = "";
if ( indent == 0 ) indent = "";
thiz.SerializeToBuffer ( &localStr, options, padding, newline, indent, baseIndent );
if ( pktString != 0 ) (*SetClientString) ( pktString, localStr.c_str(), localStr.size() );
XMP_EXIT
}
Но раз у тебя есть сборка - тебе проще по step-into убедится, что дёргаются методы именно твоего string'а.
В общем, с тебя бутылка :)
Есть тут кто? или уже
Есть тут кто? или уже /dev/null?
Ну я есть. Я собрал это
Ну я есть.
Я собрал это самое XMPCore статикой а не dll от греха.
По-идеи они обо всём
По-идеи они обо всём позаботились - то что использует std::string из твоего рантайма, собирается на твоей стороне.
Но на практике могли где-то ошибиться, что-то забыть. Так что да, если есть возможность недорого перестраховаться, то почему бы и нет.