VC9 выбрасывает при линковке неиспользуемые глобальные переменные

Тема в разделе "LANGS.C", создана пользователем Velheart, 22 июл 2009.

  1. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Собственно есть код в духе:
    (упрощенно)
    Код (Text):
    1. class CBasePacket;
    2. ...
    3. class CPacketFactory
    4. {
    5.     static long RegisterPacket(long type, CreationRoutine cr);
    6. ...
    7. }
    8. ...
    9. class CCallUsermodePacket:
    10.     CBasePacket
    11. {
    12. ...
    13.     static volatile long s_type;
    14.     static CBasePacket* CreateNew();
    15. ....
    16. }
    17. __declspec(selectany) long  CCallUsermodePacket::s_type = CPacketFactory::RegisterPacket(eCallUserMode, CreateNew);
    18. ...
    т.е. фабрика классов с "саморегистрацией", так вот в релизе нет ни s_type, ни RegisterPacket, а соответственно и автоматической регистрации.. #pragma optimize не помогает, у кого-нибудь есть идеи, как побороть?
     
  2. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Velheart

    А если убрать __declspec(selectany) ?
     
  3. Sol_Ksacap

    Sol_Ksacap Миша

    Публикаций:
    0
    Регистрация:
    6 мар 2008
    Сообщения:
    623
    А сам по себе класс "CCallUsermodePacket" используется?
    Возможно ли, что в полной версии "CCallUsermodePacket" – шаблонный класс?

    "volatile" для "s_type" не нужен – не поможет.
    Также не видим необходимости в __declspec(selectany).

    В крайнем случае можно попробовать сделать ссылку на "s_type" в каком-нибудь используемом методе:
    volatile long* stype_hack = &CCallUsermodePacket::s_type;
     
  4. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    _DEN_, Sol_Ksacap
    Если убрать __declspec(selectany), то действительно все работает, но фишка в том что я привел код хидера, который будет инклюдиться в несколько сишников, а убирать __declspec(selectany) long CCallUsermodePacket::s_type = CPacketFactory::RegisterPacket(eCallUserMode, CreateNew);
    в соответствующий сишнег -- плохо, т.к. суть фишки в том, что новые наследники CBasePacket достаточно объявить в этом хидере + добавить в конце

    Код (Text):
    1. class  CCallUsermodePacket
    2. ...
    3.     DECLARE_PACKET (CCallUsermodePacket);  
    4. };
    5. REGISTER_PACKET(CCallUsermodePacket, eCallUsermode);
    т.е. добавить соответствующие макросы -- и все, мы можем юзать дальше код типа

    Код (Text):
    1.         CTestComm com;
    2.     CPacketBase* pPacket = CPacketFactory::ReadPacket(com);
    т.е. мы вычитываем из "того, что нам дадут"(пайп, порт лпц, сокет, кусок разделяемой памяти и т.д.)

    Код (Text):
    1. template<class TCommunicator>
    2.     static CPacketBase* ReadPacket(TCommunicator& ctr)
    3.     {
    4.         PacketType type;
    5.         _S_0 (ctr.Read(&type, sizeof(type)));
    6.        
    7.         std::auto_ptr<CPacketBase> packet((s_creationRoutines[type])());
    8.         if (packet.get())
    9.         {
    10.             _S_0 (packet->FillWithData(ctr));
    11.         }
    12.        
    13.         return packet.release();
    14.     }
    тип, а потом создаем объект, на основе вычитанных данных.

    Несколько месяцев назад на работе я сталкивался с подобной задачей, только там были пайпы, и я так все и писал, но тестил все на отладочной версии, поэтому в последний момент всплыл такой вод баг, и пришлось срочно все править -- я просто сделал глобальную функцию RegisterPacketTypes, в которую добавлял макрос для каждого типа, и вызывал ее из мэйна/длл-мэйна, а сейчас речь идет о том, что не к спеху, делается пока для себя, и поэтому хочется получить максимальное количество удовольствия от красивого и правильного кода))
     
  5. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    Sol_Ksacap
    /add
    volatile -- это я на всякий случай, т.к по идее и без него должно быть ок(по мои представлениям))
    так делал, не помогает
     
  6. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Velheart
    #pragma comment(linker, "/include:?s_type@CCallUsermodePacket@@0JC")
    Проверь на всякий случай декорированное имя.
     
  7. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    green
    Ога, так работает, только не могу в макрос включить эту строчку:

    Код (Text):
    1. #define REGISTER_PACKET(cls, type)      \
    2.     __declspec(selectany) PacketType cls::s_type = CPacketFactory::RegisterPacket(type, cls::CreateNew); \
    3.     #pragma comment(linker, "/include:?s_type@##cls##@@2W4PacketType@@C");
    не компилится, но можно че-нить попридумывать может быть)
     
  8. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Velheart
    Код (Text):
    1. #define REGISTER_PACKET(cls, type)      \
    2.     __declspec(selectany) PacketType cls::s_type = CPacketFactory::RegisterPacket(type, cls::CreateNew); \
    3.     __pragma(comment(linker, "/include:?s_type@##cls##@@2W4PacketType@@C"))
     
  9. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    green
    Сенкс, так все работает, не знал про такой синтаксис))
     
  10. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Улыбнуло. Красивый и правильный...
     
  11. Velheart

    Velheart New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    526
    nop_
    Случайно сейчас наткнулся опять на эту тему =) Имхо именно так и есть, т.к. важно не то, что скрыто за макросами (красота будет потом, а в этот хэдер никто никогда не заглянет), а то насколько удобно потом это будет расширять и поддерживать, макросы будут написаны один раз, а в каждый новый класс, по аналогии с остальными будет добавляться одна строчка с функционалом а-ля "пыщ, сделай чтоб все было" + код будет хорошо читаем и не загромажден лишним, необходимо дублируемым но очень похожим кодом, так что улыбка не совсем к месту =)
     
  12. nop_

    nop_ New Member

    Публикаций:
    0
    Регистрация:
    21 июн 2007
    Сообщения:
    61
    Сказав "красота будет потом", ты согласился с тем, что к приведенному коду не применимы такие характеристики как "красивый и правильный" =)

    По существу - здесь проблема из-за этого: "в каждый новый класс, по аналогии с остальными будет добавляться одна строчка ". В месте определения класса, при таком использовании, появляется зависимость от CPacketFactory со всеми вытекающими последствиями - клиенты (те самые классы) становятся не самодостаточными, изменение интерфейса CPacketFactory влечет за собой перекомпиляцию всех зависимых классов и т.д. Впрочем, насколько это существенно - решать тебе.
     
  13. hkarel

    hkarel New Member

    Публикаций:
    0
    Регистрация:
    15 окт 2009
    Сообщения:
    1
    Вариация на тему данного решения: http://rsdn.ru/forum/cpp.applied/3570438.1.aspx
    Основой для решения послужил материал этого топика.