Удивительная ошибка в программе Delphi - PullRequest
0 голосов
/ 05 февраля 2010

Я использую этот блок в приложении Delphi 2010, чтобы сообщить мне, в какие группы Active Directory входит пользователь.

Я создал совершенно новое тестовое приложение для форм 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 ]

1 голос
/ 06 февраля 2010

Когда вы делаете listBoxADGroups.Items: = slGroups; вы заменяете listBoxADGroups.Items указателем на slGroups, пара строк ниже, вы освобождаете его. Когда программа завершает ваш метод btnShowGroupsClick, ListBox пытается использовать этот указатель, но он равен nil !, следовательно, A.V.

Решение таково:

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

Метод AddStrings копирует содержимое slGroups в свойство listBoxAdGroups.Items (которое также является объектом TStrings) вместо простой замены указателя. Таким образом, свойство Items TListBox остается без изменений, только его содержимое было изменено.

0 голосов
/ 08 февраля 2010

Это предположение, но мне кажется, что устройство, которое вы используете, несовместимо с UNICODE. Если вы не получили какую-либо группу обратно (вы отладили и посмотрели на возвращение?), Вероятно, cvsGroups не завершится должным образом. Когда вы раскомментируете код, запись в slGroups, вероятно, перезаписывает любой мусор, который у вас был раньше (или, по крайней мере, компилятор выполняет что-то вроде инициализации slGroups, как только становится ясно, что он будет затронут).

0 голосов
/ 06 февраля 2010

Я не воспроизводил проблему и не проверял выходные данные компилятора для этого кода, но я заметил, что когда этот блок кода закомментирован, переменная csvGroups избыточно используется для хранения и загрузки значение из одного местоположения в другое.

Это заставляет меня задуматься, возможно ли, что компилятор преждевременно оптимизирует некоторые важные операции вокруг этой строковой переменной.

Закомментированный код содержит дополнительную ссылку на csvGroups , что продлевает срок службы этой переменной и потенциально отрицательно влияет на оптимизацию, которую ошибочно выполняет компилятор.

Чтобы проверить эту теорию, я бы полностью исключил использование этой переменной из "как есть" версии кода, то есть изменим:

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

просто:

edtADGroups.Text := adrec.Groups;
0 голосов
/ 06 февраля 2010

Я вижу, что в вашем коде вы также получаете AV на линии:

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

В разделе, включающем TStringList, держу пари, вы получите исключение на линии:

listBoxADGroups.Items := slGroups;

Я думаю, что Self как-то недействительно, может быть, оно где-то было бесплатным ...

Вы вызываете этот метод извне или нажимаете кнопку?

...