Гость
Форумы / Delphi [игнор отключен] [закрыт для гостей] / AV на присвоении текста в AdoQuery.SQL.Text Delphi7 / 25 сообщений из 27, страница 1 из 2
17.01.2022, 15:45
    #40127224
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Добрый день, коллеги! Получаю список компьютеров из Active Directory при помощи TADOConnection и TADOQuery.

По тексту все элементы создаются и в конце работы освобождаются. Сам список компьютеров из AD также удается получить, но есть две проблемы:

1). при каждом выполнении кода получаю ошибку
Код: sql
1.
Access violation Access violation at address 00448A07 in module ExpDataFromAD.exe. Read of address 00000000


Она происходит на строке присвоения текста AdoQuery.SQL.Text:= vSQL;
Но данные запроса при этом приходят.
При этом и AdoQuery парой строчек выше создан и vSQL это существующая строковая переменная.

2). если крутить код чтения списка в приложении по таймеру, то через некоторое количество выполнении происходит out of memory.
Я предполагаю, что причина в этой самой AV, из-за нее память утекает.

Прошу совета, как бороть такую проблему?

Код программы такой:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
CoInitializeEx(nil, COINIT_MULTITHREADED);

  try
    try
      vAdoConn:=TADOConnection.Create(nil);
      vAdoConn.LoginPrompt:=false;

      vAdoConn.ConnectionString:='Provider=ADsDSOObject;Password='+aPassword+';User ID='+aLogin+';Encrypt Password=False;Mode=Read';
      vAdoConn.Open;
    except
      on e:exception do
      begin
        WriteLog(vErrorFile, 'Export PC List from AD error: '+e.message);
        exit;
      end;
    end;

    try
      vAdoQuery:=TADOQuery.Create(nil);
      vAdoQuery.Connection:=vAdoConn;

      LastDate:= now - 15;
      vObjectName:='computer';
      vSQL:='select Name, operatingsystem, operatingSystemVersion, objectguid, useraccountcontrol, whenCreated, distinguishedName '+
            'from '+quotedstr('LDAP://'+vDomainName)+' where objectClass='+quotedstr(vObjectName);
      vSQL:= vSQL + ' and whenCreated > '+ quotedstr(GetDTString(LastDate)); 

      vAdoQuery.Close;
      vAdoQuery.SQL.Text:=vSQL;
      vAdoQuery.Open;
      if NOT vAdoQuery.IsEmpty then //exit;
      begin
        setlength(PCMas, vAdoQuery.RecordCount);
        vAdoQuery.First;
        j:= 0;
        while not vAdoQuery.eof do
        //for j:= 0 to vAdoQuery.RecordCount-1 do
        begin
          for i:= 0 to vAdoQuery.FieldCount-1 do
          begin
            vFieldVal:=vAdoQuery.Fields[i].AsString;

            if vAdoQuery.Fields[i].FieldName='Name' then
              PCMas[j].PCName:= vFieldVal;
          end;

          vAdoQuery.Next;
          inc(j);       
        end;
      end;      

      vAdoQuery.Close;
    except
      on e:exception do
      begin
        WriteLog(vErrorFile, 'Export PC List from AD vAdoQuery execute error: '+e.message);
      end;
    end;
  finally
    if (vAdoQuery <> nil) then vAdoQuery.Free;
    vAdoConn.Free;
  end;
...
Рейтинг: 0 / 0
17.01.2022, 15:52
    #40127228
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield,
Если на присвоении текста исключение, то до открытия собственно запроса дело доходить не должно.
...
Рейтинг: 0 / 0
17.01.2022, 16:10
    #40127230
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Vlad F, у меня при запуске под отладчиком ошибка вываливалась на этой строке vAdoQuery.SQL.Text:=vSQL;
но потом продолжает дальше выполняться...

и память утекает, хоя в finally есть освобождение компонент...
...
Рейтинг: 0 / 0
17.01.2022, 16:12
    #40127232
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShieldПрошу совета, как бороть такую проблему?

Начать хоть немного думать мозгом о том как твой код работает не предлагать?..

