Delphi Records - creating a pointer to it - pointers

I'm trying to see how I can create a pointer to a simple record.
I have searched for similar topics before posting but it's quite confusing.
I create A & B of which are actual Records.
I then have a variable C which I want to be just a 'pointer to this record'.
I don't want C to store its own value but just a pointer to either A or B.
But whenever C is read/written to,
it's actually being written to either A or B, whichever C is pointing to.
In other words, it's like a pointer to an Object, but I don't need an Object in my case.
Using Delphi 10.3 & 10.4 (if there's any difference), please highlight.
The code below results in Access Violation on first ShowMessage.
procedure TForm1.Button2Click(Sender: TObject);
type
TMyRecord = record
Field1 : integer;
end;
var
A : TMyRecord;
B : TMyRecord;
C : ^TMyRecord; // how to declare this as a pointer?
begin
A.Field1 := 1;
B.Field1 := 2;
C^ := A; // psuedo code to point to A
A.Field1 := 3;
showmessage( C^.Field1.ToString ); // result is 3
C.Field1 := 4;
showmessage( A.Field1.ToString ); // result is 4
C^ := B; // psuedo code to point to A
C.Field1 := 5;
showmessage( B.Field1.ToString ); // result is 5
// anything to free here to avoid memory loss?
end;

C should contain address of A, so make
C := #A;
and the rest of code will work as needed.
Also note that C.Field1 is implicit dereference, it really works as C^.Field1
For now
C^ := A;
denotes assigning contents of A record to memory region addressed by C, but this memory is not allocated - that's why access violation occurs. (To allocate memory, you can make New(C), but this is not needed for your purposes)
Also if you are going to actively use pointer to record, you can define type
PMyRecord = ^TMyRecord;

Related

Translating C flexible array members with length fields to Ada

While writing bindings for interfacing with C code, I am finding issues translating the numerous instances of structs with flexible array members to Ada, as such
struct example {
size_t length;
int body[];
};
I've been told for Ada that behaviors like that can be replicated with discriminated types, but I cannot find a way to use the length field as a discriminant, while maintaining the layout of the structure so that the records can be used to interface with the C code, something like
type Example (Count : Integer := Length) is record
Length : Unsigned_64;
Body : Integer (1 .. Count);
end record;
Is there any way to create a type like that with that array? I've been defaulting for now to grabbing the address of that location and declaring the array myself on place for use, is there any better way? Thanks in advance.
Here is an example in which Ada code calls C code, passing objects of this kind from Ada to C and from C to Ada. The C header is c_example.h:
typedef struct {
size_t length;
int body[];
} example_t;
extern void example_print (example_t *e /* in */);
// Print the contents of e.
extern example_t * example_get (void);
// Return a pointer to an example_t that remains owned
// by the C part (that is, the caller can use it, but should
// not attempt to deallocate it).
The C code is c_example.c:
#include <stdio.h>
#include "c_example.h"
void example_print (example_t *e /* in */)
{
printf ("C example: length = %zd\n", e->length);
for (int i = 0; i < e->length; i++)
{
printf ("body[ %d ] = %d\n", i, e->body[i]);
}
} // example_print
static example_t datum = {4,{6,7,8,9}};
example_t * example_get (void)
{
return &datum;
} // example_get
The C-to-Ada binding is defined in c_binding.ads:
with Interfaces.C;
package C_Binding
is
pragma Linker_Options ("c_example.o");
use Interfaces.C;
type Int_Array is array (size_t range <>) of int
with Convention => C;
type Example_t (Length : size_t) is record
Bod : Int_Array(1 .. Length);
end record
with Convention => C;
type Example_ptr is access all Example_t
with Convention => C;
procedure Print (e : in Example_t)
with Import, Convention => C, External_Name => "example_print";
function Get return Example_Ptr
with Import, Convention => C, External_Name => "example_get";
end C_Binding;
The test main program is flexarr.adb:
with Ada.Text_IO;
with C_Binding;
procedure FlexArr
is
for_c : constant C_Binding.Example_t :=
(Length => 5, Bod => (55, 66, 77, 88, 99));
from_c : C_Binding.Example_ptr;
begin
C_Binding.Print (for_c);
from_c := C_Binding.Get;
Ada.Text_IO.Put_Line (
"Ada example: length =" & from_c.Length'Image);
for I in 1 .. from_c.Length loop
Ada.Text_IO.Put_Line (
"body[" & I'Image & " ] =" & from_c.Bod(I)'Image);
end loop;
end FlexArr;
I build the program thusly:
gcc -c -Wall c_example.c
gnatmake -Wall flexarr.adb
And this is the output from ./flexarr:
C example: length = 5
body[ 0 ] = 55
body[ 1 ] = 66
body[ 2 ] = 77
body[ 3 ] = 88
body[ 4 ] = 99
Ada example: length = 4
body[ 1 ] = 6
body[ 2 ] = 7
body[ 3 ] = 8
body[ 4 ] = 9
So it seems to work. However, the Ada compiler (gnat) gives me some warnings from the C_Binding package:
c_binding.ads:14:12: warning: discriminated record has no direct equivalent in C
c_binding.ads:14:12: warning: use of convention for type "Example_t" is dubious
This means that while this interfacing method works with gnat, it might not work with other compilers, for example Ada compilers that allocate the Bod component array separately from the fixed-size part of the record (whether such a compiler would accept Convention => C for this record type is questionable).
To make the interface more portable, make the following changes. In C_Binding, change Length from a discriminant to an ordinary component and make Bod a fixed-size array, using some maximum size, here 1000 elements as an example:
type Int_Array is array (size_t range 1 .. 1_000) of int
with Convention => C;
type Example_t is record
Length : size_t;
Bod : Int_Array;
end record
with Convention => C;
In the test main program, change the declaration of for_c to pad the array with zeros:
for_c : constant C_Binding.Example_t :=
(Length => 5, Bod => (55, 66, 77, 88, 99, others => 0));
For speed, you could instead let the unused part of the array be uninitialized: "others => <>".
If you cannot find a reasonably small maximum size, it should be possible to define the C binding to be generic in the actual size. But that is getting rather messy.
Note that if all the record/struct objects are created on the C side, and the Ada side only reads and writes them, then the maximum size defined in the binding is used only for index bounds checking and can be very large without impact on the memory usage.
In this example I made the Ada side start indexing from 1, but you can change it to start from zero if you want to make it more similar to the C code.
Finally, in the non-discriminated case, I recommend making Example_t a "limited" type ("type Example_t is limited record ...") so that you cannot assign whole values of that type, nor compare them. The reason is that when the C side provides an Example_t object to the Ada side, the actual size of the object may be smaller than the maximum size defined on the Ada side, but an Ada assignment or comparison would try to use the maximum size, which could make the program read or write memory that should not be read or written.
The discriminant is itself a component of the record, and has to be stored somewhere.
This code,
type Integer_Array is array (Natural range <>) of Integer;
type Example (Count : Natural) is record
Bdy : Integer_Array (1 .. Count);
end record;
compiled with -gnatR to show representtion information, says
for Integer_Array'Alignment use 4;
for Integer_Array'Component_Size use 32;
for Example'Object_Size use 68719476736;
for Example'Value_Size use ??;
for Example'Alignment use 4;
for Example use record
Count at 0 range 0 .. 31;
Bdy at 4 range 0 .. ??;
end record;
so we can see that GNAT has decided to put Count in the first 4 bytes, just like the C (well, this is a common C idiom, so I suppose it’s defined behaviour for C struct components to be allocated in source order).
Since this is to be used for interfacing with C, we could say so,
type Example (Count : Natural) is record
Bdy : Integer_Array (1 .. Count);
end record
with Convention => C;
but as Niklas points out the compiler is doubtful about this (it’s warning you that the Standard doesn’t specify the meaning of the construct).
We could confirm at least that we want Count to be in the first 4 bytes, adding
for Example use record
Count at 0 range 0 .. 31;
end record;
but I don’t suppose that would stop a different compiler using a different scheme (e.g. two structures, the first containing Count and the address of the second, Bdy).
C array indices always start at 0.
If you want to duplicate the C structure remember that the discriminant is a member of the record.
type Example (Length : Integer) is record
body : array(0 .. Length - 1) of Integer;
end record;

Why is it not possible to add an integer to a "dereferenced" pointer variable in Go?

Coming from Python, I'm currently learning Go and trying to wrap my head around pointers.
I've written this code in order to understand the concept:
a := 1
b := &a
fmt.Println(b) // Shows the memory address of a
fmt.Println(*b) // Shows the value 1
*b++
fmt.Println(a) // Shows the value 2 (as expected)
I tried to play around with this code to improve my understanding. The following, however, does not work:
a := 1
b := &a
fmt.Println(b) // Shows the memory address of a
fmt.Println(*b) // Shows the value 1
b = *b + 1 // Compile error: invalid operation: b * +1 (mismatched types *int and int)
fmt.Println(a)
Apparently, *b is of type *int, while the value 1 is (obviously) of type int. However, why is it possible to increment the value of a with *b++in the first example?
From the beginning:
b := &a
Here, b is of type *int, a pointer to a location in memory where value of a is stored. When you do *b, you are accessing a value from the location b pointer points to.
When you do *b++, it stands for *b = *b + 1 and you are incrementing a value on the location b pointer points to.
b = *b + 1 is invalid because you are trying to add *b and 1, which are both type of int, to b, which is a pointer (type of *int).
Why is it not possible to add an integer to a “dereferenced” pointer variable in Go?
b is a pointer and dereferenced b is written as *b. b = *b + 1 is invalid because you're trying to convert an integer to a pointer, which is not possible even when explicitly typecasted. You'll need to instead modify the data that pointer is pointing to, not the pointer itself: *b = *b + 1.
Take a look at the Go spec here regarding why *b++ works: https://golang.org/ref/spec
Operator precedence
Unary operators have the highest precedence. As the ++ and -- operators form statements, not expressions, they fall outside the operator hierarchy. As a consequence, statement *p++ is the same as (*p)++.
Adding an integer to a dereferenced (integer) pointer variable is possible and is working in your case correctly. However, assigning this value to a pointer variable is not acceptable in Go for type safety reasons. And it is normally not needed (but there is a way to reference any given address though). Hope this clarifies it.
You are adding a *int to an int. Hence, the error.
As b is a pointer to an integer, to do anything with that integer(read or write), you need to de-reference it. Below code will work as expected. That's what *b++ does internally.
package main
import (
"fmt"
)
func main() {
a := 1
b := &a
fmt.Println(b) // Shows the memory address of a
fmt.Println(*b) // Shows the value 1
*b = *b + 1 // No Compile error
fmt.Println(a) // Shows the value 2
}
Try it here:
https://play.golang.org/p/2RX1CWD-AQC

Address of an element appended to a slice

I want to create element, add it to the slice and change it by its address. I expect that the change of the element from the outside will change also a slice. But after the addition, a new slice is created. I use serialization, so the use of an slice of addresses is not suitable, also the addition of elements occurs in different goroutines, so accessing the last added element is also not suitable.
package main
import (
"fmt"
)
func main() {
var a []int
b := 1
fmt.Println("old addr:", &b)
// old addr: 0x10414020
a = append(a, b)
fmt.Println("new addr:", &a[0])
// new addr: 0x10414028
}
play golang example
This is not an issue of append() creating a new slice header and backing array.
This is an issue of you appending b to the slice a, a copy of the value of the b variable will be appended. You append a value, not a variable! And by the way, appending (or assigning) makes a copy of the value being appended (or assigned).
Note that the address of b and a[0] will also be different if you do not call append() but instead preallocate the slice and simply assign b to a[0]:
var a = make([]int, 1)
b := 1
fmt.Println("old addr:", &b)
// old addr: 0x10414024
a[0] = b
fmt.Println("new addr:", &a[0])
// new addr: 0x10414020
Try it on the Go Playground.
The reason for this is because the variable b and a are distinct variables; or more precisely the variable b and a's backing array reserving the memory for its elements (including the memory space for a[0]), so their addresses cannot be the same!
You cannot create a variable placed to the same memory location of another variable. To achieve this "effect", you have pointers at your hand. You have to create a pointer variable, which you can set to point to another, existing variable. And by accessing and modifying the pointed value, effectively you are accessing and modifying the variable whose address you stored in the pointer.
If you want to store "something" in the a slice through which you can access and modify the "outsider" b variable, the easiest is to store its address, which will be of type *int.
Example:
var a []*int
b := 1
fmt.Println("b's addr:", &b)
a = append(a, &b)
fmt.Println("addr in a[0]:", a[0])
// Modify b via a[0]:
*a[0] = *a[0] + 1
fmt.Println("b:", b)
Output (try it on the Go Playground):
b's addr: 0x10414020
addr in a[0]: 0x10414020
b: 2
Assigning values always lets the runtime allocate new memory for the copied value and that allocated memory will have another address. If you append to a slice of values, you will always copy the variable.
If you have to access the elements from different go routines, you will have to make it thread safe. You have to do that, whether you are using values or references.
Quoted program behaves perfectly correct - addresses denote storage locations, b int is one such location and element inside the slice is other one.
You most probably need to store pointers not ints.
Now with regard to serialization - I am not sure what kind do you have in mind, but in general you could proceed like below:
type myArray []*int
var a myArray
//...
func (x myArray) Serialize() []byte { .... }
Where Serialize satisfies the interface used by your serializator.

Modify dereferenced struct pointer changes most struct values, but not slices

I'm trying to create a shallow copy of a struct Board (a chessboard). Before saving a move to the board, I need to check if that move puts the mover in check.
To do so, within the Move method (method of a pointer), I dereference the pointer, update and check this possible board for Check. When I change the value of a single value of the Board type (such as possible.headers = "Possible Varient") the original b Board is not changed.
But here when I call a method updateBoard() it updates both boards. I still receive the error (cannot move into check), but the main thread thinks b.board (the board position) has been changed.
func (b *Board) Move(orig, dest int) error {
// validation
...
// Update
possible := *b // A 'shallow copy'?
possible.updateBoard(orig, dest, val, isEmpassant, isCastle)
king := possible.findKingPositionOfThePlayerWhoMoved()
isCheck := possible.isInCheck(king) // bool takes the king to check for
if isCheck {
return errors.New("Cannot move into Check")
}
b.updateBoard(orig, dest, val, empassant, isCastle)
return nil
Strangely, not all the the values updated by updateBoard() change. So the b.toMove value doesn't change, but the b.board value does (the position of the pieces). This means if I pass possible := b instead, the game will only ever be white's move (toMove is alternated in the updateBoard() method). With possible := *b, turn alternation works until one moves into check. Then the move is applied to b.board, but the error is thrown back and it remains the checked-players turn (meaning possible.updateBoard() didn't update b.toMove.
Edit
As abhink pointed out, in Go Slices usage and internals,
Slicing does not copy the slice's data. It creates a new slice value that points to the original array.
b.board, a []byte, always points to its original value (even when the struct which holds it is dereferenced. abhink's answer uses the Go func copy(dst, src []Type) int, https://golang.org/pkg/builtin/#copy , a shortcut for copying the values of the pointers.
Since b.board is a slice type, it is a reference type (https://blog.golang.org/go-slices-usage-and-internals) and behaves like a pointer. So any changes made to possible.board will show up in b. You can try making a copy of b.board like so:
func (b *Board) Move(orig, dest int) error {
// validation
...
// Update
possible := *b // A 'shallow copy'?
boardCopy := make([]byte, len(b.board))
copy(boardCopy, b.board)
possible.board = boardCopy
possible.updateBoard(orig, dest, val, isEmpassant, isCastle)
// ...
Note that you'll have to do something like this for all reference types.
Dereferencing does NOT make a copy. It returns the original value your pointer points to.
You get a copy because you are assigning that value to a new variable. In go every assignment makes a copy as does every pass to a function. If you assign or pass a reference, that reference is copied.
In your case you copy the value b points to. In that struct there are pointers like the b.board slice (slices have a pointer to an underlying array). So go is creating a copy of the slice. The copy still points to the same array as the slice in the original b variable. If you change that array, it is changed for both your boards.
You will need to implement a copy function to your Board struct that correctly creates a copy of your struct handling each variable depending on its type and returns that new board.
Something like:
func (b *Board) copy() *Board {
boardCopy := make([]byte, len(b.board))
copy(boardCopy, b.board)
return &Board{
moveTo: b.moveTo,
board: boardCopy
...
}
}
Hope that helps and my explanation wasn't confusing :)

Increment address of access type as pointer in c using interface.c.pointer?

Some unexpected behavior is noticed: Put_Line(Integer'Image(Var.all)); var:=var+5; -- it gives 1,var+6 then 2 and if var+7 then 0,var+8 then -1, can anyone please explain this?
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C.Pointers;
procedure Access_Pointer_Arithmetic is
type Myarr_Indices is range 1 .. 5;
type Myarr is array (Myarr_Indices range <>) of aliased Integer;
Myarr_Terminator : constant Integer := 0;
package Myarr_Pointer_Arithmetic is new Interfaces.C.Pointers
(Myarr_Indices, Integer, Myarr, Myarr_Terminator);
use Myarr_Pointer_Arithmetic;
Myarr_Var : aliased Myarr := (2, 5, 7, 9, 0);
Var : Myarr_Pointer_Arithmetic.Pointer :=Myarr_Var(Myarr_Var'First)'access;
begin
Put_Line(Integer'Image(Var.all));
var:=var+1;
Put_Line(Integer'Image(Var.all));-- why 1?
var:=var+8;
Put_Line(Integer'Image(Var.all));-- why -1 and some time different 4-7 digits no?
end Access_Pointer_Arithmetic;
Your Ada code is precisely equivalent to this C:
#include <stdio.h>
int main()
{
int arr[5] = {2, 5, 7, 9, 0};
int *p = arr;
printf("%d\n", *p);
p += 1;
printf("%d\n", *p);
p += 8;
printf("%d\n", *p);
return 0;
}
which, when it’s run, produces (on my machine)
2
5
32767
You have told the compiler to reserve space for 5 ints (20 bytes), in which you have put some data. The compiler is free to use the space beyond the end of the array for whatever it likes; it certainly doesn’t belong to you, you have no idea what it’s used for: HANDS OFF!
So when you increment the pointer to what would be the tenth element of the array if you had declared it to be at least 10 elements long, you are addressing undefined data. You have no reason to suppose that it’s an int; it might be part of a character string, it might be the middle of a double, it might be anything. On a desktop machine, it’s unlikely to be a memory location which will cause the machine to catch fire when it’s read; a bit less unlikely in a microcontroller running your toaster.
Writing via the pointer is almost guaranteed to make your program crash, immediately or thousands of instructions later when you will have real trouble finding the bug.
The Ada word for this behaviour of a program is “erroneous”; the C word is, I believe, “undefined”.

Resources