IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

3 страниц V < 1 2 3 >  
 Ответить  Открыть новую тему 
> Отлов утечек памяти - GNAT, (разделено)
сообщение
Сообщение #21


Гость






После того, как внес изменения (если делал это через IDE) Project -> Save All делал? В настройках проекта Recompile if switches changed стоит? Clean All (в самом крайнем случае) для удаления всех библиотек, и потом пересборка проекта - помогает?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #22


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> В настройках проекта Recompile if switches changed стоит?

Поставил, заработало.

Я видел эту галочку, думал, что это как самоочевидное должно быть, поэтому понял её, как "перекомпилировывать только если что-то там менялось", для надёжности я её ставить не стал, потому что помню, как в Дельфи7 я компилировал прогу с какими-то галочками, а потом меня спрашивали - а что это программа выкидывает окно при ненайденном файле? А я смотрю - не стоит галка на проверках ввода-вывода. Что такое, думаю, за бред? А оказалось, что чтобы галочки заработали, надо там вообще всё пересобирать. Вот и не доверяю я частичной пересборке.
Кстати, полная сборка там была на порядок быстрее.

Сообщение отредактировано: TarasBer -


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #23


Гость






Ну, там например не было препроцессора. А здесь мало того, что у тебя надо файлы компилировать, так еще и препроцессором проходить теперь надо - это тоже время. Плюс ко всему, скорость сборки зависит от режима (дебаг это или оптимизация, или профайлер). Да и возможностей у языка больше. Но все равно, скорость сборки у Ады на порядки выше С++-ной...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #24


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> Ну, там например не было препроцессора.

В таком виде он там был.
{$IFDEF} {$ENDIF} я пользовался по полной.
Или тут что-то ещё есть?

> Плюс ко всему, скорость сборки зависит от режима (дебаг это или оптимизация, или профайлер).

Быстрее всего - неоптимизированный неотладочный режим?

> Да и возможностей у языка больше.

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


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #25


Гость






Цитата
В таком виде он там был.
{$IFDEF} {$ENDIF} я пользовался по полной.
Это не препроцессор. Вот когда перед компиляцией файла он скармливается внешней программе, которая из него убирает всё ненужное, руководствуясь известными ей директивами и параметрами, переданными в нее - вот это препроцессор. То, что было в Паскаль/Дельфи - это условная компиляция. Причем самая примитивная. ifdef/ifndef/ifopt/else/endif - это все, что есть в Дельфи. А комбинировать условия через Or/And? Я ж могу захотеть и задать несколько ключей, а потом написать

#if Debugging and Test_Leaks
-- ...
#end if;

А получить строковое представление ключа в рантайме? Вот откомпилировал я программу с
& ("-gnateDMyStr=""Test""");
, и хочу вывести строку, переданную в MyStr на печать. Как такое сделать в Дельфи? Я-то вот так сделаю:

s : String := $MyStr;

, и все, обычная строка, что хочешь с ней - то и твори...

Цитата
Быстрее всего - неоптимизированный неотладочный режим?
Да, default в комбобоксе режимов. Хотя у меня есть ощущение, что под Windows этот комбобокс как-то не так работает. Вообще он должен при переключении менять в настройках проекта некоторые свойства, он этого не делает, насколько я помню. Приходится вручную лазить в свойства проекта, и там устанавливать самостоятельно. Хорошо, что хоть компилирует в разные папки...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #26


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> А комбинировать условия через Or/And?

or:

{$IFDEF COND1}
{$DEFINE COND3}
{$ENDIF}

{$IFDEF COND2}
{$DEFINE COND3}
{$ENDIF}

and:

{$IFDEF COND1}
{$IFDEF COND2}
{$DEFINE COND3}
{$ENDIF}
{$ENDIF}

> А получить строковое представление ключа в рантайме?

Зачем это?
const S: string = 'test';



--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #27


Гость






Цитата
Зачем это?
Затем, что не всегда допустимо править исходники. А иногда - просто невозможно обойтись другими средствами. Вот если я хочу в программу запихать дату и время ее сборки (или характеристики машины, на которой производилась сборка) - твои действия?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #28


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


> Вот если я хочу в программу запихать дату и время ее сборки

А разве константа, определённая через функцию GetTime, не превратится во время сборки (ведь константы считаются компилятором, а не программой при старте)?
Аналогично про характеристики - константу определить через GetHardSerialNumber.

> Но все равно, скорость сборки у Ады на порядки выше С++-ной...

С++ плохой пример по скорости сборки, не надо с ним сравнивать.


По поводу самой функции Do_Tree возражений нету, кстати?


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #29


Гость






Цитата
А разве константа, определённая через функцию GetTime, не превратится во время сборки (ведь константы считаются компилятором, а не программой при старте)?
Ага, щаззз...
with ada.Calendar;
with ada.Calendar.Formatting;
...
Time : constant Ada.Calendar.Time := Ada.Calendar.Clock; -- Перед Main-ом
...
Ada.Text_IO.Put_Line (Item => Ada.Calendar.Formatting.Image (Time) ); -- Проверяем
А теперь собираем программу и запускаем EXE-шник несколько раз с интервалом в несколько десятков секунд. Что получается? Получается, что текущее время берется при старте программы, а вот потом изменить его программа не даст, ибо constant. Так как быть, если мне надо время/конфиг именно при сборке? Я поступаю просто донельзя: есть скрипт, собирающий в строку всю нужную мне информацию, эта строка передается в gnatprep, и строка жестко зашивается в EXE-шник...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #30


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


То есть константы считаются не компилятором, а программой при старте?
Это как-нибудь настраивается? Или считается, что скорость старта программы не важна?

Сообщение отредактировано: TarasBer -


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #31


Гость






Цитата
То есть константы считаются не компилятором, а программой при старте?
Ada.Calendar.Clock - это все-таки функция. То есть, ты хочешь, чтобы при компиляции еще и вызывались функции, и результат их работы запоминался как обычная константа? Этого не было и не будет никогда.

Для простых типов данных - да, компилятор в состоянии описать настоящую константу. Для сложных - нет. Как я могу, скажем, получить истинную константу для Unbounded_String, если мне для этого надо вызвать процедуру Initialize? Только на этапе запуска программы... А вот для Ch : constant Character := 'A'; проблем не будет - для символов ничего не надо выполнять, компилятор подставит сразу нужное значение, еще в compile-time...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #32


Гость






Цитата
По поводу самой функции Do_Tree возражений нету, кстати?
Я бы немного "разгрузил" функцию от множества if/end if. То есть, вынес бы выброс исключений в отдельные функции (там всего два вида выбрасывается, так что всего 2 доп. функции - Check_IA и Check_BB), по проверке условия. Один фиг, когда ты получаешь исключение - получаешь и Call stack traceback locations, которые можно преобразовать в названия процедур:

Прикрепленное изображение

Ну, и вот так я б не написал:
Цитата
            while Was_Token loop
-- пока у нового оператора приоритет выше, чем у текущего
case Last_Token.Kind is
when Operator =>
if Less(KP, To_Pair(Last_Token), Last_Token.Right_Associated) then
High_Level := True; -- повышаем уровень
Do_Tree(T, To_Pair(Last_Token));
else
exit;
end if;
when Close_Bracket | Delimiter => exit;
when others =>
Position.all := Old_Position;
Was_Token := False;
return;
end case;
end loop;
, лишние if/else, я б сделал так:
            while Was_Token loop
-- пока у нового оператора приоритет выше, чем у текущего
case Last_Token.Kind is
when Operator =>
exit when not Less(KP, To_Pair(Last_Token), Last_Token.Right_Associated);
High_Level := True; -- повышаем уровень
Do_Tree(T, To_Pair(Last_Token));
when Close_Bracket | Delimiter => exit;
when others =>
Position.all := Old_Position;
Was_Token := False;
return;
end case;
end loop;
 К началу страницы 
+ Ответить 
сообщение
Сообщение #33


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Ну это тоже можно.
Гораздо хуже, что операторы и функции слиты в одну ветку, это не нужно, просто была задумка, чтобы каждый оператор мог быть и функцией, но я решил для + и * сделать отдельные функции.
Вопрос такой: как переписать через Iterate процедуры To_Vector и Copy_Childs, чтобы выглядело не хуже, чем было?
Ещё в выражении не надо писать в конце =, просто парсер молча останавливается, когда видит что-то совсем незнакомое, а текущее выражение корректно обработано.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #34


Гость






А что мне надо сделать (какую строку входную заставить обработать), чтоб вызвалось Copy_Childs?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #35


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


В данном случае оно не вызывается, потому что программа нигде не копирует функции. Но мало ли, понадобится, делать limited я не захотел.


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #36


Гость






Ну, тогда без проверки:

   function To_Vector (A : Key_Arr) return Key_Based_Vectors.Vector is

V : Key_Based_Vectors.Vector;
Arr_Index : Integer := A'First;

procedure Update (Item : in out Key_Base) is
begin
Item := A (Arr_Index);
Arr_Index := Arr_Index + 1;
end Update;