Код: sql
1.
vAdoQuery.Close;


Закрывается запрос который никогда не открывался.

Код: sql
1.
vAdoQuery.First;


Возврат к первой записи набора данных, который никогда с неё и не сходил.

Код: sql
1.
2.
3.
setlength(PCMas, vAdoQuery.RecordCount);

while not vAdoQuery.eof do


Резервируется место по числу RecordCount, а заполняется пока не надоест.
Естественно массив переполняется, затирая всё, чему не повезло оказаться в куче
после него.

Код: sql
1.
2.
3.
4.
5.
6.
7.
for i:= 0 to vAdoQuery.FieldCount-1 do
           begin
             vFieldVal:=vAdoQuery.Fields[i].AsString;

             if vAdoQuery.Fields[i].FieldName='Name' then
               PCMas[j].PCName:= vFieldVal;
           end;


Значения всех полей заносятся в одну переменную, которая потом в большинстве
случаев не используется. О FieldByName ты когда-нибудь слышал?..

Код: sql
1.
if (vAdoQuery <> nil) then vAdoQuery.Free;


Проверка переменной на значение, которое ей никогда никем не присваивалось.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
17.01.2022, 16:23
    #40127236
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield

и память утекает, хоя в finally есть освобождение компонент...

Однако нет SetLength(PCMas, 0).
...
Рейтинг: 0 / 0
17.01.2022, 16:47
    #40127246
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Dimitry Sibiryakov, благодарю за замечания. Я их учту.
Тем не менее close и first для ADOQuery в данном коде просто избыточны (т.к. компоненты создаются и разрушаются), но к ошибке они не приведут.

Переменных при разборе запроса больше берется (точнее, используются все, какие в query были), я при выкладке на форум код сократил. можно по имени брать, а можно и просто перечислить. так или иначе все поля разбираются.

if (vAdoQuery <> nil)
значение nil может быть, если подключение ADOCon не прошло успешно. Поэтому такая проверка ИМХО выглядит нужной.

Код: pascal
1.
while not vAdoQuery.eof do


тут все равно выберется не больше чем есть в выборке. Согласен, правильнее или динамически массив увеличивать внутри while или вместо while использовать for j:= 0 to vAdoQuery.RecordCount-1 do
Но если бы дело было в разном количестве элементов массива, то ошибка бы другая была.
...
Рейтинг: 0 / 0
17.01.2022, 16:54
    #40127249
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Vlad F, Вы имеете ввиду зануление массива в начале процедуры или в finally?
данный массив PCMas подается на вход процедуры с параметром out. Он используется в коде, вызывающем процедуру и там же после использования и зануляется. хотя его зануление в начале процедуры можно поставить. но по коду дальше, размер массива все равно будет сделан равным RecordsCount нового запроса...
...
Рейтинг: 0 / 0
17.01.2022, 17:15
    #40127252
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShieldзначение nil может быть, если подключение ADOCon не прошло
успешно.

Откуда? Если нет явного присвоения - значение переменной не определено и может
быть любым. Исключение составляют переменные типа интерфейс и строка.

SilverShieldтут все равно выберется не больше чем есть в выборке.

А вот тут ты глубоко заблуждаешься. RecordCount не обязано возвращать реальное
количество записей в выборке, допускается возвращение -1 или текущего
отфетченного батча.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
17.01.2022, 20:29
    #40127299
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Dimitry Sibiryakov, про nil принято. Правильнее будет if assign использовать? для проверки, что компонента создана.

> RecordCount не обязано возвращать реальное количество записей в выборке

Принято, это переделаю на увеличение массива внутри цикла while not vAdoQuery.eof do
...
Рейтинг: 0 / 0
17.01.2022, 21:11
    #40127302
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
По поводу Access violation эти действия не помогли. Оно также происходит на строке vAdoQuery.SQL.Text:=vSQL;
при этом код также как и раньше продолжает выполняться дальше и возвращается результат запроса.
что за чудеса, откуда может расти AV на ровном месте...
...
Рейтинг: 0 / 0
17.01.2022, 21:54
    #40127308
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Не нравится мне вот это
SilverShield
Код: pascal
1.
CoInitializeEx(nil, COINIT_MULTITHREADED);

