You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pascal外部访问违规问题:原因及修复方法求助

二叉树初始化时的空指针访问问题

运行代码

program Version_als_Kompilett;

uses SysUtils;

type
  tRefBinBaum = ^tBinBaum;
  tBinBaum = record
    wert: integer;
    li: tRefBinBaum;
    re: tRefBinBaum
  end;

  function initTree(): tRefBinBaum;
  var 
    Baum: tRefBinBaum;
  begin
    new(Baum);
    Baum^.wert := 30; //random(100);

    if (Baum = nil)         then writeln('Baum ist nil');
    if (Baum^.li = nil)     then writeln ('Baum links nil')        else writeln('Baum links                : ' + IntToStr(Baum^.li^.wert));
    if (Baum^.re = nil)     then writeln('Baum rechts nil')        else writeln('Baum rechts        : ' + IntToStr(Baum^.re^.wert));
    if (Baum^.li^.li = nil) then writeln('Baum links links nil')   else writeln('Baum links links   : ' + IntToStr(Baum^.li^.li^.wert));
    if (Baum^.li^.re = nil) then writeln('Baum links rechts nil')  else writeln('Baum links rechts  : ' + IntToStr(Baum^.li^.re^.wert));
    if (Baum^.re^.li = nil) then writeln('Baum rechts links nil')  else writeln('Baum rechts links  : ' + IntToStr(Baum^.re^.li^.wert));
    if (Baum^.re^.re = nil) then writeln('Baum rechts rechts nil') else writeln('Baum rechts rechts : ' + IntToStr(Baum^.re^.re^.wert));

    initTree := Baum;
  end;

var
  Testsubjekt: tRefBinBaum;

begin
  Testsubjekt := initTree();

  readln();
end.

报错情况

运行时触发内存访问错误,问题出在以下代码行:

if (Baum^.re = nil)     then writeln('Baum rechts nil')             else writeln('Baum rechts        : ' + IntToStr(Baum^.re^.wert));

疑问

  1. 为什么会出现这个错误?左子节点的判断似乎可以正常工作,但右子节点不行。
  2. 我该如何修复?我是Object-Pascal的新手。

(注:使用Lazarus IDE,术语翻译:Baum=树,Wert=值,rechts=右,links=左)


问题原因

这是未初始化指针的随机值问题。你用new(Baum)创建了根节点的指针并分配了内存,但Baum^.li和Baum^.re这两个子节点指针并没有被显式初始化为nil。

在Object-Pascal中,new仅为记录分配内存空间,不会自动初始化内部的指针字段——这些指针会保留内存中的随机垃圾值。左子节点的判断没报错只是巧合,那个随机值刚好是nil或者指向了程序可访问的内存;而右子节点的随机值是无效地址,访问时直接触发了内存访问错误。

修复方案

1. 显式初始化子节点指针

在创建根节点后,手动将左右子节点指针设为nil,确保它们的状态确定:

function initTree(): tRefBinBaum;
var 
  Baum: tRefBinBaum;
begin
  new(Baum);
  Baum^.wert := 30; 
  // 显式初始化左右子节点为nil
  Baum^.li := nil;
  Baum^.re := nil;

  // 后续判断逻辑可正常执行
  if (Baum = nil)         then writeln('Baum ist nil');
  if (Baum^.li = nil)     then writeln ('Baum links nil')        else writeln('Baum links                : ' + IntToStr(Baum^.li^.wert));
  if (Baum^.re = nil)     then writeln('Baum rechts nil')        else writeln('Baum rechts        : ' + IntToStr(Baum^.re^.wert));
  // ... 其余判断代码不变
  initTree := Baum;
end;

2. 修复深层子节点的访问逻辑

当前代码中访问Baum^.li^.li这类深层节点时,没有先判断父节点是否有效。如果Baum^.li是nil,直接访问Baum^.li^.li会再次触发崩溃,正确写法应该先校验父节点指针:

// 示例:修复左左子节点的判断逻辑
if (Baum^.li <> nil) then
begin
  if (Baum^.li^.li = nil) then
    writeln('Baum links links nil')
  else
    writeln('Baum links links   : ' + IntToStr(Baum^.li^.li^.wert));
end
else
  writeln('Baum links ist nil,无法访问左左子节点');

内容的提问来源于stack exchange,提问作者Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 14:07:03