Глюки Lazarus

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Глюки Lazarus

Сообщение Angel_19 » 29.10.2014 18:55:28

Такая проблема проявилась.

Есть небольшой проект.
Одно время он компилировался и работал нормально. Какое-то время я его не использовал.
Тут внес небольшие изменения, и часть кода просто не выполняется....
Т.е. как пример - при запуске программы, вызываю процедуру, в которой в Memo добавляются строки. Часть строк добавляется, а часть нет.
Пробовал: Файл - очистить каталог - проблема осталась.

Добавил на форму кнопку, в которой вызываю ту же процедуру - она отрабатывает нормально.

В чем проблема? (Просто подозреваю, что и в крупном проекте несмотря на внесенные изменения, выполняется как бы старый код...)
Angel_19
новенький
 
Сообщения: 37
Зарегистрирован: 24.06.2014 17:29:47

Re: Глюки Lazarus

Сообщение Sharfik » 29.10.2014 19:21:24

Не видя код это гадание.
Как доступ к Мемо осуществляется, как вывод идет, где какие обновления....

:arrow: "-Помогите, мотоцикл не заводится! -Бензин есть? Нейтраль включил? Аварийный стоп выключен? Почему ключи от другого мотоцикла вставляешь?"
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Глюки Lazarus

Сообщение Angel_19 » 29.10.2014 22:26:50

Код: Выделить всё
procedure TForm1.GetName;
Var
   vSizet  : DWord;
   vPWChart: PWideChar;
   vNamePC,
   vNameUser : String;
   I         : DWord;
   vWNameUser,
   vWNamePC  : WideString;
begin
     vSizet := 1024;
     vPWChart := GetMem(vSizet);
     // получаем имя ПК
     if GetComputerNameW(vPWChart, vSizet) then
     begin
        SetString(vWNamePC, vPWChart, vSizet);
        vNamePC := UTF8Encode(vWNamePC);
     end
     else
        vNamePC := '';
     Memo1.Lines.Add('Имя ПК: '+vNamePC);

     // получаем логин !!!
     vSizet := 1024;
     if GetUserNameW(vPWChart, vSizet) then
     begin
          SetString(vWNameUser, vPWChart, vSizet);
          vNameUser := UTF8Encode(vWNameUser);
     end
     else
     begin
        vNameUser := '';
        Memo1.Lines.Add('LastError: ' + SysErrorMessageUTF8(GetLastError));
     end;
     Memo1.Lines.Add('GetUserName: '+vNameUser);
     for i:= 0 to 12 do
     begin
          vSizet := 1024;
          if GetUserNameExW(I,vPWChart, vSizet) then
          begin
               SetString(vWNameUser, vPWChart, vSizet);
               vNameUser := UTF8Encode(vWNameUser);
          end
          else
          begin
               vNameUser := '';
               vNameUser := 'LastError: ' + SysErrorMessageUTF8(GetLastError);
          end;
          Memo1.Lines.Add('GetUserNameEx '+IntToStr(I)+': '+vNameUser);
     end;
     FreeMem(vPWChart);
end;

Если вызываю в FormCreate , то то что в for i:= 0 to 12 do не работает.
Angel_19
новенький
 
Сообщения: 37
Зарегистрирован: 24.06.2014 17:29:47

Re: Глюки Lazarus

Сообщение Sharfik » 29.10.2014 23:45:06

Angel_19 писал(а):Если вызываю в FormCreate , то то что в for i:= 0 to 12 do не работает.

Нет, все что после
Код: Выделить всё
Memo1.Lines.Add('GetUserName: '+vNameUser);

Не отображается в самом мемо. Если ее закомментируешь, то работать будет.
Там что то в переменной передается, что мешает Мемо работать.
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Глюки Lazarus

Сообщение Angel_19 » 30.10.2014 00:25:33

В переменной там обычная строка.

