Распределение памяти с помощью диспетчера хранения приводит к не чистой функции (RM 13.1 (22)) - PullRequest
0 голосов
/ 25 сентября 2018

Портирование старого кода на новую машину CentOs Linux.Я использую linux gnat с парой флагов:

Default_Switches ("ada") use ("-fstack-check", "-g", "-gnatVr", "-gnato", "-gnatE", "-gnatwmuv", "-gnata", "-m32");

, и у меня есть версия gnat:

gcc-gnat.i686   4.8.5-11.el7

Так что это предварительные условия.Теперь у меня есть точно работающий самописный менеджер хранилища, который вызывается

St_Wa.Alloc(StoragePool, BitSize)

Так что теперь к моей проблеме и, честно говоря, я не совсем понимаю, почему компилятор выходит из строя, поэтому я быбудьте очень благодарны за подробное объяснение, почему оно не работает!

function AllocMem(StoragePool : in St_Wa.Mem_Pool_Type;
                  Option: in Option_Type) 
                  return Option_Ref is

 subtype New_Type is Option_Type (Option.Kind);

 New_Option : New_Type;

for New_Option use at St_Wa.Alloc( StoragePool => StoragePool, 
                                    BitSize => New_Type'Size)
begin 
    Bl_Bl.Move( ... sth happens here ... )
    return Pointer(New_Option'Address);
end AllocMem;

Принимая во внимание:

type Option_Type ( Kind : Option_Kind_Type := Marker) is
record
  Next : Option_Ref;
  case Kind is
    when First_Procedure => First_Procedure : First_Procedure_Type;
    when Sec_Procedure => Sec_Procedure : Sec_Procedure_Type;
  end case;
end record;

И я получаю следующую ошибку:

invalid address clause for initialized object "New_Option"
function "Alloc" is not pure (RM 13.1 (22))

DoЯ получаю эту ошибку, потому что у меня есть случай переключения в типе с условиями и, следовательно, размер определяется только в зависимости от вида?Как я могу избежать этого, не переписывая все?

1 Ответ

0 голосов
/ 25 сентября 2018

Я получаю эту ошибку, потому что у меня есть корпус переключателя в типе с условиями и, следовательно, размер определяется только в зависимости от вида?

Нет.Абзац, на который ссылается сообщение об ошибке (RM 13.1 (22)) в LRM, гласит:

Реализация не должна поддерживать элементы представления, содержащие нестатические выражения, за исключением того, что реализация должна поддерживать элемент представления длязаданной сущности, если каждое нестатическое выражение в элементе представления является именем, которое статически обозначает константу, объявленную перед сущностью.

Теперь элемент представления здесь является вызовом Alloc, поскольку ваш код:

for New_Option use at St_Wa.Alloc(StoragePool => StoragePool, 
                                  BitSize => New_Type'Size);

в стиле Ada83 для

for New_Option'Address use St_Wa.Alloc(StoragePool => StoragePool, 
                                       BitSize => New_Type'Size);

И поскольку Alloc (...) является вызовом функции, это не статическое выражение, поскольку статические функции, согласно RM 4.9:

  • предопределенный оператор, все параметры и типы результатов которого являются скалярными типами, ни один из которых не является потомком формальных скалярных типов;
  • предопределенный оператор конкатенации, тип результата которого является строковым типом;
  • литерал перечисления;
  • атрибут, определяемый языком, который является функциейЕсли префикс обозначает статический скалярный подтип и если параметры и типы результатов являются скалярными.

Поскольку Alloc не является ни одним из вышеперечисленных, как утверждает RM 13.1, реализацияне нужно поддерживать его в элементе представления.Однако фактическое сообщение об ошибке говорит нам, что «Alloc» не является чистым , поэтому GNAT сообщает, что оно поддержит это, если Alloc будет чистым.

Так что один из способов исправить этобыть чистым Alloc, что означает: Добавить pragma Pure; в пакет St_Wa, который содержит Alloc.Возможность этого зависит от пакета и может потребовать дополнительных изменений.

Если это неосуществимо, RM 13.1 (22) намекает на другой способ: нестатическое выражение должно поддерживаться, если оно обозначает константу, объявленную ранее.лицо.Таким образом, это должно работать:

My_Address : constant System.Address :=
  St_Wa.Alloc(StoragePool => StoragePool, BitSize => New_Type'Size);

New_Option : New_Type;

for New_Option use at My_Address;
...