代码之家  ›  专栏  ›  技术社区  ›  JosephStyons

delphi程序中的意外错误

  •  0
  • JosephStyons  · 技术社区  · 16 年前

    我正在使用 this unit 在Delphi2010应用程序中,告诉我用户是哪个活动目录组的成员。

    我创建了一个全新的测试VCL表单应用程序,从该链接添加了单元,并创建了一个带有用户名编辑框的小表单,另一个编辑框用于保存CSV分隔的组列表,以及一个列表框用于以列格式保存组列表。

    我的代码如下:

    procedure TfrmMain.btnShowGroupsClick(Sender: TObject);
    var
      ad: TADSI;
      adrec: TADSIUserInfo;
      csvGroups: string;
      slGroups: TStringList;
    begin
      //take username from an edit box, tell me what AD groups they are a member of
      ad := TADSI.Create(Self);
      try
        ad.GetUser(edtDomain.Text,edtUser.Text,adrec);
        csvGroups := adrec.Groups;
        edtADGroups.Text := csvGroups;  //ACCESS VIOLATION!!
      finally
        FreeAndNil(ad);
      end;
    
      {
      //If I UN-comment this code, and make NO OTHER CHANGES, then the
      //aforementioned access violation does NOT occur; there are no errors @ all,
      //and everything works just fine
    
      slGroups := TStringList.Create;
      try
        slGroups.CommaText := csvGroups;
        listBoxADGroups.Items := slGroups;
      finally
        FreeAndNil(slGroups);
      end;
      //}
    end;
    

    如果按原样运行此代码,则在尝试将组的csv列表分配给编辑框时会遇到访问冲突。

    ---------------------------
    Debugger Fault Notification
    ---------------------------
    Project C:\Users\my_username.mydomain\bin\ADSITest.exe faulted with message: 'access violation at 0x0048a321: read of address 0x458c0035'. Process Stopped. Use Step or Run to continue.
    ---------------------------
    OK   
    ---------------------------
    

    但是,如果我取消对涉及tstringlist的代码块的注释,那么一切都很好。

    要么这是一个非常奇怪的编译器错误,要么我遗漏了一些显而易见的东西。有人能帮我吗?

    “adrec”结构是一个简单的记录,由几个布尔值、字符串和另一个记录(tpassword)组成。

    4 回复  |  直到 11 年前
        1
  •  1
  •   Leonardo M. Ramé    16 年前

    当您执行listboxadgroups.items:=slgroups;时,将listboxadgroups.items替换为指向slgroups的指针,下面几行,您将释放它。当程序结束btnshowgroupsclick方法时,列表框将尝试使用此指针,但它为零!,因此,A.V.

    解决办法是:

      slGroups := TStringList.Create;
      try
        slGroups.CommaText := csvGroups;
        listBoxADGroups.Items.AddStrings(slGroups);
      finally
        FreeAndNil(slGroups);
      end;
    

    addStrings方法将slgroups的内容复制到listboxadgroups.items属性(它也是一个tstrings对象),而不是仅仅替换指针。这样,tlistbox的items属性就完好无损了,只更改了其内容。

        2
  •  0
  •   Nat    16 年前

    我看到在你的代码中你也得到了一个av:

    edtADGroups.Text := csvGroups;  //ACCESS VIOLATION!!
    

    在涉及 TStringList ,我敢打赌你会在电话里看到例外情况:

    listBoxADGroups.Items := slGroups;
    

    我认为 Self 不知怎么的是无效的,也许是在某个地方免费的…

    您是在外部调用该方法,还是单击按钮?

        3
  •  0
  •   Deltics    16 年前

    我没有重现这个问题,也没有检查这个代码的编译器的输出,但是我注意到当这个代码块被注释掉时, CSV群 变量被冗余地用于存储一个值并将其从一个位置加载到另一个位置。

    这使我怀疑编译器是否过早地优化了字符串变量周围的一些关键的内部管理。

    注释掉的代码包含对 CSV群 ,从而延长了该变量的使用寿命,并有可能破坏编译器错误执行的优化。

    为了测试这一理论,我将从代码的“原样”版本中完全消除对该变量的使用,即更改:

    csvGroups := adrec.Groups;
    edtADGroups.Text := csvGroups;  //ACCESS VIOLATION!!
    

    简单地说:

    edtADGroups.Text := adrec.Groups;
    
        4
  •  0
  •   Jim    16 年前

    这是推测,但在我看来,您使用的单元与Unicode不兼容。如果没有任何组返回(调试并查看返回结果了吗?)CVS组可能未正确终止。当您取消对代码的注释时,写入slgroups可能会覆盖您以前拥有的任何垃圾(或者至少编译器会在清除了slgroups将被触碰之后执行类似初始化slgroups的操作)。