Hacking pointers in fortran - pointers

Let's consider a complex structure in fortran
TYPE ComplexStrType
! Static as well as dynamic memory defined here.
END TYPE ComplexStrType
Defined a physical space (allocated on the stack memory I think) to use two variables of ComplexStrType:
TYPE(ComplexStrType) :: SomeComplexStr
TYPE(ComplexStrType) :: AnotherComplexStr
TYPE(ComplexStrType),POINTER :: PointerComplexStr
Then, I use SomeComplexStr to define a few stuff in the stack and to allocate a big space in the dynamic memory.
Now, suppose I want to point AnotherComplexStr to SomeComplexStr and forget space I have defined in the stack memory to AnotherComplexStr. To do that I use a simple but useful trick which converts some variable in a Target:
FUNCTION TargComplexStr(x)
IMPLICIT NONE
TYPE(ComplexStrType),INTENT(IN),TARGET :: x
TYPE(ComplexStrType),POINTER :: TargComplexStr
TargComplexStr => x
END FUNCTION TargComplexStr
And then I point PointerComplexStr to SomeComplexStr:
PointerComplexStr => TargComplexStr(SomeComplexStr)
Finally, I do AnotherComplexStr equal to PointerComplexStr:
AnotherComplexStr = PointerComplexStr
After that, it's supposed SomeComplexStr as well AnotherComplexStr are pointing to the same static and dynamic memory.
The thing is:
How can I free the space used by AnotherComplexStr used when I defined it at the beggining?
How do you recomend me nullify the pointers?
Is that practice safe, or do I have to expect some strange memory leaks on the execution?
If it's possible, how can I point the "pointed variable" to its original form? (Just in case I have to use it again as normal variable)
NOTE: It's useful because at the execution we can be decided if we want to use AnotherComplexStr as what it is, a complex and allocated structure, or we can switch it to be treated as a pointer and points it to another thing which already has the information we need. If there is another and easy way to do that, please tell me.