procedure Copy (C : Key_Based_Vectors.Cursor) is
begin
V.Update_Element (C, Update'Access);
end Copy;

use Key_Based_Vectors;
begin
Set_Length (V, A'Length);
V.Iterate (Copy'Access);
return V;
end To_Vector;
(почему использован Update_Element - ибо не может привести к реаллокации данных ни при каких условиях, следовательно индексация не собьется. Replace_Element от этого не застрахован).

И
	 function Copy_Childs (V : Vector) return Vector is

New_Vector : Vector;

procedure Deep_Copy (C : Func_Tree_Vectors.Cursor) is
begin
New_Vector.Replace_Element (C, Copy_Tree (Element (V, To_Index ( C ))));
end Deep_Copy;

begin
Set_Length (New_Vector, Length (V));
New_Vector.Iterate (Deep_Copy'Access);
return New_Vector;
end Copy_Childs;
 К началу страницы 
+ Ответить 
сообщение
Сообщение #37


Злостный любитель
*****

Группа: Пользователи
Сообщений: 1 755
Пол: Мужской

Репутация: -  62  +


Я так и не понял механизм контролируемых типов. Что именно в описании типа говорит компилятору, что тип контролируем?
Даже если дословно, буква в букву, переписать описание типа Controlled в другой модуль, то для него уже не работает автовызов Initialize и Finalize.
Надо, чтобы объект был именно унаследован от типа, называемого именно так-то, находящегося именно в модуле таком-то?

Ещё вопрос: почему ссылка на строку - это 64 бита? Указатель на начало и конец строки? Или указатель на начало и на длину?
Как хранятся дин массивы в памяти? Выделяются на стеке? Где хранятся их границы? Если выделяются на стеке, то где выделяются локальные переменные, объявленные после них, как хранятся ссылки на локальные переменные, объявленные до них?

Сообщение отредактировано: TarasBer -


--------------------
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #38


Гость






Цитата
Даже если дословно, буква в букву, переписать описание типа Controlled в другой модуль, то для него уже не работает автовызов Initialize и Finalize
Если дословно (буква в букву) переписать все, что нужно в другой модуль - то он у тебя даже не откомпилируется. Потому как
gnatmake -ws -c -u -P/home/forum_test/forum.gpr my_con.ads --subdirs=debug -cargs -g -O0
gcc -c -g -gnatVa -gnatw.e -gnata -g -gnatf -gnat05 -g -O0 -I- -gnatA /home/forum_test/my_con.ads
my_con.ads:3:06: warning: "system.finalization_root" is an internal GNAT unit
my_con.ads:3:06: warning: use of this unit is non-portable and version-dependent
my_con.ads:3:06: cannot depend on "Finalization_Root" (wrong categorization)
my_con.ads:21:24: warning: declaration of "=" hides one at line 19
my_con.ads:21:24: warning: declaration of "=" hides one in package Standard
gnatmake: "/home/forum_test/my_con.ads" compilation error

Finalization_Root - это внутренний пакет, нельзя его использовать в своих целях. Это жестко зашито в GNAT.

Цитата
Ещё вопрос: почему ссылка на строку - это 64 бита? Указатель на начало и конец строки? Или указатель на начало и на длину?
Смотри. Во-первых, это только в GNAT-компиляторе. Во всех остальных для access-типов всегда используются только thin-pointers (ага, худые). В GNAT-е же для неограниченных типов (массивы, строки, без жесткого указания длины, всякие Unbounded_String-и) используется "fat pointer" - это два указателя: один - на данные, другой - на границы массива. Но это, насколько я помню, отключаемо. Можно заставить компилятор всегда использовать thin-pointers, но это может сказаться на производительности.

Цитата
Как хранятся дин массивы в памяти? Выделяются на стеке?
Динамические - это какие? Вот эти:
procedure P(N : Integer) is
arr : array (1 .. N) of Integer; -- <--- ???
begin
-- ...
end P;
? Или которые через new выделяются?

Сообщение отредактировано: volvo -
 К началу страницы 
+ Ответить 
сообщение
Сообщение #39


Гость






> Это жестко зашито в GNAT.

То есть работает именно с типом, унаследованного именно от Controlled из именно этого пакета?

> Динамические - это какие?

Динамические - это которые в declare пишутся.


i := 5;
...
declare
a: array (1..i) of integer;
... j := 5;
declare
b: array(1..j) of integer;


...итд

В голове только одна идея - сначала вычисляется, где на стеке будут лежать переменные с известным размером (и указатели на массивы), и ставятся подряд, а массивы аллоцируются на стеке (при этом локальные переменные известного размера и указатели на массивы адресуются относительно esp, а ebp сдвигается за массив), и так как их расположение уже не предсказать на этапе компиляции, обращение к ним идёт через указатель.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #40


Гость






Хм. Ну, разницы с тем, что я привел - никакой. И там и там на этапе компиляции размер определить нельзя, поэтому компилятор использует одинаковую стратегию. Почитать об этом можно в книге Michael L. Scott "Programming Language Pragmatics" (перевода не видел, к сожалению).

Вот тут есть кусками: Как раз на нужной странице, если надо полную версию - скажи, я положу куда-нибудь, там около 8 Мб...
 К началу страницы 
+ Ответить 

3 страниц V < 1 2 3 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 27.10.2020 17:21
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name