Поиск:

Ответ в темуСоздание новой темы Создание опроса
> PACKAGE - что значит? Что означает это слово? 
:(
    Опции темы
Bodro
Дата 21.6.2012, 12:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 27.1.2006
Где: Россия, г. Рязань

Репутация: 2
Всего: 4



Добрый день!

Что означает слово PACKAGE в C++ Builder? И можно ли его использовать совместно с неймспейсом?
Прошу объяснить или дать ссылку на источник. Спасибо!
PM MAIL WWW ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
xvr
Дата 22.6.2012, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(Bodro @  21.6.2012,  12:43 Найти цитируемый пост)
Что означает слово PACKAGE

Это дефайн (из sysmac.h)
Код

#define __safecall __stdcall
#define __interface class
#define __dispinterface class

#define PACKAGE              __declspec(package)                 // Implemented in a package
#define PASCALIMPLEMENTATION __declspec(pascalimplementation, package) // Implemented in Delphi - no code should be generated
#define DELPHIRETURN         __declspec(delphireturn, package)  // Uses Delphi's return semantic; resides in a package
#define DELPHICLASS          __declspec(delphiclass, package)   // Implemented in Delphi (C++ does not generate RTTI)
#define DYNAMIC              __declspec(dynamic)                // For compatibility with Delphi's old virtual mechanism

#if (__BORLANDC__ >= 0x0550)
#define INTERFACE_UUID(guid) __declspec(uuid(guid))             // For associating a GUID with a type
#else
#define INTERFACE_UUID(guid)
#endif

// Macros specifically for C++ emulation of Delphi language features
// Used for RTL functionality which should not be packaged.
//
#define RTL_DELPHIRETURN     __declspec(delphireturn)           // Uses Delphi's return semantic (not in package)
#define RTL_DELPHICLASS      __declspec(delphiclass)            // Implemented in Delphi

#define HIDESBASEDYNAMIC     __declspec(hidesbase, dynamic)     // For compatibility with Delphi
#define HIDESBASE            __declspec(hidesbase)              // For compatibility with Delphi

Другой информации похоже нету

PM MAIL   Вверх
Bodro
Дата 23.6.2012, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 27.1.2006
Где: Россия, г. Рязань

Репутация: 2
Всего: 4



Это то всё понятно. Это что-то типа экспортдлл. Но хотелось бы побольше информации как это влияет на линковку и всё, что с этим связано.
PM MAIL WWW ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
xvr
Дата 23.6.2012, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Цитата(Bodro @  23.6.2012,  15:12 Найти цитируемый пост)
 Но хотелось бы побольше информации

Это вам вряд ли кто скажет точно. 
Вот (с сайта Embarcadero):
Цитата

__declspec(package)

Category

Modifiers, Keyword Extensions, Storage Class Specifiers

Syntax

__declspec(package) declarator

The package argument is used to indicate that the class definition can be compiled in a package.

    Note: You can use the macro PACKAGE, defined in sysmac.h, as an alternative for __declspec(package).


Еще тут есть немного


PM MAIL   Вверх
Bodro
Дата 26.6.2012, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 27.1.2006
Где: Россия, г. Рязань

Репутация: 2
Всего: 4



Разобрался. В общем, как-нить потом, если будет время, расскажу конкретно как работает __declspec(package).

А сейчас хочу поведать вам о том, что в процессе работы обнаружил ошибку в компиляторе Embarcadero Builder 2010. Ошибка эта связана с тем, что компилятор по-разному генерирует код, если у класса указть __declspec(package) или если не указывать его.

Вот минимальный код, который её воспроизводит:
Код

#pragma hdrstop

#define PACKAGE __declspec(package)

class PACKAGE TestClass { // Вариант №1. Не работает (AV)
//class TestClass { // Вариант №2. Работает
  private:
    static const int defaultValue;
  public:
    explicit TestClass(const int value = TestClass::defaultValue) throw();
};

const int TestClass::defaultValue = 0x00FF00;

TestClass::TestClass(const int value) throw() {
}

#pragma argsused
int main() {
  new TestClass; // Access Violation reading of address 0x0000FF00
  return 0;
}

Вариант 1:
Код

    mov       edx,dword ptr [@@TestClass@defaultValue]
    push      dword ptr [edx]

Вариант 2:
Код

    push      dword ptr [@@TestClass@defaultValue]


В первом случае компилятор, зачем-то, в стек заталкивает не само значение переменной, а значение, которое он пытается взять, обращаясь за переменной по адресу, который был указан в нашей переменной, т.е. он считает что мы ему подсунули не переменную, а её адрес. Почему он так делает понять сложно - это просто баг. При запуске программы появляется AV по адресу 0x0000FF00.
Во втором случае всё нормально и Access Violation не появляется.

Причём, если использовать другие нотации вызовов такие, как, например, __fastcall, то результирующий код будет выглядеть несколько по-другому, но сути не поменяет.

Лечение такое:
  •  Не использовать инициализацию аргументов конструктора значениями по-умолчанию статическими переменными. Варианта два - или использовать сами значения или вообще не использовать значения по-умолчанию
    Код

    explicit TestClass(const int value = 0x0000FF00) throw();
    explicit TestClass(const int value) throw();
  •  Без необходимости не использовать PACKAGE (или __declspec(package), что одно и то же по-сути);
    Код

    class TestClass {
  •  Инициализировать значения статических констант сразу
    Код

    static const int defaultValue  = 0x00FF00;

    Не уверен, что данная конструкция будет работать на всех компиляторах, т.е. если вы пишите кроссплатформенный код на C++03, лучше, наверное, не использовать такие конструкции. Если у вас тлко Builder, то можно использовать такие конструкции (не факт что на ранних версиях Builder будет работать).
  •  Передавать значения по ссылке:
    Код

    explicit TestClass(const int& value = TestClass::defaultValue) throw();

Убирание explicit и throw() у конструктора не влияет. Так же никак не повлияет на ситуацию убирание const у статической переменной.

На более ранних или более поздних версиях компилятора не тестровал. Если протестируете и выложите свои результаты - буду очень признателен.
PM MAIL WWW ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
xvr
Дата 26.6.2012, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 48
Всего: 223



Попробуйте написать PACKAGE перед определением TestClass::defaultValue (в строке 13), может заработает  smile 

PM MAIL   Вверх
Bodro
Дата 26.6.2012, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 27.1.2006
Где: Россия, г. Рязань

Репутация: 2
Всего: 4



А куда его воткнуть-то? Пример приведи.

UPD
Стоп. А зачем, кстати? Это же приватная константа и она должна остаться в классе - наружу её светить не нужно никак.
Если знаешь про данную ситуацию что-то - объясни, если не сложно.

Это сообщение отредактировал(а) Bodro - 26.6.2012, 14:53
PM MAIL WWW ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Alexeis
Дата 26.6.2012, 16:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



Видел такое объявление
Код

extern PACKAGE <объявление>

В данном случае это значит что реализация находиться в пакете.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
borisbn
Дата 26.6.2012, 17:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



Цитата(Bodro @  26.6.2012,  13:30 Найти цитируемый пост)
 Если протестируете и выложите свои результаты - буду очень признателен. 

Не признательности ради, а интереса для...
Судя по всему, это - не вновь образовавшаяся ошибка. В Builder 5.0 (да, да... такое старьё...) то же самое. Падает с AV при указании __declspec(package)

Цитата(xvr @  26.6.2012,  14:09 Найти цитируемый пост)
Попробуйте написать PACKAGE перед определением TestClass::defaultValue (в строке 13), может заработает 

в моём билдере не помогло



--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Bodro
Дата 26.6.2012, 17:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 27.1.2006
Где: Россия, г. Рязань

Репутация: 2
Всего: 4



Так, значит проблема тянется давным-давно. Кто-нить на XE и на XE2 протестирует?

Кстати, borisbn, а ассемблерный вывод какой? Такой же? Сравни с  PACKAGE и без него.
PM MAIL WWW ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
borisbn
Дата 26.6.2012, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 18
Всего: 135



Цитата(Bodro @  26.6.2012,  17:35 Найти цитируемый пост)
Кстати, borisbn, а ассемблерный вывод какой? Такой же? 

абсолютно такой же


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Alexeis
Дата 26.6.2012, 18:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



Цитата(borisbn @  26.6.2012,  18:09 Найти цитируемый пост)
Судя по всему, это - не вновь образовавшаяся ошибка. В Builder 5.0 (да, да... такое старьё...) то же самое. Падает с AV при указании __declspec(package)

  А почему вы решили что это ошибка? Директива малодокументирована. Вполне возможно что мы имеем дело с Undefined Behaviour . Пока что я не видел ни одной ссылки на документацию о правильном использовании.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Bodro
Дата 26.6.2012, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 92
Регистрация: 27.1.2006
Где: Россия, г. Рязань

Репутация: 2
Всего: 4



А вы считаете что это не ошибка? Я месяц разрабатывал большой компонент и линковал его #pragma link (более 4 000 строк кода). Всё протестировал - работает просто отлично! Необходимо было корректно его вставить в разработанную библиотеку. Классы были объявлены с PACKAGE. Всё собралось отлично - ворнингов небыло. Если вы посмотрите на код внимательно, то увидите, что он соответствует стандарту C++03 в полной мере (ну за исключением PACKAGE и других прагм, что, собственно, не запрещается стандартом). И в один прекрасный момент программа упала в абсолютно неожиданном месте, при этом показав нелепый стек вызовов. Простыми способами и точками останова проблемы выявить нельзя. При этом все константы (до шага совершения ошибки) были вполне нормальными и чётко определёнными. Вы считаете что это не ошибка?

Как бы она не была документирована, подобная подмена всегда является ошибкой. Я думаю что вы просто не до конца поняли суть проблемы. Посмотрите ещё раз код, разберите ассемблерный вывод каждого варианта и вы увидите что это действительно баг - компилятор неправильно генерирует код.

Если вы считаете что это не баг, то в таком случае компилятор мог бы и предупредить о том, что в данном случае он собирается сделать такую манипуляцию. Внимательно гляньте на код - компилятор просто некорректно преобразовал код из C++ в ассемблер.

Это сообщение отредактировал(а) Bodro - 26.6.2012, 22:01
PM MAIL WWW ICQ Skype GTalk Jabber AOL YIM MSN   Вверх
Alexeis
Дата 26.6.2012, 19:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 26
Всего: 459



Цитата(Bodro @  26.6.2012,  19:39 Найти цитируемый пост)
Если вы считаете что это не баг, то в таком случае компилятор мог бы и предупредить о том, что в данном случае он собирается сделать такую манипуляцию. Внимательно гляньте на код - компилятор просто некорректно преобразовал код из C++ в ассемблер.

  Директива PACKAGE может накладывать некоторые ограничения на использование конструкций С++ . Не забывайте, что все эти механизмы пишутся сначала для делфи, а потом переносятся на С++ . Фик его знает на что он рассчитывает. Может на то что экспортируемые классы будут иметь всегда VMT или еще что. Компилятор много чего позволяет на самом деле. Например экспортировать объект класса из Dll , без того чтобы иметь общую реализацию. Тут он явно рассчитывал, что реализация класса может быть прилинкована, а значит код инициализации пакета должен был сохранить указатели на поля данных. А значит вместо вместо того, чтобы адресовать напрямую нужна будет дополнительная операция.   
   Возможно не было выполнено одно из условий использование таких конструкций, в результате код поздней линковки что-то не связал между собой. 


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0950 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.