Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблема со строками 8-( [D4, Win95/98]


Cobalt ©   (2002-09-16 09:35:00) 

Строки копируются не всегда, а время от времени

Procedure TProcessList.Add_PInfo(AInfo:TProcessEntry32);
var tmp:PProcessInfo;
begin
if First=nil
then
begin
GetMem(First,SizeOf(TProcessInfo));
tmp:=First;
end
else
begin //Находим последний элемент с пустым "окончанием"
tmp:=First;
while tmp.Next<>nil do
tmp:=tmp.Next;
GetMem(tmp.Next,SizeOf(TProcessInfo));
tmp:=tmp.Next;
end;
with tmp^ do
begin
PID:=AInfo.th32ProcessID;
OwnPID:=AInfo.th32ParentProcessID;
Checked:=false;
Next:=nil;
//SetLength(FullName,length(AInfo.szExeFile));
FullName:=Application.ExeName; Здесь происходит AV
// FullName:=AInfo.szExeFile;
except
end
end;
end;
PProcessInfo = ^TProcessInfo;

TProcessInfo = record
PID,
OwnPID : Cardinal;
FullName : string;
Checked : boolean;
Next : PProcessInfo;
end;

TProcessList = class
First : PProcessInfo;
Constructor Create;
Procedure Add_PInfo(AInfo:TProcessEntry32);
Function DuplicateExist(AInfo:PProcessInfo):boolean;
Destructor Destroy;reintroduce;
end;

Может кто подскажет, где можно тут накосячить?


REA   (2002-09-18 10:23:00) [1]

Ему надо видимо мусор собирать динамический и создавать заголовки массивов, а GetMem это не умеет.


Alx2   (2002-09-18 07:30:00) [2]

>REA (17.09.02 15:20)
>Т.е. строки в записях с GetMem вообще нельзя хранить?
Видимо, это связано с заполнением структуры RTTI.
В частности,в D6 в ходе выполнения New вызывается

procedure _InitializeRecord(p: Pointer; typeInfo: Pointer);
var
FT: PFieldTable;
I: Cardinal;
begin
FT := PFieldTable(Integer(typeInfo) + Byte(PTypeInfo(typeInfo).Name[0]));
for I := FT.Count-1 downto 0 do
_InitializeArray(Pointer(Cardinal(P) + FT.Fields[I].Offset), FT.Fields[I].TypeInfo^, 1);
end;

где _InitializeArray:

const
tkLString = 10;
tkWString = 11;
tkVariant = 12;
tkArray = 13;
tkRecord = 14;
tkInterface = 15;
tkDynArray = 17;

procedure _InitializeArray(p: Pointer; typeInfo: Pointer; elemCount: Cardinal);
{$IFDEF PUREPASCAL}
var
FT: PFieldTable;
begin
if elemCount = 0 then Exit;
case PTypeInfo(typeInfo).Kind of
tkLString, tkWString, tkInterface, tkDynArray:
while elemCount > 0 do
begin
PInteger(P)^ := 0;
Inc(Integer(P), 4);
Dec(elemCount);
end;
tkVariant:
while elemCount > 0 do
begin
PInteger(P)^ := 0;
PInteger(Integer(P)+4)^ := 0;
PInteger(Integer(P)+8)^ := 0;
PInteger(Integer(P)+12)^ := 0;
Inc(Integer(P), sizeof(Variant));
Dec(elemCount);
end;
tkArray:
begin
FT := PFieldTable(Integer(typeInfo) + Byte(PTypeInfo(typeInfo).Name[0]));
while elemCount > 0 do
begin
_InitializeArray(P, FT.Fields[0].TypeInfo^, FT.Count);
Inc(Integer(P), FT.Size);
Dec(elemCount);
end;
end;
tkRecord:
begin
FT := PFieldTable(Integer(typeInfo) + Byte(PTypeInfo(typeInfo).Name[0]));
while elemCount > 0 do
begin
_InitializeRecord(P, typeInfo);
Inc(Integer(P), FT.Size);
Dec(elemCount);
end;
end;
else
Error(reInvalidPtr);
end;
end;

Короче говоря, модуль system.pas вносит полную ясность в происходящее. Только почему в help ничего не сказано о столь значительной разнице между getmem и new?


Cobalt   (2002-09-18 00:40:00) [3]

>Alx2 ©
Спасибо. Просто при выборе GetMem/New я считал, что New - это больше для объектов(осталось еще с ТР 7.0). А так как у меня были записи, то решил использовать GetMem. Вот тебе и опыт 8-((


REA   (2002-09-17 15:20:00) [4]

Т.е. строки в записях с GetMem вообще нельзя хранить?
Не встречал такой информаци...


Alx2   (2002-09-17 13:47:00) [5]

Нашел разницу!
В ходе работы New вызывается initializeArray, где и происходит недостающее при GetMem таинство :)


Alx2   (2002-09-17 13:32:00) [6]

Хотя принципиальной разницы с GetMem быть не должно. Надо посмотреть еще.
Но факт: с заменой Getmem на New все заработало :)


Alx2   (2002-09-17 12:38:00) [7]

Еще вдогонку:
Парной к New является Dispose.


Alx2   (2002-09-17 12:37:00) [8]

>Cobalt © (17.09.02 12:26)
Нашел я твои ошибки :)

