以下是该函数,
程序在执行数次操作后出现invalid pointer异常,谁有经验帮忙解决一下??
function TfrmXzxc.MoveSelCarsToDestPos(CellsSource,CellsDest :CCellRange;var strErrorMsg:String):Boolean ;
var
  nRow,i,j,k,DestRow : Integer;
   //计算需要拖放的车辆总数
nDragCellCount : Integer; //定义拖放车辆总数
nAdjustDestRowCount :Integer; //定义由于本股道进行拖放需要调整目标选择区行数
nAdjustSourceRowCount :Integer; //定义由于本股道进行拖放需要调整源选择区行数
  nLocomotive  :integer ; //计算目标股道尾是否有机车
  nCol : Integer;
  nMin,nMax : Integer;
  bSelect : Boolean;
  nStationSourcePos,nStationDestpos : Integer;
  nSourceGDM : string;
  UndoMsg :UNDO_MSG;
begin
  Result := False;
  nCol := CellsDest.nMinCol ;  ////删除目标区上部
if(CellsDest.nMinRow <CAR_POS_START_ROW) then
CellsDest.nMinRow := CAR_POS_START_ROW; //删除选择区上部机车位
if(CellsSource.nMinRow < CAR_POS_START_ROW) then
CellsSource.nMinRow := CAR_POS_START_ROW;
if(cellsSource.nMaxCol <> CellsSource.nMinCol) then
  begin
strErrorMsg :='对不起,只能拖放同一个股道(列)的车辆!';
    Exit;
  end;  nDragCellCount := 0; //定义拖放车辆总数
nAdjustDestRowCount := 0; //定义由于本股道进行拖放需要调整目标选择区行数
nAdjustSourceRowCount := 0; //定义由于本股道进行拖放需要调整源选择区行数 //删除选择区中下部的空单元格及机车位
  nMin := -1;
  nMax := -1;
  bSelect := False;
for nRow := CellsSource.nMinRow to CellsSource.nMaxRow do
  begin
    if StrToIntDef(Cell1.GetCellNote(CellsSource.nMinCol ,nRow,0),-1) > -1 then
    begin
nDragCellCount := nDragCellCount + 1;
      if not bSelect  then
      begin
        nMin := nRow;
        bSelect := True;
      end;
      nMax := nRow;
    end;
  end;
  CellsSource.nMinRow := nMin;
  cellsSource.nMaxRow := nMax;//保存有效车辆区域 //检查是目标位置否在选择区内部
if(CellsSource.nMinCol=CellsDest.nMinCol) and (CellsDest.nMinRow>=CellsSource.nMinRow) and (CellsDest.nMinRow<=CellsSource.nMaxRow) then
  begin
strErrorMsg :='对不起,目标位置不能在选择区内部!';
    Exit;
  end; if(nDragCellCount<=0) then //选中的空车辆,直接返回
  begin
strErrorMsg := '对不起,请先选择需要拖放的车辆!';
    Exit;
  end; if((gd_desc[CellsDest.nMinCol-1].nClzs+nDragCellCount) > gd_desc[CellsDest.nMinCol-1].nRcs)
and (CellsDest.nMinCol <> CellsSource.nMinCol) then
  begin
strErrorMsg := '对不起,目标股道已放不下拖放的车辆了!';
    Exit;
  end;  //移动数组,同一股道调车情况处理办法
  if CellsSource.nMinCol = CellsDest.nMinCol then
  begin//下到上
    if (CellsSource.nMinRow > CellsDest.nMinRow) then
    begin
      CellsSource.nMinRow := CellsSource.nMinRow + nDragCellCount;
      CellsSource.nMaxRow := CellsSource.nMaxRow + nDragCellCount;
      CellsDest.nMinRow := CAR_POS_START_ROW;
      CellsDest.nMaxRow := CAR_POS_START_ROW + nDragCellCount - 1;
    end else
    begin//上到下
      CellsDest.nMinRow := CAR_POS_START_ROW + Length(gd_desc[nCol - 1].v_sy);
      CellsDest.nMaxRow := CellsDest.nMinRow + nDragCellCount - 1  ;
    end;
  end;
  SetLength(gd_desc[nCol-1].v_sy,gd_desc[nCol-1].nClzs + nDragCellCount);
//确定目标位置,空出相应位置
  //目标为空白单元格,需要找到其上的第一个空白单元格