Добавлено спустя 4 минуты 7 секунд:
Там в конце строки идет символ: #0 , он то все и портит.
если изменить код так, то все работает сразу:
Код: Выделить всё
procedure TForm1.GetName;
Var
   vSizet  : DWord;
   vPWChart: PWideChar;
   vNamePC,
   vNameUser : String;
   I         : DWord;
   vWNameUser,
   vWNamePC  : WideString;
begin
     vSizet := 1024;
     vPWChart := GetMem(vSizet);
     // получаем имя ПК
     if GetComputerNameW(vPWChart, vSizet) then
     begin
        SetString(vWNamePC, vPWChart, vSizet);
        vNamePC := UTF8Encode(vWNamePC);
     end
     else
        vNamePC := '';
     Memo1.Lines.Add('Имя ПК: '+vNamePC);

     // получаем логин !!!
     vSizet := 1024;
     if GetUserNameW(vPWChart, vSizet) then
     begin
         // SetString(vWNameUser, vPWChart, vSizet);
         // vNameUser := UTF8Encode(vWNameUser);
        vNameUser := UTF8Encode(WideString(vPWChart));
     end
     else
     begin
        vNameUser := '';
        Memo1.Lines.Add('LastError: ' + SysErrorMessageUTF8(GetLastError));
     end;
     vNameUser := 'GetUserName: '+vNameUser;
     Memo1.Lines.Add(vNameUser);
     for i:= 0 to 12 do
     begin
          vSizet := 1024;
          if GetUserNameExW(I,vPWChart, vSizet) then
          begin
               SetString(vWNameUser, vPWChart, vSizet);
               vNameUser := UTF8Encode(vWNameUser);
          end
          else
          begin
               vNameUser := '';
               vNameUser := 'LastError: ' + SysErrorMessageUTF8(GetLastError);
          end;
          Memo1.Lines.Add('GetUserNameEx '+IntToStr(I)+': '+vNameUser);
     end;
     FreeMem(vPWChart);
end;


Добавлено спустя 6 минут 43 секунды:
Но если оставить преждний код, и на форму добавить кнопку, и вызвать эту процедуру из кнопки, то все отрабатывает нормально, хотя символ #0 есть в злополучной строке...

Добавлено спустя 19 минут 56 секунд:
Правильный код:
Код: Выделить всё
procedure TForm1.GetName;
Var
   vSizet  : DWord;
   vPWChart: PWideChar;
   vNamePC,
   vNameUser : String;
   I         : DWord;
   vWNameUser,
   vWNamePC  : WideString;
begin
     vSizet := 1024;
     vPWChart := GetMem(vSizet);
     // получаем имя ПК
     if GetComputerNameW(vPWChart, vSizet) then
     begin
        SetString(vWNamePC, vPWChart, vSizet);
        vNamePC := UTF8Encode(vWNamePC);
     end
     else
        vNamePC := '';
     Memo1.Lines.Add('Имя ПК: '+vNamePC);

     // получаем логин !!!
     vSizet := 1024;
     if GetUserNameW(vPWChart, vSizet) then
     begin
          SetString(vWNameUser, vPWChart, vSizet-1);
          vNameUser := UTF8Encode(vWNameUser);
     end
     else
     begin
        vNameUser := '';
        Memo1.Lines.Add('LastError: ' + SysErrorMessageUTF8(GetLastError));
     end;
     vNameUser := 'GetUserName: '+vNameUser;
     Memo1.Lines.Add(vNameUser);
     for i:= 0 to 12 do
     begin
          vSizet := 1024;
          if GetUserNameExW(I,vPWChart, vSizet) then
          begin
               SetString(vWNameUser, vPWChart, vSizet-1);
               vNameUser := UTF8Encode(vWNameUser);
          end
          else
          begin
               vNameUser := '';
               vNameUser := 'LastError: ' + SysErrorMessageUTF8(GetLastError);
          end;
          Memo1.Lines.Add('GetUserNameEx '+IntToStr(I)+': '+vNameUser);
     end;
     FreeMem(vPWChart);