The "trick" that you are using in TargComplexStr does not work the way you think - that function offers nothing useful over simple pointer assignment.
You can associate a non-TARGET actual argument with a TARGET dummy argument, as you are doing, but when the procedure with the TARGET dummy argument completes, any pointers that were associated with the dummy argument become undefined (F2008 12.5.2.4 p11).
(Pointers can only be associated with targets, therefore something that isn't a target cannot have a pointer associated with it.)
This means that the result of the function is a pointer with undefined association status. It is not permitted to return a pointer with undefined association status from a function (F2008 12.6.2.2 p4).
The pointer assignment statement would then make PointerComplexStr become an undefined pointer. PointerComplexStr is then referenced in the assignment to AnotherComplexStr. It is not permitted to reference a pointer with undefined association status (F2008 16.5.2.8 p1).
Intrinsic assignment creates a copy of a value. This is the case even if the object on the right is a pointer - a copy of the value of the target of that pointer is created. Intrinsic assignment does not, at the level of the top data object being assigned[1], make one variable reference the storage of another. As far as I can tell, the intent of your entire example code could be replaced by:
AnotherComplexStr = ComplexStr
If you are trying to do something different to that, then you need to explain what it is that you are trying to do.
[1]: If the type of an object being assigned is a derived type that has a pointer components, then the definition of the value of the object includes the pointer association status of the pointer component, but not the value of the target of the component itself (F2008 4.5.8).

Related

How is the `'Old` attribute in a **Post** contract handled for access types that might got deallocated inside the function or procedure?

Assume having the following setup:
type My is new Integer;
type My_Acc is access My;
procedure Replace(Self : in out My_Acc; New_Int : Integer)
with Pre => New_Int /= Self.all, Post => Self'Old.all /= Self.all;
Note: Code above might not be fully valid, but I hope the concept is understandable.
Now what happens if Unchecked_Deallocation() is used on Self inside Replace
and a new Integer is allocated and set to Self (This should result in Self'Old pointing to a now invalid memory location)?
Does Ada keep kind of a snapshot where Self'Old points to the previous memory location, but before Unchecked_Deallocation() is executed?
If Self'Old would get invalid for use in the Post contract, how could you still access the previous value? Is it possible to create a manual snapshot in the Pre contract that can then be used in Post? Maybe it can be achieved using Ghost_Code?
I want to make everything in Spark, in case that changes something.
Edit: Fixed Self to in out as mentioned by Simon Wright.
Edit: Fixed type of Self to allow null
It may be that the latest versions of SPARK support access types; it used not to, at all.
First, your Not_Null_My_Acc needs to be a subtype of My_Acc, unless you meant it to be a type in its own right.
Second, you can’t deallocate Self inside Replace and allocate a new value; Self is in-mode, & hence not writable.
Third, you can’t apply ’Old to Self, because
warning: attribute "Old" applied to constant has no effect
What you can say is
Post => Self.all'Old /= Self.all;
In ARM 6.1.1(26ff) it says
Each X'Old in a postcondition expression that is enabled denotes a constant that is implicitly declared at the beginning of the subprogram body, entry body, or accept statement.
The implicitly declared entity denoted by each occurrence of X'Old is declared as follows:
...
X'Old : constant S := X;
... in other words, nothing fancy is expected, just a straight copy of (in this case) Self: not Self.all.
So, if your Replace deallocates Self, then Self’Old is a dangling reference, and erroneous.
I suggested previously that changing the postcondition to
Post => Self.all'Old /= Self.all;
would be safe; why wouldn’t that meet your requirements? is there something going on you haven’t told us about?
Note the subtle difference between Self’Old.all and Self.all’Old. The first one takes a copy of Self as it was before the call, which gets dereferenced after the call (by which time it’s pointing into hyperspace), while the second one dereferences the prior Self and copies the integer value it finds there; on return that’s still valid.

Specifying Referential transparency in ACSL

I want to find some ACSL annotation that can be applied to a function or function pointer to indicate that it has the property of referential transparency. Some way to say "this function will always return the same value when given the same arguments". So far I haven't found any such way. Can anyone point me to a way to express that?
Maybe some way to refer to an arbitrary logic function? If I could name an unknown logic boolean uknown_function(void* a, void* b) = /* this is unkown */; then I could document a function as having a postcondition that it's \result is equal to this arbitrary/unknown logic function?
The larger context is trying to do type-erased comparisons. I want to generally express the concept of "the user has given me void*s to work with and a bool (*)(void const*, void const*) to compare them with, and the user is guaranteeing to me that the function provided really is a strict partial order over whatever those pointers point to." If I had that, then I could start to describe properties of these type-erased objects being sorted, for example.
There is indeed no direct possibility to do that in ACSL: a function contract only specifies what happens during a single call of the function. You could indeed rely on a declared but left undefined logic function, with a reads clause that specifies the part of the C memory state that the function will need to compute its result, e.g.
/*# logic boolean unknown_function{L}(int* a, int* b) reads a[0 .. 1], b[2 .. 3]; */
but if you work with void *, without knowing the size of the underlying objects, this might be tricky to specify: unless the result of unknown_function relies solely on the value of the pointer, and not the content of the pointed object, in which case you don't need that reads trick.
Note in addition that contracts over function pointers are not supported yet, which will probably be an issue for what you intend to do if I understand correctly your last paragraph.
Finally, you might be interested in an upcoming plug-in, RPP, that proposes a way to specify, prove, and use properties relating several calls of one or more C function(s). It is described here and here, and a public release should happen in a not-too-distant future.

Safety of unrestricted_access

I have a complicated situation so I hope I can explain it properly.
I am using unchecked_access in combination with Ada.Finalization.Controlled types to pass references to vectors to an out of scope protected hashed map type on the Initialize procedure and removing references in the protected map on the finalize procedure. This way I thought I could assure that it would be impossible for any tasks to see out of scope references in the map.
However, the way I have the protected map organized snap shots are taken at each instance that is it used (effectively making it a normal hashed_map) which during the course of it being used vector references could go out of scope and the snap shot would still have the reference and attempt to access it.
I could see this creating 2 problems, either I am creating dangling pointers and trying to reference freed memory or my snapshot of the references is keeping the memory alive and I am leaving garbage around. I made a test to see what would happen and it seems the memory is still alive but is this really the case? Are there any other problems with my organization?
with Ada.Containers; use Ada.Containers;
with Ada.Containers.Vectors;
with Ada.Text_IO; use Ada.Text_IO;
procedure Test is
package V_Integer is new Ada.Containers.Vectors(Positive, Integer);
use V_Integer;
type V_Access is access all Vector;
Bar : V_Access;
begin
declare
Foo : aliased Vector;
begin
Bar := Foo'unrestricted_Access;
Foo.Append(3);
Foo.Append(5);
Put_Line("In scope: " & count_type'image(Length(Bar.all)));
end;
-- Will this reference always exist? Does it need to be freed?
Put_Line("Out of scope: " & count_type'image(Length(Bar.all)));
end Test;
begin
declare
Foo : aliased Vector;
begin
Bar := Foo'unrestricted_Access;
Foo.Append(3);
Foo.Append(5);
Put_Line("In scope: " & count_type'image(Length(Bar.all)));
end;
-- Will this reference always exist? Does it need to be freed?
Put_Line("Out of scope: " & count_type'image(Length(Bar.all)));
end Test;
Foo will be an object of type Vector, and it will probably exist on the stack. This object is itself a relatively small record, maybe about 6 32-bit words in GNAT (give or take a few, I haven't checked). It contains an access component that is used to get at all the vector's elements, and it contains some other housekeeping information. Bar will point to that small 6-word record. Essentially it will contain the address of something on the stack.
Since the small record Foo exists on the stack, when it goes out of scope, the stack space could be used for something else. Whether it will happen in this case, I don't know. But if you have another declare...begin...end block after the one in the example, local variables used by the new block could reuse the same stack space. Or if a procedure is called, that will put different stuff on the stack. In either case, the stack space previously used by Foo will be overwritten. And Bar will still point to the same address, but the area it points to will have been overrun with other data. So the result is likely to be wrong and could be a disaster.
I don't know if this is exactly how the implementation will work, but no matter how it's implemented, this code is potentially disastrous. The main things to keep in mind are: (1) If a variable goes out of scope, the space used for that variable may be reused at will; (2) if you use 'Unchecked_Access (or 'Unrestricted_Access) to set up a pointer to that variable, then after the variable goes out of scope, accessing data pointed to by the pointer could get you garbage or very bad behavior; (3) variables, whether aliased or not, are not (usually) dynamically allocated and the program does not need to (and cannot) explicitly free them, even if you've created a reference to them with 'Unchecked_Access.

Dealing with access type in Ada95

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?
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;
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.

Ada Actual for this must be a variable in out mode

I am making a program in Ada for Data Structures and Algorithms class.
My current problem is the error 'actual for "this" must be a variable'
I did some looking around and I read about it being because of in out mode, but I'm not entirely grasping why it's happening to me I guess.
The Examples I seen made sense but I guess since it's my coding I'm just not seeing it?
Procedure AddUnmarked(g:Grid; this:Linked_List_Coord.List_Type; c:Cell) is
cNorth : Cell := getCell(g, North(c));
cEast : Cell := getCell(g, East(c));
cSouth : Cell := getCell(g, South(c));
cWest : Cell := getCell(g, West(c));
Begin
if CellExists(g, cNorth) and not cNorth.IsMarked then
Linked_List_Coord.Append(this, cNorth.Coords);
elsif CellExists(g, cEast) and not cEast.IsMarked then
Linked_List_Coord.Append(this, cEast.Coords);
elsif CellExists(g, cSouth) and not cSouth.IsMarked then
Linked_List_Coord.Append(this, cSouth.Coords);
elsif CellExists(g, cWest) and not cWest.IsMarked then
Linked_List_Coord.Append(this, cWest.Coords);
end if;
End AddUnmarked;
before "this" is passed to the function it is a Linked_List of my self defined type Coord (2 integers). It is initialized and has had a Coordinate pair added to it before the list is passed to the function above in my code.
What it means is that the list cannot be modified unless you are passing it as a modifiable parameter, that is, in out.
To elaborate, think of LIST_TYPE as being a handle to a tagged-type object; in order to ensure that LIST_TYPE is valid you need to pass it in via an in parameter (or create/manipulate a local object), but to pass out your results you need an out parameter.
So, in order to do your operations on an already-existing object {and get the results back} you need in out.
In Ada, subroutine parameters all have a usage mode associated with them. The available modes are in, out, and in out*. If you don't specify a mode, (like you didn't in your code), then it defaults to in only.
The modes specify what you can do with that parameter on the inside of the subprogram. If you want to read a value passed in from outside the routine, it must have in on it. If you want to write to the parameter (and/or possibly have it read outside the routine), then it must have out on it.
Since none of your parameters have out on them, you cannot write to any of them.
(* - There's another possible mode: access, but that's an advanced topic).

Resources