GUI program exits silently (32 bit, low RAM, LOB)
Posted: Mon 18 May 2020 18:25
Fetching many rows with lobs does sometimes not show an EOutOfMemory exception.
The program vanishes silently.
Very good reproducable with 19.6 oracle client, server version does not matter.
Tested with ODAC 10.3.9 and 11.1.3
Running form Delphi throws (internally) exception class $C0000005 'access violation at 0x72a0c823: read of address 0xfffffffb' from OraClasses.pas
From the user's point of view, it is very annoying if the program disappears without a message.
Although fetching gigabytes of data is not very smart.
Running the console (see sample code) prints stack trace from oracle client.
Sample code
The program vanishes silently.
Very good reproducable with 19.6 oracle client, server version does not matter.
Tested with ODAC 10.3.9 and 11.1.3
Running form Delphi throws (internally) exception class $C0000005 'access violation at 0x72a0c823: read of address 0xfffffffb' from OraClasses.pas
Code: Select all
Check(OCI8.OCIDescriptorAlloc(OCISvcCtx.hOCIEnv, LOBLocator, OCI_DTYPE_LOB, 0, nil));
From the user's point of view, it is very annoying if the program disappears without a message.
Although fetching gigabytes of data is not very smart.
Running the console (see sample code) prints stack trace from oracle client.
Code: Select all
ODAC: 11.1.3
Mem: 7.208.960
Mem: 1.819.230.208
Client: 19.6.0.0.0
Server: 12.2.0.1.0
Start 1
Open OK 1
Last OK 1 999 records
Mem: 1.874.677.760
Mem: 1.874.714.624
Start 2
Open OK 2
Errors in file :
OCI-21500: Interner Fehlercode, Argumente: [kgepop: no error frame to pop to], [], [], [], [], [], [], []
OCI-21503: Programm durch schwerwiegenden Fehler beendet
OCI-04030: Zu wenig Prozessspeicher für Versuch 16336 Byte zuzuweisen (koh-kghu sessi,alloc lob locator)
----- Call Stack Trace -----
calling call entry argument values in hex
location type point (? means dubious value)
-------------------- -------- -------------------- ----------------------------
02D488C7 CALLrel 02ED2448 18D3D4 1 2D48520 2D48980
2D48520 2D48980
71F80150 CALLreg 00000000 301C200 3
71FE61D8 CALLrel 71F7FDC0 301C200 3025E68 0 1 72E8B110
72E8B214
71FF998D CALLrel 71FE4EE0 301C200 3063CC0 3FD0 0
3063CEC 0
72039E89 CALLrel 71FF8D70 301C200 3063CC0 3FC4 0 0
2F241A0
72262E50 CALLrel 72039B70 301C200 3063CB0 FA4 1 2F241A0
305CA18
72262830 CALLrel 72262CF0 301C200 FA0 A 1 2F241A0 0 0
7225DBE5 CALLrel 72262220 301C200 FA0 A 1 2F241A0 0 0
02B3FDD5 CALLrel 02ED2AD8 301BAF0 FA0 A 2F241A0 0 40
02B374AA CALLrel 02B3D230 301BAF0 18FC20 32 1 0 0 0 0
_OCIDescriptorAlloc CALLptr 00000000 301BAF0 18FC20 32 0 0
()+43
...
Sample code
Code: Select all
{$APPTYPE CONSOLE}
program odactest19ram;
uses
SysUtils, Windows, PsAPI, Ora;
procedure WriteMemUsage;
var
MemCnt: PROCESS_MEMORY_COUNTERS;
begin
if GetProcessMemoryInfo(GetCurrentProcess, @MemCnt, SizeOf(MemCnt)) then
Writeln(Format('Mem: %.0n', [MemCnt.WorkingSetSize / 1]));
end;
var
Session: TOraSession;
Query: TOraQuery;
I: Integer;
P: Pointer;
procedure DoTest(ASql: string);
begin
Inc(I);
Writeln('Start ', I);
Query.SQL.Text := ASql;
Query.Open;
Writeln('Open OK ', I);
try
Query.Last;
Writeln('Last OK ', I, ' ', Query.RecordCount, ' records');
WriteMemUsage;
except
on E: Exception do
begin
Writeln('Last not OK ', I, ' ', Query.RecordCount, ' records');
Writeln(E.ClassName, ' ', E.Message);
WriteMemUsage;
end;
end;
Query.Close;
WriteMemUsage;
end;
begin
Writeln('ODAC: ', ODACVersion);
I := 96 * 1024 * 1024; // 96 MB - try different values - YMMV
WriteMemUsage;
while True do // waste some RAM - if no big table is available
begin
try
GetMem(P, I);
FillChar(P^, I, $FF);
except
Break;
end;
end;
WriteMemUsage;
I := 0;
Session := TOraSession.Create(nil);
Query := TOraQuery.Create(nil);
Query.Session := Session;
Session.ConnectString := 'system/manager@server';
Session.Connect;
Writeln('Client: ', Session.Home.OCIVersionSt);
Writeln('Server: ', Session.OracleVersion);
DoTest('SELECT O.*, TO_CLOB(OBJECT_NAME) AS CLOB FROM ALL_OBJECTS O WHERE ROWNUM < 1000');
DoTest('SELECT O.*, TO_CLOB(OBJECT_NAME) AS CLOB FROM ALL_OBJECTS O');
Writeln('End');
end.