record оставь в покое.

Деструктор объяви как
Destructor Destroy; override;

И причина глюка - вместо GetMem используй New
Вот как здесь:

procedure TProcessList.Add_PInfo(AInfo: TProcessEntry32);
var tmp: PProcessInfo;
begin
if First = nil
then
begin
New(First);
tmp := First;
end
else
begin
tmp := First;
while tmp.Next <> nil do
tmp := tmp.Next;
New(tmp.Next);
tmp := tmp.Next;
end;
with tmp^ do
begin
PID := AInfo.th32ProcessID;
OwnPID := AInfo.th32ParentProcessID;
Checked := false;
Next := nil;
try
//SetLength(FullName,length(AInfo.szExeFile));
FullName := Application.ExeName;
// FullName:=AInfo.szExeFile;
except
end
end;
end;


REA   (2002-09-17 12:33:00) [9]

Мистика. Видимо надо смотреть как остальное сделано. Я обычно делаю TObjectList наследника и не вожусь со списками. Тем более что всякие очереди списки хэши стэки и бэги там есть.


Cobalt   (2002-09-17 12:26:00) [10]

Alx2 © (17.09.02 07:09)

>Cobalt © (16.09.02 23:32)
sharemem?

попробовал добавить этот модуль - стала выскакивать ошибка EInvalidPointer !при закрытии формы! (обработчиков событий на это нет), так что это не то ;(

Заменил record на Class - ошибка пропала!
Это наверное, Борланд классы продвигает таким путем...
http://cobalt747.narod.ru/ProcessViewer.zip(4,83 КБ)


Alx2   (2002-09-17 07:09:00) [11]

>Cobalt © (16.09.02 23:32)
sharemem?


Cobalt   (2002-09-16 23:32:00) [12]

REA (16.09.02 17:57)
Вот это я и пробовал, простую, стопудово существующую строку.
Никак потоков нет, по таймеру(уже по кнопке;) пытаюсь заполнить связанный список.
причем
with tmp^ do
begin
PID:=AInfo.th32ProcessID;
OwnPID:=AInfo.th32ParentProcessID;
Checked:=false;
Next:=nil;// До этого все в порядке
FullName:=Application.ExeName;
Здесь происходит AV

Интересное дело: комментирую операцию со строками - список работает (проверял по PID процессов)


REA   (2002-09-16 17:57:00) [13]

FullName:=Application.ExeName - а если просто строку туда? Может что то с потоками?


Cobalt   (2002-09-16 17:52:00) [14]


> REA (16.09.02 10:59)
> А не из DLL код вызывается?
нет

> Alx2 © (16.09.02 11:50)
> TProcessList = class
> First : PProcessInfo;
> Constructor Create; - Там есть First := nil?
Да
Вот последняя версия "этого дела": http://cobalt747.narod.ru/ProcessViewer.zip
Такое впечатление, что память либо не выделяется, либо теряется


Alx2   (2002-09-16 11:50:00) [15]

TProcessList = class
First : PProcessInfo;
Constructor Create;- Там есть First := nil?
Procedure Add_PInfo(AInfo:TProcessEntry32);
Function DuplicateExist(AInfo:PProcessInfo):boolean;
Destructor Destroy;reintroduce;
end;


REA   (2002-09-16 10:59:00) [16]

А не из DLL код вызывается?


Наверх

Титульная страница Поиск, карта сайта Написать письмо