עבור לתוכן

pascal pointers - dispose מקבל הודעת שגיאה בשימוש בפקודה

Featured Replies

פורסם

שלום

אני משתמש ב Turbo Pascal 7.

בתוכנית שבניתי המשתמשת בפוינטרים יצרתי תאים בזיכרון בשימוש בפקודה new

אם למשל יש לי פוינטר p

אז השתמשתי ב new(p).

בקטע מסוים בתוכנית אני צריך למחוק תאים מסוימים שיצרתי, כלומר שערכם יהיה שווה nil.

השתמשתי בפקודה dispose כך

dispose(p).

כאשר p מצביע על התא שאני רוצה למחוק.

הקומפיילר מראה שהכל תקין ואני יכול להפעיל את התוכנית אבל ברגע שהתוכנית מגיעה לשימוש בdispose אני מקבל הודעת שגיאה:

:error 204 invalid pointer operation

תודה לעוזרים

פורסם

בדקת ש-new הצליח?

פורסם
  • מחבר

כן, אני יכול לקרוא את המידע מהתאים.

פורסם

תרשום את הקוד.

פורסם
  • מחבר

קוד התכנית:

program treebuild;

type tree_type = char {integer ...};
tree_pointer = ^node;
node = record
data: tree_type;
left, right, parent: tree_pointer
end;
bin_tree = tree_pointer;
node_position = tree_pointer;

procedure create_tree (var t: bin_tree);
begin
t := nil;
end;

function left_child (n: node_position): node_position;
begin
left_child := n^.left;
end;

function right_child (n: node_position): node_position;
begin
right_child := n^.right;
end;

function parent (n: node_position): node_position;
begin
parent := n^.parent;
end;

function key (n: node_position): tree_type;
begin
key := n^.data;
end;

function root (t: bin_tree): node_position;
begin
root := t;
end;

function tree_is_empty (t: bin_tree): boolean;
begin
tree_is_empty := t = nil;
end;

procedure tree_insert (k: tree_type; var t:bin_tree;
var pn: node_position);
begin

if t=nil then
begin
new (t);
t^.data := k;
t^.left :=nil;
t^.right := nil;
t^.parent := pn;
end
else
if k < key (t) then tree_insert(k,t^.left,t)
else tree_insert(k,t^.right,t);

end; {tree_insert}

procedure build_tree (var tree:bin_tree);
var
k:char;
pn:node_position;
begin
pn:=nil;
create_tree(tree);
writeln('Enter values for the tree. After each value use "Enter". Finish with a "." as a value');
readln(k);
while (k<>'.') do
begin
tree_insert(k,tree,pn);
readln(k);
end;
end;

procedure visit (n: node_position);
begin
write (' ', key(n), ' ');
end;

procedure inorder (t: bin_tree);
begin
if not tree_is_empty (t) then
begin
inorder (left_child (t));
visit (t);
inorder (right_child (t));
end;
end;

procedure inorder2 (t: bin_tree);
var
n,n2:node_position;
begin
while (t<>nil) do
begin
if (left_child(t)<>nil) then
begin
t:=left_child(t);
end
else
begin
visit(t);
if (right_child(t)<>nil) then
t:=right_child(t)
else
begin
n:=t;
t:=parent(t);
dispose(n);
end;
end;
end;
end;

var
tree:bin_tree;
begin
build_tree(tree);
inorder(tree);
writeln;
inorder2(tree);

readln;



end.

פורסם

שכחת לבדוק אם new(t) הצליח. העובדה שאתה יכול לכתוב ולקרוא מידע לא מוכיחה כלום.

גם אם זה לא הבאג במקרה הזה, כשאתה מקצה זכרון תמיד (אבל תמיד!) תבדוק אם ההקצאה הצליחה.

כנ"ל ברוב (עדיף בכל) קריאות מערכת הפעלה, כגון פתיחת קובץ.

הבעיה שלך היא מימושית ואלגוריתמית.

תסתכל על האיטרציה לאחר הראשונה שביצעת t = parent(t). במקרה זה באיטרציה הבאה הילדים של ההורה עדיין מאותחלים למצביעים שאינם נכונים כבר כי שחררת אותם.

עקרונית אחרי שאתה משחרר יחד אתה צריך לעדכן באב שלו את המצביע ל-nil. במימוש שלך אתה צריך להוסיף אחרי ה-dispose משהו כמו n^.xxx:= nil אבל אתה לא יכול כי אתה לא יודע אם XXX הוא left או right במימוש שלך.

הפתרון? תשנה מעט את האלגוריתם כך שתמיד תשחרר את הבן הימני או השמאלי דרך האבא. רמז: תכתוב את הפונקציה הפשוטה is_leaf(t) שתעזור לך.

נכון שמצביעים זה כיף?

פורסם
  • מחבר

לא הבנתי איך אני אמור "לבדוק אם ההקצאה הצליחה".

פורסם

לא תכנתתי פסקל כבר הרבה שנים, אבל אני מניח שאם new(p) נכשל אז p הוא nil.

פורסם
  • מחבר

תודה על התגובות.

שיניתי קצת את הקוד והכל עובד.

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים