![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Проблема со строками 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Здесь происходит AV
begin
PID:=AInfo.th32ProcessID;
OwnPID:=AInfo.th32ParentProcessID;
Checked:=false;
Next:=nil;// До этого все в порядке
FullName:=Application.ExeName;
Интересное дело: комментирую операцию со строками - список работает (проверял по 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 код вызывается?