| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C++ Builder > PACKAGE - что значит? |
| Автор: Bodro 21.6.2012, 12:43 |
| Добрый день! Что означает слово PACKAGE в C++ Builder? И можно ли его использовать совместно с неймспейсом? Прошу объяснить или дать ссылку на источник. Спасибо! |
| Автор: xvr 22.6.2012, 11:48 | ||
Это дефайн (из sysmac.h)
Другой информации похоже нету |
| Автор: Bodro 23.6.2012, 15:12 |
| Это то всё понятно. Это что-то типа экспортдлл. Но хотелось бы побольше информации как это влияет на линковку и всё, что с этим связано. |
| Автор: xvr 23.6.2012, 17:02 | ||
Это вам вряд ли кто скажет точно. Вот (с сайта Embarcadero):
Еще http://stackoverflow.com/questions/2727001/how-do-i-solve-an-unresolved-external-when-using-c-builder-packages есть немного |
| Автор: Bodro 26.6.2012, 13:30 | ||||||||||||||
| Разобрался. В общем, как-нить потом, если будет время, расскажу конкретно как работает __declspec(package). А сейчас хочу поведать вам о том, что в процессе работы обнаружил ошибку в компиляторе Embarcadero Builder 2010. Ошибка эта связана с тем, что компилятор по-разному генерирует код, если у класса указть __declspec(package) или если не указывать его. Вот минимальный код, который её воспроизводит:
Вариант 1:
Вариант 2:
В первом случае компилятор, зачем-то, в стек заталкивает не само значение переменной, а значение, которое он пытается взять, обращаясь за переменной по адресу, который был указан в нашей переменной, т.е. он считает что мы ему подсунули не переменную, а её адрес. Почему он так делает понять сложно - это просто баг. При запуске программы появляется AV по адресу 0x0000FF00. Во втором случае всё нормально и Access Violation не появляется. Причём, если использовать другие нотации вызовов такие, как, например, __fastcall, то результирующий код будет выглядеть несколько по-другому, но сути не поменяет. Лечение такое:
Убирание explicit и throw() у конструктора не влияет. Так же никак не повлияет на ситуацию убирание const у статической переменной. На более ранних или более поздних версиях компилятора не тестровал. Если протестируете и выложите свои результаты - буду очень признателен. |
| Автор: xvr 26.6.2012, 14:09 |
| Попробуйте написать PACKAGE перед определением TestClass::defaultValue (в строке 13), может заработает |
| Автор: Bodro 26.6.2012, 14:50 |
| А куда его воткнуть-то? Пример приведи. UPD Стоп. А зачем, кстати? Это же приватная константа и она должна остаться в классе - наружу её светить не нужно никак. Если знаешь про данную ситуацию что-то - объясни, если не сложно. |
| Автор: Alexeis 26.6.2012, 16:56 | ||
Видел такое объявление
В данном случае это значит что реализация находиться в пакете. |
| Автор: Bodro 26.6.2012, 17:35 |
| Так, значит проблема тянется давным-давно. Кто-нить на XE и на XE2 протестирует? Кстати, borisbn, а ассемблерный вывод какой? Такой же? Сравни с PACKAGE и без него. |
| Автор: borisbn 26.6.2012, 17:48 |
абсолютно такой же |
| Автор: Alexeis 26.6.2012, 18:21 | ||
А почему вы решили что это ошибка? Директива малодокументирована. Вполне возможно что мы имеем дело с Undefined Behaviour . Пока что я не видел ни одной ссылки на документацию о правильном использовании. |
| Автор: Bodro 26.6.2012, 18:39 |
| А вы считаете что это не ошибка? Я месяц разрабатывал большой компонент и линковал его #pragma link (более 4 000 строк кода). Всё протестировал - работает просто отлично! Необходимо было корректно его вставить в разработанную библиотеку. Классы были объявлены с PACKAGE. Всё собралось отлично - ворнингов небыло. Если вы посмотрите на код внимательно, то увидите, что он соответствует стандарту C++03 в полной мере (ну за исключением PACKAGE и других прагм, что, собственно, не запрещается стандартом). И в один прекрасный момент программа упала в абсолютно неожиданном месте, при этом показав нелепый стек вызовов. Простыми способами и точками останова проблемы выявить нельзя. При этом все константы (до шага совершения ошибки) были вполне нормальными и чётко определёнными. Вы считаете что это не ошибка? Как бы она не была документирована, подобная подмена всегда является ошибкой. Я думаю что вы просто не до конца поняли суть проблемы. Посмотрите ещё раз код, разберите ассемблерный вывод каждого варианта и вы увидите что это действительно баг - компилятор неправильно генерирует код. Если вы считаете что это не баг, то в таком случае компилятор мог бы и предупредить о том, что в данном случае он собирается сделать такую манипуляцию. Внимательно гляньте на код - компилятор просто некорректно преобразовал код из C++ в ассемблер. |
| Автор: Alexeis 26.6.2012, 19:20 | ||
Директива PACKAGE может накладывать некоторые ограничения на использование конструкций С++ . Не забывайте, что все эти механизмы пишутся сначала для делфи, а потом переносятся на С++ . Фик его знает на что он рассчитывает. Может на то что экспортируемые классы будут иметь всегда VMT или еще что. Компилятор много чего позволяет на самом деле. Например экспортировать объект класса из Dll , без того чтобы иметь общую реализацию. Тут он явно рассчитывал, что реализация класса может быть прилинкована, а значит код инициализации пакета должен был сохранить указатели на поля данных. А значит вместо вместо того, чтобы адресовать напрямую нужна будет дополнительная операция. Возможно не было выполнено одно из условий использование таких конструкций, в результате код поздней линковки что-то не связал между собой. |