I have a problem understanding the behavior of pointers set to nil in Pascal. I am using turbo pascal 7.0.
It seems that when I set two pointers head,tail to nil...they always seem to point to the same value in the future, even if they are assigned to different values.
In the code below, when I've commented out the problem area, and get the expected results.
When I remove comments from this pair of lines
head:=nil;
tail:=nil;
The 'head' pointer always seems to take the value given to the 'tail' pointer when de-referenced. Any insight provided will be appreciated.
program LinkedListTest;
type
ListNodePtr = ^ListNode;
ListNode = record
key,cycleLength: integer;
NodePtr: ListNodePtr;
end;
{
We have just defined the node of a linked list.
Next we declare our head which is the pointer to the first node
and the tail which points to the last node.
The head helps us find our first node in the list
the tail helps us to keep track of the last node in the list.
Both are simple pointers to a node (in our case ListNodePtr).
}
var
head,tail : ListNodePtr;
node1,node2,node3,node4: ListNode;
count: integer;
{Init the linked list}
procedure InitLinkedList;
Begin
new(head);
new(tail);
(* **Remove comments from this code to see problems in final output**
head:=nil;
tail:=nil;
*)
node1.key:=10;
new(node1.NodePtr);
node1.NodePtr:=nil;
head^:=node1;
tail^:=node1;
writeln('head key is now: ',head^.key);
node2.key:=20;
new(node2.NodePtr);
node2.NodePtr:=nil;
head^.NodePtr^:=node2;
tail^:=node2;
writeln('head key is now: ',head^.key);
writeln('tail key is now: ',tail^.key);
writeln('node1 key is now: ',node1.key);
writeln('node2 key is now: ',node2.key);
readln;
end;
begin
InitLinkedList;
end
.
There are several strange things.
You load data into allocate a record on the stack (node1), which will be gone on procedure exit, and then deep copy its contents (not references/pointers) into the records allocated to head and tail (using new).
head^:=node1;
tail^:=node1;
At that point you have three copies of node1's content, node1, head^ and tail^
With node2 you make the same mistake. ( head^.NodePtr^:=node2)
You can assign the points by simply assigning them, e.g.
head:=tail;
and access fields directly too
head^.field:=something
if head points to something sane.
This construct:
new(node1.NodePtr);
node1.NodePtr:=nil;
is essentially a memory leak. You allocate space for a record to nodeptr, but then immediately assign NIL to it, leaving no reference to the just allocated record.
HINT: work out your algorithm on paper with boxes (to signify records) and arrows (to signify pointers) first.
Revision 1- Removed local variables Node1 and Node2
Set tail 'next node' pointer to nil
check that head points to tail for 2 nodes in the list
UPDATED SOLUTION BASED ON ANSWERS
program LinkedListTest;
type
ListNodePtr = ^ListNode;
ListNode = record
key,cycleLength: integer;
NodePtr: ListNodePtr;
end;
var
head,tail,tempPtr : ListNodePtr;
count: integer;
pointerIsNil: boolean;
{Init the linked list}
begin
new(head);
new(tail);
new(tempPtr);
tempPtr^.key:=10;
head:=tempPtr;
tail:=tempPtr;
tail^.NodePtr:=nil;
writeln('head key is now: ',head^.key);
writeln('tail key is now: ',tail^.key);
pointerIsNil:=head^.NodePtr = nil;
writeln('Is heads node ptr nil? Answer is: ',pointerIsNil);
new(tempPtr);
tempPtr^.key:=20;
head^.Nodeptr:=tempPtr;
tail:=tempPtr;
writeln('head key is now: ',head^.key);
writeln('tail key is now: ',tail^.key);
pointerIsNil:=head^.NodePtr = nil;
writeln('Is heads node ptr nil? Answer is: ',pointerIsNil);
writeln('Making sure head is linked to the tail ',head^.NodePtr^.key);
readln;
end
.
Related
I have a fundamental question. I always read that the HEAD pointer of a linked list points to the first node of the list. My question is just by declaring a variable of type pointer and calling it head (or whatever), how does it end up pointing to the first node in the list. For example, I have the following pointer definition in VHDL
type Item;
type ItemPtr is access Item;
type Item is record
NextItem : ItemPtr;
data : integer;
end record;
variable HEAD : ItemPtr;
signal ReadData : integer;
ReadData <= HEAD.data;
...
This ends up reading 'data' from the first node of the list. But all I have done is declare a variable HEAD of type ItemPtr. How does that end up pointing to the first node of the linked list?
I am currently solving the problem of creating a singly linked list using pointers in Free Pascal. The task:
Write a program that reads integers from the standard input stream until the "end of file" situation occurs, after which it prints all the entered numbers TWICE in the order in which they were entered. The quantity of numbers is not known in advance, explicit restrictions on this number are prohibited.
In my program, the list is built in the wrong order. How to build the correct sequence?
program InputStreamNumbers;
type
itemptr = ^item;
item = record
data: Integer;
next: itemptr;
end;
var
first, tmp: itemptr;
n: Integer;
begin
first := nil; { make the list properly empty! }
while not SeekEof do { number reading loop }
begin
read(n);
new(tmp); { created }
tmp^.data := n; { fill out}
tmp^.next := first;
first := tmp; { include in the list}
end;
tmp := first; { go through the list from beginning to end }
while tmp <> nil do
begin
writeln(tmp^.data);
tmp := tmp^.next; { move to the next element}
end;
end.
When you add nodes to the list, you create a new node named tmp and assign its data. That's correct. But there is an error in how you add new items to the list. The error is in
tmp^.next := first; // this creates the backwards linkage
first := tmp;
If you can (assuming it's not against your task), add one variable more
last: itemptr;
which, as the name says, refers to the last item in the list.
The purpose is to have direct access to the end of the list, to make it easier to add items. Otherwise you would need to traverse the list from the beginning until you find the last item ( who's item.next is nil).
The list should end up like this:
first last
| |
v v
item.next -> item.next -> item.next -> item.next = nil
.data .data .data .data
I leave the implementation for you to do. But if it helps, initially first and last are nil. After one item is created, both first and last point to that one item. After a second item is created, first still points to the first created, but last points to the second ... and so on.
These are two linked lists that I've made,for a school project...
I want the first list to be called from the second,I have done that and at the compile time everything is ok. When I run it it says :
Project (myProject) raised exception class 'External: SIGSEGV'.
At address 40D32D
Here is my code:
list2=^ptr;
ptr=record
vlera:integer;
pozicioni:integer;
end;
type
list=^pointer;
pointer=record
rreshti:list2;
end;
var
a:array[1..7] of list;
i:integer;
kjovlere:list2;
begin
for i:=1 to 7 do begin
a[i]:=#kjovlere;
write('Give the pozition for the row:',i,' : ');
read(a[i]^.rreshti^.pozicioni);
write ('give the value for this poziton :');
read(a[i]^.rreshti^.vlera);
writeln;
end;
end.
And the error is at the for loop,at the read(a[i]^.rreshti^.pozicioni);
I would be very thankful if anyone explains me or gives me any suggestion :)
The provided source code shows at least two misunderstandings about pointer management in Pascal.
Main Problem - To assign data, a record type shall be allocated before.
This problem is referring to the lines read(a[i]^.rreshti^.pozicioni); and read(a[i]^.rreshti^.vlera);.
Both a[i] and rreshti are declared as pointer type (list=^pointer; & list2=^ptr;) and shall be allocated to a record structure before assigning data.
Step1: allocate the a[i] pointer in the loop.
new(a[i]);
Step2: allocate the a[i]^.rreshti pointer in the loop.
new(a[i]^.rreshti);
Strange Problem - Assign a pointer to a record type shall respect the destination type.
This problem is referring to the line a[i]:=#kjovlere;.
The a[i] is a list which is list=^pointer; and not list2 (list2=^ptr;) as declared for kjovlere:list2;.
Solution is: remove that line a[i]:=#kjovlere;.
Solution:
begin
for i:=1 to 7 do begin
(* a[i]:=#kjovlere; to be removed *)
new(a[i]);
new(a[i]^.rreshti);
write('Give the pozition for the row:',i,' : ');
read(a[i]^.rreshti^.pozicioni);
write ('give the value for this poziton :');
read(a[i]^.rreshti^.vlera);
writeln;
end;
end.
first timer here,
The first NOTE in SliceTricks suggests that there is a potential memory leak problem when cutting or deleting elements in a slice of pointers.
Is the same true for a map? For example: https://play.golang.org/p/67cN0JggWY
Should we nil the entry before deleting from map? Like so:
m["foo"] = nil
What if we simply clear the map?
m = make(map[string]*myStruct)
Will the garbage collector still pick it up?
Thanks in advance
Checking the sources
Although this is not documented anywhere, checking the sources: runtime/hashmap.go, mapdelete() function:
558 func mapdelete(t *maptype, h *hmap, key unsafe.Pointer) {
// ...
600 memclr(k, uintptr(t.keysize))
601 v := unsafe.Pointer(uintptr(unsafe.Pointer(b)) + dataOffset + bucketCnt*uintptr(t.keysize) + i*uintptr(t.valuesize))
602 memclr(v, uintptr(t.valuesize))
// ...
618 }
As you can see, storage for both the key (line #600) and the value (line #602) are cleared / zeroed.
This means if any of the key or value was a pointer, or if they were values of complex types containing pointers, they are zeroed and therefore the pointed objects are no longer referenced by the internal data structures of the map, so there is no memory leak here.
When there is no more reference to a complete map value, then the complete memory area of the map will be garbage collected, and all the pointers included in keys and values are also not held anymore by the map; and if no one else has reference to the pointed objects, they will be garbage collected properly.
Constructing an example to prove this
We can also construct a test code which proves this without examining the sources:
type point struct {
X, Y int
}
var m = map[int]*point{}
func main() {
fillMap()
delete(m, 1)
runtime.GC()
time.Sleep(time.Second)
fmt.Println(m)
}
func fillMap() {
p := &point{1, 2}
runtime.SetFinalizer(p, func(p *point) {
fmt.Printf("Finalized: %p %+v\n", p, p)
})
m[1] = p
fmt.Printf("Put in map: %p %+v\n", p, p)
}
Output (try it on the Go Playground):
Put in map: 0x1040a128 &{X:1 Y:2}
Finalized: 0x1040a128 &{X:1 Y:2}
map[]
What does this do? It creates a *Point value (pointer to a struct), puts it in the map, and registers a function that should be called when this pointer becomes unreachable (using runtime.SetFinalizer()), and then deletes the entry containing this pointer. Then we call runtime.GC() to "force" an immediate garbage collection. I also print the map at the end just to make sure the whole map is not garbage collected due to some optimization.
The result? We see the registered function gets called, which proves the pointer was removed from the map as the result of the delete() call, because (since we had no other references to it) it was eligible for garbage collection.
No, there will not be any memory leaks when deleting from a map.
In case of slices, since a slice actually uses an underlying array, as long as the slice exists - even if it uses just one slot in that array - the pointer items inside the array can not get garbage collected.
"A slice describes a piece of an array" which implies the array needs to be there for the slice to exist and can not get collected by GC; as long as some code is pointing at the slice.
I simply don't catch why the following does not work. Could someone help me to fix it? It complains (at runtime):
raised CONSTRAINT_ERROR : variant2.adb:21 discriminant check failed
procedure Variant2 is
type POWER is (NONE,GAS, STEAM);
type VEHICLE (Engine : POWER := NONE) is
record
Model_Year : INTEGER range 1888..1992;
case Engine is
when NONE => null;
when GAS => Cylinders : INTEGER range 1..16;
when STEAM => Boiler_Size : INTEGER range 5..22;
Coal_Burner : BOOLEAN;
end case;
end record;
Works : VEHICLE;
Works_Not : access VEHICLE := new VEHICLE;
begin
Works := (GAS,1980,4); -- (1)
Works_Not.all := (GAS,1981,8); -- (2)
end Variant2;
(1) is working, but (2) does not
Thanks in advance!
The RM explicitly states that "If the designated type is composite, [...] the created object is constrained by its initial value (even if the designated subtype is unconstrained with defaults)." (RM 4.8(6/3))
which means you have to reallocate your access type
Works_Not := new VEHICLE'(GAS,1981,8);
(of course, you should deallocate the old access value first (see RM 13.11.2 Unchecked Storage Deallocation), but I leave that as an exercise)
UPDATE: as discussed in the comments
Here's an example you can play around with:
with Ada.Text_IO;
procedure Array_Of_Aliased is
type POWER is (NONE, GAS, STEAM);
type VEHICLE(Engine : POWER := NONE) is
record
Model_Year : Integer range 1888..1992;
case Engine is
when NONE => null;
when GAS => Cylinders : INTEGER range 1..16;
when STEAM => Boiler_Size : INTEGER range 5..22;
Coal_Burner : BOOLEAN;
end case;
end record;
-- array of aliased elements
type Vehicle_Array is array(1..5) of aliased VEHICLE;
-- the access type need to be "all" or "constant" in order to access aliased values
type Vehicle_Access is access all VEHICLE;
Vehicles : Vehicle_Array;
Works : Vehicle_Access;
begin
-- access to the first element of the array. Can't change discriminant this way...
Works := Vehicles(1)'Access;
Ada.Text_IO.Put_Line(POWER'Image(Works.Engine));
-- However, using the array, we _can_ change the discriminant, since it's _not_ an access value
Vehicles(1) := (STEAM, 1890, 20, True);
Vehicles(2) := (GAS, 1981, 8);
Ada.Text_IO.Put_Line(POWER'Image(Works.Engine));
-- We can still update the record elements using the access value, as long as the discriminant stays the same
Works.all := (STEAM, 1900, 15, False);
end Array_Of_Aliased;
As egilhh said, when you allocate a discriminant record using new, you can't change the discriminant of the record you allocated, even though you could do this for a variable of the type (as opposed to an allocated record). This rule has been around since Ada 83. The rationale was, I believe, that it allows the compiler to optimize space when allocating records. In your example, if we assume all the fields (including the discriminant) are 1 word, then the record will be 2 words if ENGINE=NONE, 3 words if ENGINE=GAS, 4 words if ENGINE=STEAM. When Works_Not is initialized, it's initialized to a NONE, which means it may take only 2 words on the heap (note: it's not a requirement that compilers optimize in this way). If it uses only 2 words, then reassigning the record to one with ENGINE=GAS would be a disaster--you'd be overflowing the area that you previously allocated, and stomping on other data.
Whether this was a good language design decision or not, I can't say; I don't know how many compilers, and how many applications, needed to take advantage of this optimization. Somebody 33 years ago thought it would be useful, and they must have had some good reasons for thinking so.
The restriction is annoying but not insurmountable. I've definitely run into it before, multiple times, but the simple answer is to wrap it in another record.
type VEHICLE_DATA (Engine : POWER := NONE) is
record
Model_Year : INTEGER range 1888..1992;
case Engine is
when NONE => null;
when GAS => Cylinders : INTEGER range 1..16;
when STEAM => Boiler_Size : INTEGER range 5..22;
Coal_Burner : BOOLEAN;
end case;
end record;
type VEHICLE is record
Data : VEHICLE_DATA;
end record;
Now_Works : access VEHICLE := new VEHICLE; -- still sets ENGINE=NONE
Now_Works := (Data => (Gas, 1981, 8)); -- legal
Now_Works.Data := (Gas, 1981, 8); -- legal, does the same thing
These are OK because the allocated record is a VEHICLE, which isn't a discriminant record. It's OK to change the discriminant of a subcomponent like this. That's how I've gotten around the rule.