if not (StrToIntDef(Cell1.GetCellNote(CellsDest.nMinCol ,CellsDest.nMinRow,0),-1) > -1) then
  begin
    CellsDest.nMinRow := gd_desc[nCol - 1].nClzs + CAR_POS_START_ROW ;
    CellsDest.nMaxRow := CellsDest.nMinRow + nDragCellCount -1; if(CellsDest.nMinCol = CellsSource.nMinCol) then//如果是在同一股道进行甩挂操作
    begin
nAdjustDestRowCount := nDragCellCount;
    end;
  end else //目标为有内容的单元格,需要向下移位量为:nDragCellCount
  begin
//空出目标区车辆位置    for i:= High(gd_desc[nCol - 1].v_sy) - nDragCellCount downto CellsDest.nMinRow - CAR_POS_START_ROW do
    begin
      if (i < gd_desc[nCol-1].nClzs) then
      begin
        gd_desc[nCol - 1].v_sy[i+nDragCellCount] := gd_desc[nCol - 1].v_sy[i];
        SwapTwoCells(i+CAR_POS_START_ROW,nCol,i+CAR_POS_START_ROW+nDragCellCount,nCol);
      end else
        Break;
    end;
  end;  j := CellsSource.nMinRow - CAR_POS_START_ROW ;
//  SetLength(gd_desc[nCol-1].v_sy,gd_desc[nCol-1].nClzs + nDragCellCount);
  for i:= CellsDest.nMinRow - CAR_POS_START_ROW to CellsDest.nMaxRow - CAR_POS_START_ROW  do
  begin
     gd_desc[nCol - 1].v_sy[i] := gd_desc[CellsSource.nMinCol - 1].v_sy[j];
     j := j + 1;
  end;
  gd_desc[nCol - 1].nClzs := gd_desc[nCol - 1].nClzs + nDragCellCount;
//  SetLength(gd_desc[nCol-1].v_sy,gd_desc[nCol - 1].nClzs); //开始进行甩挂  destRow := CellsDest.nMinRow ;
for nRow := CellsSource.nMinRow to CellsSource.nMaxRow do
  begin
    SwapTwoCells(nRow,CellsSource.nMinCol,destRow,CellsDest.nMinCol);
    destRow := destRow + 1;
  end;  //移动数据源
  j := 0;
  DestRow := CellsSource.nMinRow - CAR_POS_START_ROW ;
  nCol := CellsSource.nMinCol;
  for i := CellsSource.nMaxRow - CAR_POS_START_ROW + 1  to High(gd_desc[nCol - 1].v_sy) do
  begin
     gd_desc[nCol - 1].v_sy[DestRow] := gd_desc[nCol - 1].v_sy[i] ;
     SwapTwoCells(i+CAR_POS_START_ROW,nCol,DestRow+CAR_POS_START_ROW,nCol);
     DestRow := DestRow + 1;
  end;
  gd_desc[nCol - 1].nClzs := gd_desc[nCol - 1].nClzs - nDragCellCount;
  SetLength(gd_desc[nCol-1].v_sy,gd_desc[nCol - 1].nClzs);  if (CellsSource.nMinCol = CellsDest.nMinCol)and (CellsSource.nMinRow < CellsDest.nMinRow) then
  begin//,同股道甩挂后重新指定选择区域,上到下,重新指定选择目标区域
    CellsDest.nMinRow := CellsDest.nMinRow - nDragCellCount;
    CellsDest.nMaxRow := CellsDest.nMaxRow - nDragCellCount;
  end;
{
     //移动整列车
  if (gd_desc[CellsSource.nMinCol - 1].nClzs = nDragCellCount) then
  begin
    if Trim(Cell1.GetCellString(CellsDest.nMinCol,1,0)) = '' then
    begin
      //设置第一行车次标志
      SwapTwoCells(1,CellsSource.nMinCol,1,CellsDest.nMinCol);
      for i := Low(station_train) to High(station_train) do
      begin
        if Trim(station_train[i].GDM) = Trim(gd_desc[CellsSource.nMinCol - 1].strGdm) then
        begin
          nStationSourcePos := i;
          Break;
        end;
      end;
      station_train[nStationSourcePos].GDM := DestGdm ;
      //刷新机车位
      RefreshAllLocomotiveCells(Cell1);
    end;
  end;      }  Cell1.SelectRange(CellsDest.nMinCol,CellsDest.nMinRow,CellsDest.nMinCol,CellsDest.nMaxRow);
  FCellcol := CellsDest.nMinCol;//确保在不重新选择单元格时,取目标格的值
  result := True;