Форум: "Потрепаться";
Текущий архив: 2004.05.23;
Скачать: [xml.tar.bz2];
ВнизОптимизация при линковке: проблема мертвого кода. Найти похожие ветки
← →
PVOzerski © (2004-04-29 13:45) [0]Хотелось бы обсудить навеянное размышлениями о багах во FreePascal и нереализованных возможностях в Object Pascal вообще. Возьмем примерчик.
type
t1=object
constructor Create;
destructor Destroy;
procedure test;virtual;
end;
t2=object(t1)
procedure test;virtual;
end;
constructor t1.Create;
begin
end;
destructor t1.Destroy;
begin
end;
procedure t1.test;
begin
writeln("Вася");
end;
procedure t2.test;
begin
end;
var
obj:t2;
begin
obj.Create;
obj.test;
obj.Destroy;
end.
Вопрос: почему в exe, полученным из него борландовскими компиляторами, не будет слова "Вася", но если переделать с объектов на классы, то оно будет? А FreePascal оставит Васю в бинарнике в обоих случаях. Можно ли научить компилятор с этим побороться? Я имею в виду не поиск ключей, а изменения в коде компилятора (ясно, что речь в данном случае идет не о Delphi, а о FreePascal).
← →
Verg © (2004-04-29 14:01) [1]Ну так, если нет ни одной ссылки на метод T1.Test, то и сам метод компоновать бессмысленно.
У классов VMT представляет собой связанный список VMTs всего дерева наследственности, а у объектов каждому типу - одна VMT.
Если нет ни одного упоминания об объекте - предке, то и VMT для него можно не создавать. Нет вмт - нет ссылки на виртуальные методы, нет ни одной ссылки - незачем и эти методы прикомпоновывать..
← →
PVOzerski © (2004-04-29 14:09) [2][1]
Собственно говоря, меня интересует не столько то, как оставить этого Васю в примере 1, а как избавиться от него в примере 2.
Вот что FreePascal выдает из кода с классами, если его попросить сгенерить asm-текст (естественно, выдержки).
ALIGN 4
PUBLIC VMT_P$PROGRAM_T1
VMT_P$PROGRAM_T1 DD 4,4294967292
DD offset VMT_SYSTEM_TOBJECT
DD offset _$PROGRAM$_L6
DD 0,0
DD offset _$PROGRAM$_L4
DD 0,0,0,0,0
DD offset SYSTEM_TOBJECT_$__DESTROY
DD offset SYSTEM_TOBJECT_$__NEWINSTANCE
DD offset SYSTEM_TOBJECT_$__FREEINSTANCE
DD offset SYSTEM_TOBJECT_$__SAFECALLEXCEPTION$TOBJECT$POINTER
DD offset SYSTEM_TOBJECT_$__DEFAULTHANDLER$formal
DD offset SYSTEM_TOBJECT_$__AFTERCONSTRUCTION
DD offset SYSTEM_TOBJECT_$__BEFOREDESTRUCTION
DD offset SYSTEM_TOBJECT_$__DEFAULTHANDLERSTR$formal
DD offset P$PROGRAM_T1_$__TEST
ALIGN 4
_$PROGRAM$_L9 DB 2
DB "t2"
ALIGN 4
PUBLIC VMT_P$PROGRAM_T2
VMT_P$PROGRAM_T2 DD 4,4294967292
DD offset VMT_P$PROGRAM_T1
DD offset _$PROGRAM$_L9
DD 0,0
DD offset _$PROGRAM$_L7
DD 0,0,0,0,0
DD offset SYSTEM_TOBJECT_$__DESTROY
DD offset SYSTEM_TOBJECT_$__NEWINSTANCE
DD offset SYSTEM_TOBJECT_$__FREEINSTANCE
DD offset SYSTEM_TOBJECT_$__SAFECALLEXCEPTION$TOBJECT$POINTER
DD offset SYSTEM_TOBJECT_$__DEFAULTHANDLER$formal
DD offset SYSTEM_TOBJECT_$__AFTERCONSTRUCTION
DD offset SYSTEM_TOBJECT_$__BEFOREDESTRUCTION
DD offset SYSTEM_TOBJECT_$__DEFAULTHANDLERSTR$formal
DD offset P$PROGRAM_T2_$__TEST
Что нам мешает из кусков, обозначенных метками VMT_P$PROGRAM_T1 и VMT_P$PROGRAM_T2, выкинуть ссылки на неиспользуемые методы, не нарушая при этом целостности связанного списка?
← →
Ev_genus © (2004-04-29 14:10) [3]Не все компиляторы одинаково определяют понятия класов и объектов
← →
Ev_genus © (2004-04-29 14:10) [4]Не все компиляторы одинаково определяют понятия класов и объектов
← →
PVOzerski © (2004-04-29 14:15) [5]2Ev_genus:
Сейчас я говорю, главным образом, о компиляторе FreePascal и языке Object Pascal/Delphi. А фразу "Не все компиляторы одинаково определяют понятия класов и объектов" никак не могу понять. Это о чем? О том, что у них разная внутренняя организация или о том, что у них разный синтаксис? Так вот, я о том, как бы улучшить внутреннюю организацию при сохранении нынешнего синтаксиса.
← →
Verg © (2004-04-29 14:24) [6]
> PVOzerski © (29.04.04 14:09) [2]
Чесно говоря я и сам не знаю для чего в случае классов формируют всегда полную VTM.
Будь-то бы для того, чтобы в runtime можно было вызывать любой виртуальный метод предка пройдясь по списку VTM. Но это так, предположения в стиле "что в голову пришло"....
← →
Verg © (2004-04-29 14:30) [7]Если нет реальных ссылок на класс T1 (ни приведения типов, ни переменных(параметров) данного класса), то почему бы не исключать из кода виртуальые его методы, на которые нет ссылок?
Пока сообразить не могу, но может есть какая-то причина?
← →
SPeller © (2004-04-29 14:58) [8]Может всё-таки защита от "хакерских" способов доступа к методам классов? Даже не защита, а перестраховка, для надёжности?
← →
PVOzerski © (2004-04-29 15:08) [9]>Может всё-таки защита от "хакерских" способов доступа к методам >классов? Даже не защита, а перестраховка, для надёжности?
Так что, объекты стиля BP в этом не нуждаются, а классы нуждаются? Я вот думаю, как объяснить эту разницу. Не связано ли это как-то с поддержкой RTTI? Или с поддержкой виртуальных конструкторов? Интересно, можно ли написать код, способный создать экземляр класса, заранее не зная какого? Например, прочитав переменную типа метакласс из файла?
← →
Vuk © (2004-04-29 15:18) [10]to VOzerski © (29.04.04 15:08) [9]:
>Не связано ли это как-то с поддержкой RTTI?
Скорее всего да, т.к. должен быть боступ к RTTI предка.
>Или с поддержкой виртуальных конструкторов?
И это, видимо, тоже. Только, скорее всего, нужно говорить не о виртуальных конструкторах, а о метаклассах и возможностях работы с ними.
>Интересно, можно ли написать код, способный создать экземляр
>класса, заранее не зная какого? Например, прочитав переменную
>типа метакласс из файла?
Легально - только для зарегистрированных каким-либо образом классов. Нелегально - любых. Достаточно просканировать память и найти все классы в приложении. Для монолитного exe это делается легко. Для пакетов - не пробовал.
← →
PVOzerski © (2004-04-29 15:33) [11]>>Не связано ли это как-то с поддержкой RTTI?
>Скорее всего да, т.к. должен быть боступ к RTTI предка.
Хорошо, согласен. Тогда почему не разрешить выбрасывание мертвых виртуальных методов, если класс скомпилирован с {$M-}?
>>Интересно, можно ли написать код, способный создать экземляр
>>класса, заранее не зная какого? Например, прочитав переменную
Я вот сейчас сделал-таки экспериментик :^) Написал вот такую прогу.
uses
Classes;
type
tClass1=class
procedure Hello;virtual;
end;
tClass2=class(tClass1)
procedure Hello;override;
end;
tClassRef=class of tClass1;
procedure tClass1.Hello;
begin
writeln(1);
end;
procedure tClass2.Hello;
begin
writeln(1);
end;
var
c:tClassRef;
f:file of tClassRef;
begin
assign(f,"test.bin");
rewrite(f);
c:=tClass1;
write(f,c);
c:=tClass2;
write(f,c);
close(f);
end.
Запустил ее, получил файл. Потом добавил uses classes, перекомпилировал, опять запустил, опять получил файл. И сравнил содержимое этих двух файлов test.bin в хекс-вьюере. Оказалось, разное оно. И разное, видимо, потому, что модуль classes имеет инициализационную часть, вынуждающую программу использовать еще и другие классы. Значит, для того, чтобы трюк с загрузкой метакласса из файла гарантированно прошел правильно, программа должна иметь в себе список доступных классов, идентичный тому, каким располагает программа, этот файл метаклассов создавшая. Следовательно, содержать явно указанные в тексте использования (не только описания) всех классов, потенциально могущих быть созданными по метаклассу, полученному из файла. А значит, если таких использований нет, то всё лишнее, связанное с этим классом, пусть даже предком используемых, можно выкинуть из кода. Я прав?
← →
Матлабист (2004-04-29 16:04) [12]На самом деле, имхо, разрботчики Delphi решили не тянуть с собой весь геморой, связанный с выкидыванием мертвого кода для перекрытых виртуальных функций. В чем-то они правы.
Страницы: 1 вся ветка
Форум: "Потрепаться";
Текущий архив: 2004.05.23;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.041 c