Domanda

I have a specification of a function that acts like a constructor. The specification of the function is

function Create_Controller return Type_Controller;

Also, in the specification file, I have the Type_Controller type, which is an access. I copy the relevant fragment:

type Type_Controller_Implementation;
type Type_Controller is access Type_Controller_Implementation;

So, this is what I've attempted:

function Create_Controller return Type_Controller
is
   My_Controller : aliased Type_Controller_Implementation;
begin
   return My_Controller'Access;
end Create_Controller;

I tried to compile the program without the aliased keyword, but then, the compiler says:

prefix of "Access" attribute must be aliased

So, I put the aliased keyword and the compiler now suggests that I should change the specification:

result must be general access type
add "all" to type "Controlador_De_Impresion" defined at controller.ads

The problem is that I'm not allowed to change the specification. I've read the chapter about access types in the Ada Programming Wikibook, but I still don't understand why my code doesn't work. What am I doing wrong?

È stato utile?

Soluzione

The implementation of the Create_Controller function body is incorrect. Were it to work as coded, you'd be returning a pointer to a variable local to that function body's scope...which would be immediately lost upon returning from the function, leaving you with an invalid pointer.

No, an instance of the type needs to be allocated and returned. If there's no explicit initialization that needs to occur you can simply do:

return new Type_Controller_Implementation;

If there is some initialization/construction that has to occur, then:

function Create_Controller return Type_Controller
is
   My_Controller : Type_Controller := new Type_Controller_Implementation;
begin
   -- Set fields of My_Controller

     ...

   return My_Controller;
end Create_Controller;

Altri suggerimenti

When you declare an access type as access T, you're saying that "this is a pointer to a T and it must point to objects of type T allocated from a pool". (That is, allocated with a new keyword.) When you declare an access type as access all T, you're saying that it can point either to a T allocated from a pool, or to an aliased variable of type T.

If the type is declared as access T and you can't change it, then all access values of the type have to point to something allocated with new. You can't make it point to a variable (even to a "global" variable that isn't located on the stack).

The reasons for this are historical, I think. The first version of Ada (Ada 83) only had "pool-specific types." You couldn't make an access value point to some other variable at all, without trickery. This meant that a compiler could implement access values as indexes into some storage block, or as some other value, instead of making them the actual address of an object. This could save space (an access value could be smaller than an address) or allow more flexibility in how pool memory was managed. Allowing access values to point directly to objects takes away some of that flexibility. I think that's why they decided to keep the old meaning, for backward compatibility, and require an all keyword to indicate the new kind of access.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top