применительно к ADO.

И еще вопрос - приложение, случайно, не многопоточное? А если да, то где объявлено vAdoQuery?
...
Рейтинг: 0 / 0
17.01.2022, 22:10
    #40127313
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShieldПравильнее будет if assign использовать?

Нет. Это то же самое.

Переменные надо всегда инициализировать.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
17.01.2022, 22:58
    #40127321
Vlad F
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield
...переделаю на увеличение массива внутри цикла while not vAdoQuery.eof do

Ты эта, - уже ослабь фантазию маленько.
Перед .RecordCount вызови .FetchAll, ну а если его там нет, то .Last/.First, как вариант замены.
...
Рейтинг: 0 / 0
18.01.2022, 09:22
    #40127357
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
_Vasilisk_, приложение в котором тестирую, однопоточное. Компоненты ADOConnection и ADOQuery обявлены в var той процедуры, где дальше с ними идет работа. Т.е. они по сути локальные.
...
Рейтинг: 0 / 0
18.01.2022, 09:23
    #40127358
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Vlad F, благодарю. Действительно, можно и так.
...
Рейтинг: 0 / 0
18.01.2022, 09:25
    #40127360
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield,

код программы не полный, нужно видеть все объявления переменных, помести все в дпр и запости сюда.
...
Рейтинг: 0 / 0
18.01.2022, 11:03
    #40127383
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Zelius, прикрепил юнит с процедурой. Код основной программы в упрощенном виде:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure TForm1.Button1Click(Sender: TObject);
var
  NewPCMas: TNewPCMas;  
  LastCheckTime: Tdatetime;
  aLogin, aPassword: string;
begin
  LastCheckTime:= Now-2190;
  aLogin:= 'domain\testuser';
  aPassword:= 'userpassword';

  GetNewPCFromAD(LastCheckTime, aLogin, aPassword, NewPCMas);
end;
...
Рейтинг: 0 / 0
18.01.2022, 11:51
    #40127389
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield,

GetUserNameExA - функция, а не процедура
GetUserNameExA
...
Рейтинг: 0 / 0
18.01.2022, 12:29
    #40127402
SilverShield
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Zelius, изменил ее объявление на функцию. К сожалению, на AV это не влияет...
...
Рейтинг: 0 / 0
18.01.2022, 12:32
    #40127403
Belotsky Serge
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield,
А не попробовали? Что-то меня смущает присвоение прямо в .Text (взято из справки по Delphi). Просто выполнить один Add(vSQL).
Код: pascal
1.
2.
3.
4.
5.
6.
with ADOQuery1 do begin
with SQL do begin
Clear;
Add(vSQL);
end;
Open;
...
Рейтинг: 0 / 0
18.01.2022, 13:01
    #40127410
Fr0sT-Brutal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Belotsky Serge
Что-то меня смущает присвоение прямо в .Text

Зря смущает
...
Рейтинг: 0 / 0
18.01.2022, 13:33
    #40127421
DimaBr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
авторОна происходит на строке присвоения текста AdoQuery.SQL.Text:= vSQL;
Почему бы перед присвоением не вывести текст запроса на экран ?
...
Рейтинг: 0 / 0
18.01.2022, 13:38
    #40127425
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
SilverShield,

проверил код у себя на Д7, у меня AV не выпадает. имхо, попробуй вынести сам в отдельный проект где больше ничего нет. если не поможет, то возможно проблемы с установкой дельфи.
...
Рейтинг: 0 / 0
18.01.2022, 14:15
    #40127438
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
Delphi Rio - работает
...
Рейтинг: 0 / 0
18.01.2022, 14:15
    #40127439
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
AV на присвоении текста в AdoQuery.SQL.Text Delphi7
del
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / AV на присвоении текста в AdoQuery.SQL.Text Delphi7 / 25 сообщений из 27, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]