Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> GCC: Как избавиться от type_info? -fno-rtti не спасает 
V
    Опции темы
LShadow77
Дата 9.8.2019, 21:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 17.10.2011

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



Здравствуйте!
Я пользуюсь компилятором MinGW GCC и заметил, что появление хотя бы одного виртуального метода в классах сразу даёт +100 Кб к размеру моей программы. Погуглил, и нашёл, что виной всему - т.н. механизм RTTI. А также нашёл опцию, которая этот механизм должна отключать: -fno-rtti. И всё бы ничего, только эта опция не убирает лишний код из программы - все неиспользуемые классы RTTI всё равно остаются прилинкованными мусорным балластом. 

Для иллюстраци, привожу таблицу виртуальных функций моего тестового класса ('CTestNode2) c включённым RTTI. Видно, что в ней присутствует указатель на typeinfo для класса, а далее следуют специфичные для RTTI таблицы, из-за чего и увеличивается размер приложения...
Код

rdata:00414184                 public __ZTV10CTestNode2
.rdata:00414184 ; `vtable for'CTestNode2
.rdata:00414184 __ZTV10CTestNode2 dd 0                  ; offset to this
.rdata:00414188                 dd offset __ZTI10CTestNode2 ; `typeinfo for'CTestNode2
.rdata:0041418C off_41418C      dd offset __ZN10CTestNode2D1Ev
.rdata:0041418C                                         ; DATA XREF: CTestNode2::~CTestNode2()+9↑o
.rdata:0041418C                                         ; _main+395↑o
.rdata:0041418C                                         ; CTestNode2::~CTestNode2()
.rdata:00414190                 dd offset __ZN10CTestNode2D0Ev ; CTestNode2::~CTestNode2()
.rdata:00414194                 dd offset __ZN10CTestNode211TestVMethodEv ; CTestNode2::TestVMethod(void)
.rdata:00414198                 public __ZTVN10__cxxabiv115__forced_unwindE
.rdata:00414198 ; `vtable for'__cxxabiv1::__forced_unwind
.rdata:00414198 __ZTVN10__cxxabiv115__forced_unwindE db    0
.rdata:00414199                 db    0
.rdata:0041419A                 db    0
.rdata:0041419B                 db    0
.rdata:0041419C                 db 0E8h ; и
.rdata:0041419D                 db  3Eh ; >
.rdata:0041419E                 db  41h ; A
.rdata:0041419F                 db    0
.rdata:004141A0                 db    0
.rdata:004141A1                 db    0
.rdata:004141A2                 db    0
.rdata:004141A3                 db    0
.rdata:004141A4                 db    0
.rdata:004141A5                 db    0
.rdata:004141A6                 db    0
.rdata:004141A7                 db    0
.rdata:004141A8                 db  80h ; Ђ
.rdata:004141A9                 db 0FAh ; ъ
.rdata:004141AA                 db  40h ; @
.rdata:004141AB                 db    0
.rdata:004141AC                 public __ZTVN10__cxxabiv117__class_type_infoE
.rdata:004141AC ; `vtable for'__cxxabiv1::__class_type_info
.rdata:004141AC __ZTVN10__cxxabiv117__class_type_infoE dd 0
.rdata:004141AC                                         ; DATA XREF: .rdata:`typeinfo for'__cxxabiv1::__forced_unwind↑o
.rdata:004141AC                                         ; .rdata:`typeinfo for'__cxxabiv1::__foreign_exception↑o ...
.rdata:004141AC                                         ; offset to this
.rdata:004141B0                 dd offset __ZTIN10__cxxabiv117__class_type_infoE ; `typeinfo for'__cxxabiv1::__class_type_info
.rdata:004141B4 off_4141B4      dd offset __ZN10__cxxabiv117__class_type_infoD1Ev
.rdata:004141B4                                         ; DATA XREF: __cxxabiv1::__class_type_info::~__class_type_info()+6↑o
.rdata:004141B4                                         ; __cxxabiv1::__class_type_info::~__class_type_info()↑o ...
.rdata:004141B4                                         ; __cxxabiv1::__class_type_info::~__class_type_info()
.rdata:004141B8                 dd offset __ZN10__cxxabiv117__class_type_infoD0Ev ; __cxxabiv1::__class_type_info::~__class_type_info()
.rdata:004141BC                 dd offset __ZNKSt9type_info15__is_function_pEv ; std::type_info::__is_function_p(void)
.rdata:004141C0                 dd offset __ZNKSt9type_info15__is_function_pEv ; std::type_info::__is_function_p(void)
.rdata:004141C4                 dd offset __ZNK10__cxxabiv117__class_type_info10__do_catchEPKSt9type_infoPPvj ; __cxxabiv1::__class_type_info::__do_catch(std::type_info const*,void **,uint)
.rdata:004141C8                 dd offset __ZNK10__cxxabiv117__class_type_info11__do_upcastEPKS0_PPv ; __cxxabiv1::__class_type_info::__do_upcast(__cxxabiv1::__class_type_info const*,void **)
.rdata:004141CC                 dd offset __ZNK10__cxxabiv117__class_type_info11__do_upcastEPKS0_PKvRNS0_15__upcast_resultE ; __cxxabiv1::__class_type_info::__do_upcast(__cxxabiv1::__class_type_info const*,void const*,__cxxabiv1::__class_type_info::__upcast_result &)
.rdata:004141D0                 dd offset __ZNK10__cxxabiv117__class_type_info12__do_dyncastEiNS0_10__sub_kindEPKS0_PKvS3_S5_RNS0_16__dyncast_resultE ; __cxxabiv1::__class_type_info::__do_dyncast(int,__cxxabiv1::__class_type_info::__sub_kind,__cxxabiv1::__class_type_info const*,void const*,__cxxabiv1::__class_type_info const*,void const*,__cxxabiv1::__class_type_info::__dyncast_result &)
.rdata:004141D4                 dd offset __ZNK10__cxxabiv117__class_type_info20__do_find_public_srcEiPKvPKS0_S2_ ; __cxxabiv1::__class_type_info::__do_find_public_src(int,void const*,__cxxabiv1::__class_type_info const*,void const*)
.rdata:004141D8                 public __ZTVN10__cxxabiv119__foreign_exceptionE
.rdata:004141D8 ; `vtable for'__cxxabiv1::__foreign_exception
.rdata:004141D8 __ZTVN10__cxxabiv119__foreign_exceptionE db    0
-----------------------------
И так далее...


А вот та же vtable, но уже без RTTI:

Код

 public __ZTV10CTestNode2
.rdata:004140E4 ; `vtable for'CTestNode2
.rdata:004140E4 __ZTV10CTestNode2 db    0
.rdata:004140E5                 db    0
.rdata:004140E6                 db    0
.rdata:004140E7                 db    0
.rdata:004140E8                 db    0
.rdata:004140E9                 db    0
.rdata:004140EA                 db    0
.rdata:004140EB                 db    0
.rdata:004140EC off_4140EC      dd offset __ZN10CTestNode2D1Ev
.rdata:004140EC                                         ; DATA XREF: CTestNode2::~CTestNode2()+9↑o
.rdata:004140EC                                         ; _main+395↑o
.rdata:004140EC                                         ; CTestNode2::~CTestNode2()
.rdata:004140F0                 dd offset __ZN10CTestNode2D0Ev ; CTestNode2::~CTestNode2()
.rdata:004140F4                 dd offset __ZN10CTestNode211TestVMethodEv ; CTestNode2::TestVMethod(void)
.rdata:004140F8                 public __ZTVN10__cxxabiv115__forced_unwindE
.rdata:004140F8 ; `vtable for'__cxxabiv1::__forced_unwind
.rdata:004140F8 __ZTVN10__cxxabiv115__forced_unwindE db 4 dup(0), 0C4h, 3Eh, 41h, 9 dup(0), 0A0h, 0F0h, 40h
.rdata:004140F8                 db 0
.rdata:0041410C                 public __ZTVN10__cxxabiv117__class_type_infoE
.rdata:0041410C ; `vtable for'__cxxabiv1::__class_type_info
.rdata:0041410C __ZTVN10__cxxabiv117__class_type_infoE dd 0
.rdata:0041410C                                         ; DATA XREF: .rdata:`typeinfo for'__cxxabiv1::__forced_unwind↑o
.rdata:0041410C                                         ; .rdata:`typeinfo for'__cxxabiv1::__foreign_exception↑o ...
.rdata:0041410C                                         ; offset to this
.rdata:00414110                 dd offset __ZTIN10__cxxabiv117__class_type_infoE ; `typeinfo for'__cxxabiv1::__class_type_info
.rdata:00414114 off_414114      dd offset __ZN10__cxxabiv117__class_type_infoD1Ev
.rdata:00414114                                         ; DATA XREF: __cxxabiv1::__class_type_info::~__class_type_info()+6↑o
.rdata:00414114                                         ; __cxxabiv1::__class_type_info::~__class_type_info()↑o ...
.rdata:00414114                                         ; __cxxabiv1::__class_type_info::~__class_type_info()
.rdata:00414118                 dd offset __ZN10__cxxabiv117__class_type_infoD0Ev ; __cxxabiv1::__class_type_info::~__class_type_info()
.rdata:0041411C                 dd offset __ZNKSt9type_info15__is_function_pEv ; std::type_info::__is_function_p(void)
.rdata:00414120                 dd offset __ZNKSt9type_info15__is_function_pEv ; std::type_info::__is_function_p(void)
.rdata:00414124                 dd offset __ZNK10__cxxabiv117__class_type_info10__do_catchEPKSt9type_infoPPvj ; __cxxabiv1::__class_type_info::__do_catch(std::type_info const*,void **,uint)
.rdata:00414128                 dd offset __ZNK10__cxxabiv117__class_type_info11__do_upcastEPKS0_PPv ; __cxxabiv1::__class_type_info::__do_upcast(__cxxabiv1::__class_type_info const*,void **)
.rdata:0041412C                 dd offset __ZNK10__cxxabiv117__class_type_info11__do_upcastEPKS0_PKvRNS0_15__upcast_resultE ; __cxxabiv1::__class_type_info::__do_upcast(__cxxabiv1::__class_type_info const*,void const*,__cxxabiv1::__class_type_info::__upcast_result &)
.rdata:00414130                 dd offset __ZNK10__cxxabiv117__class_type_info12__do_dyncastEiNS0_10__sub_kindEPKS0_PKvS3_S5_RNS0_16__dyncast_resultE ; __cxxabiv1::__class_type_info::__do_dyncast(int,__cxxabiv1::__class_type_info::__sub_kind,__cxxabiv1::__class_type_info const*,void const*,__cxxabiv1::__class_type_info const*,void const*,__cxxabiv1::__class_type_info::__dyncast_result &)
.rdata:00414134                 dd offset __ZNK10__cxxabiv117__class_type_info20__do_find_public_srcEiPKvPKS0_S2_ ; __cxxabiv1::__class_type_info::__do_find_public_src(int,void const*,__cxxabiv1::__class_type_info const*,void const*)
.rdata:00414138                 public __ZTVN10__cxxabiv119__foreign_exceptionE
.rdata:00414138 ; `vtable for'__cxxabiv1::__foreign_exception
.rdata:00414138 __ZTVN10__cxxabiv119__foreign_exceptionE db    0
-----------------------------
И так далее...


Видно, что там, где ранее был адрес typeinfo, теперь просто нулевое поле. Однако весь ненужный теперь функционал typeinfo никуда не делся, он по-прежнему в коде!

Собственно, ключевой вопрос: как удалить RTTI полностью из кода программы?
Спасибо.

Это сообщение отредактировал(а) LShadow77 - 10.8.2019, 00:10
PM MAIL   Вверх
LShadow77
Дата 9.8.2019, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 17.10.2011

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



Так, кажется разобрался. Оказывается, проблема не только в виртуальных функциях, но ещё и в стандартном операторе new()! Переопределил оператор new() и всё стало хорошо: Код моей тестовой программы сократился с 157680 байт до 48128 байт! И балласт исчез:
Код

.rdata:00406400                 public __ZTV10CTestNode2
.rdata:00406400 ; `vtable for'CTestNode2
.rdata:00406400 __ZTV10CTestNode2 db    0
.rdata:00406401                 db    0
.rdata:00406402                 db    0
.rdata:00406403                 db    0
.rdata:00406404                 db    0
.rdata:00406405                 db    0
.rdata:00406406                 db    0
.rdata:00406407                 db    0
.rdata:00406408 off_406408      dd offset __ZN10CTestNode2D1Ev
.rdata:00406408                                         ; DATA XREF: CTestNode2::~CTestNode2()+9↑o
.rdata:00406408                                         ; _main+395↑o
.rdata:00406408                                         ; CTestNode2::~CTestNode2()
.rdata:0040640C                 dd offset __ZN10CTestNode2D0Ev ; CTestNode2::~CTestNode2()
.rdata:00406410                 dd offset __ZN10CTestNode211TestVMethodEv ; CTestNode2::TestVMethod(void)
.rdata:00406414 aGccGnu820      db 'GCC: (GNU) 8.2.0',0
.rdata:00406425                 align 4
.rdata:00406428 aGccGnu820_0    db 'GCC: (GNU) 8.2.0',0
.rdata:00406439                 align 4
.rdata:0040643C aGccMingwOrgGcc db 'GCC: (MinGW.org GCC-8.2.0-3) 8.2.0',0
.rdata:0040645F                 align 10h
.rdata:00406460 aGccMingwOrgGcc_0 db 'GCC: (MinGW.org GCC-8.2.0-3) 8.2.0',0
............................


Похоже, что стандартный оператор new() находится в том же модуле, что и RTTI, вот и тянет довесок в код... 
Итог: переопределение операторов new() и delete() совместно с опцией компилятора -fno-rtti сокращают размер скомпилированного кода сразу на 100 килобайт! Ну, если быть уж совсем точным и удалить из приложения всю символьную информацию, то экономия составит чистых 64 Кб кода, что тоже относительно немало.
Может кому-то это наблюдение окажется полезным...)
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

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

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

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

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


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

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


 




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


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

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