end;

Размер использованного буфера возвращаемый системными функциями GetUserNameW и GetUserNameExW больше на 1.

Добавлено спустя 46 секунд:
Sharfik - спасибо!
Angel_19
новенький
 
Сообщения: 37
Зарегистрирован: 24.06.2014 17:29:47

Re: Глюки Lazarus

Сообщение Sharfik » 30.10.2014 12:50:46

Теперь ты мне подскажи, сделал как у тебя через GetMem выделение памяти под String.
При передаче адреса в качестве параметра функции в самой функции он уже не читается. Адрес другой.
Код: Выделить всё
....
vPString := GetMem(vSizet);
MyFunction(vPString ) // function MyFunction(Sender:Pointer):Integer;

Чтение это присвоение адреса аналогичной переменной с адресом
Код: Выделить всё
function MyFunction(Sender:Pointer):Integer;
...
vPString := Sender;
....text:=vPString^;

Я ошибся в присвоениях или система не позволяет передать объявленный участок памяти в другую функцию?
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Глюки Lazarus

Сообщение zub » 30.10.2014 14:09:10

особо не вникал, но
>>сделал как у тебя через GetMem выделение памяти под String.
Выделять vPString := GetMem(vSizet); смысла нет, т.к. нужно vPString := GetMem(sizeof(string)) - выделяем память под переменную, под значение память выделит rtl, но нужно незабыть ее проинициализировать, иначе будут AV

>>При передаче адреса в качестве параметра функции в самой функции он уже не читается. Адрес другой.
ты похоже путаешь @vPString и @vPStringх[1] - для стрингов адрес переменной и адрес значения (содержимого переменной) - разные вещи
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Глюки Lazarus

Сообщение Sharfik » 30.10.2014 14:55:24

vPString:PString; //PString=^String
vPString - указатель на адрес значения
@vPString - указатель на адрес переменной с указателем на значение
Передаваться должен первый. С ним по работе проблем нет, пока не читаю указатель в функции вложенной, там адрес другой получаю. Вроде всегда нормально было, а тут бред...
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Глюки Lazarus

Сообщение zub » 30.10.2014 16:39:42

vPString:PString; //PString=^String
vPString - указатель на адрес значения
@vPString - указатель на адрес переменной с указателем на значение

Что есть значение?
>>vPString - указатель на адрес значения
Указатель на переменную типа string, а указатель на само текстовое значение лежит внутри этой переменной вместе с другой служебной информацией

Код: Выделить всё
vPString:pstring;
....
vPString := GetMem(sizeof(string));
pointer(vPString):=nil;
pstring^:=text;

MyFunction1(vPString);//MyFunction1(param:pstring)
MyFunction2(vPString^);//MyFunction2(param:string)
MyFunction3(@vPString^[1]);//MyFunction3(param:pchar)

должно быть чтото типа такого при динамическом создании стрингов

>>Вроде всегда нормально было, а тут бред...
попрежнему всё нормально, ищите ошибки))
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Глюки Lazarus

Сообщение Sharfik » 02.11.2014 02:29:15

Все проще, я правильно делал, только stdcall; функции которой передавал адрес не прописал. :D
Аватара пользователя
Sharfik
энтузиаст
 
Сообщения: 809
Зарегистрирован: 20.07.2013 01:04:30

Re: Глюки Lazarus

Сообщение Alex2013 » 03.11.2014 14:56:38

Для выделения памяти под динамические строки
Лучше всего применять функцию NewStr(const S: string): PString;
в паре с DisposeStr(S: PString);
То есть что задал то и освободил .И никаких лишних "танцев с бубном" вокруг длины строки ...
(Что с учетом кодировки UTF8 задача временами не тривиальная )
Alex2013
долгожитель
 
Сообщения: 3145
Зарегистрирован: 03.04.2013 11:59:44


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 236

Рейтинг@Mail.ru
cron