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.