Page 1 of 1

FreeOCI call does not unload Oracle dll's

Posted: Tue 06 Dec 2011 11:05
by dados
Hi,

I'm using:
Win7 32bit
Delphi XE2 Update 2
ODAC PRO 8.1.3 for Delphi XE2

Steps to reproduce:
1. Delphi -> New VCL Form Application
2. put "oracall" in uses clause;
3. in FormCreate put these two line:
InitOCI;
FreeOCI;
4. Run program...

If you use Process Explorer from Sysinternal and monitor the process while you step through the two lines you can see that oci.dll and many other oracle dll's are loaded with the InitOCI call but only oci.dll is unloaded when FreeOCI is called, leaving bunch of Oracle dll loaded.

I'm trying to change the oracle HOME property and load the correct dll's and I want to be able to do this without having to close my program and start another. Because once I've called InitOCI and connected to my session I'm stuck with the selected Oracle Home.

I've seen that SQL Navigator from Quest does load/unload Oracle DLL's perfectly :)

Reg,
Arni Thor

Posted: Wed 07 Dec 2011 11:15
by AlexP
Hello,

Thank you for the information.
We know about this problem, we are working on it.

Posted: Thu 08 Dec 2011 00:03
by dados
Excellent

Thanks.

Posted: Wed 29 Feb 2012 11:52
by dados
Hi,

Do you have any development news on this issue?

Reg,
Arni Thor

Posted: Fri 02 Mar 2012 14:16
by AlexP
Hello,

We continue to study this problem. However, more probably, the problem is due to Oci.dll that doesn't free the libraries that it uses.
We have checked this behaviour not using our components. We just used Api methods for downloading and uploading libraries, the library's methods (Delphi), and also the Oci.h and Oci.Lib files (C++) distributed together with Oracle. In both cases, the additionally downloaded libraries remain not uploaded till the end of the application work. There is a code of these projects.

Code: Select all

program ConsolApplication;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows;

type
_OCIEnvCreate = function (var envhpp: pointer; mode: cardinal; const ctxp: pointer;
const malocfp: pointer; const ralocfp: pointer;
const mfreefp: pointer; xtramemsz: Cardinal; usrmempp: pointer): integer; cdecl;

_OCIHandleFree = function (hndlp: pointer; htype: Cardinal): integer;  cdecl;

_OCITerminate  = function (mode: Cardinal): integer; cdecl;
var
  hOraLib: HMODULE;
  hOCIEnv: pointer;
  hOCIError: pointer;
  OCIEnvCreate: _OCIEnvCreate;
  OCIHandleFree: _OCIHandleFree;
  OCITerminate: _OCITerminate;
begin
    hOraLib := LoadLibraryEx('Path to oci.dll',0, LOAD_WITH_ALTERED_SEARCH_PATH);
    OCIEnvCreate := GetProcAddress(hOraLib, 'OCIEnvCreate');
    OCIEnvCreate(hOCIEnv,7,nil, nil, nil, nil, 0, nil);
    OCIHandleFree := GetProcAddress(hOraLib, 'OCIHandleFree');
    OCIHandleFree(hOCIEnv,1);
    OCITerminate := GetProcAddress(hOraLib, 'OCITerminate');
    OCITerminate(0);
    FreeLibrary(hOraLib);
    ReadLn;
end.

Code: Select all

#include 
#include 
#include 

using namespace std;

void checkerr(OCIError* err, sword status) {
  text errbuf[512];
  ub4 buflen;
  sb4 errcode;

  switch (status) {
  case OCI_SUCCESS:
    break;
  case OCI_SUCCESS_WITH_INFO:
    printf("Error - OCI_SUCCESS_WITH_INFO\n");
    break;
  case OCI_NEED_DATA:
    printf("Error - OCI_NEED_DATA\n");
    break;
  case OCI_NO_DATA:
    printf("Error - OCI_NO_DATA\n");
    break;
  case OCI_ERROR:
    OCIErrorGet ( err, (ub4) 1, (text *) NULL, &errcode, errbuf, (ub4) sizeof(errbuf), (ub4) OCI_HTYPE_ERROR);
    printf("Error - %s\n", errbuf);
    break;
  case OCI_INVALID_HANDLE:
    printf("Error - OCI_INVALID_HANDLE\n");
    break;
  case OCI_STILL_EXECUTING:
    printf("Error - OCI_STILL_EXECUTE\n");
    break;
  case OCI_CONTINUE:
    printf("Error - OCI_CONTINUE\n");
    break;
  default:
    break;
  }
}


int main(int argc, char *argv[])
{

  OCIEnv*       env;

  OCIError*     err;

  OCIServer*    srv;
  OCISvcCtx*    svc;
  OCISession*   ses;
  OCISvcCtx*     svchp;

  sword         r;

  text         bufp;

  env           =       0;
  err           =       0;
  srv           =       0;
  svc           =       0;
  ses           =       0;

  r=OCIEnvCreate( &env, OCI_DEFAULT, 0, 0, 0, 0, 0, 0); 

  if (r != OCI_SUCCESS)  {
    printf("OCIEnvCreate failed!\n");
    goto clean_up;
  }

  OCIHandleAlloc(env, (dvoid**)&err, OCI_HTYPE_ERROR,   0, 0);
  OCIHandleAlloc(env, (dvoid**)&srv, OCI_HTYPE_SERVER,  0, 0);
  OCIHandleAlloc(env, (dvoid**)&svc, OCI_HTYPE_SVCCTX,  0, 0);
  OCIHandleAlloc(env, (dvoid**)&ses, OCI_HTYPE_SESSION, 0, 0);

  r=OCIServerAttach(srv, err,  (text* )"orcl1020", strlen("orcl1020"), (ub4) OCI_DEFAULT);
  if (r != OCI_SUCCESS) {
    checkerr(err, r);
    goto clean_up;
  }

  OCIAttrSet(svc, OCI_HTYPE_SVCCTX, srv, 0, OCI_ATTR_SERVER,  err);

  OCIAttrSet(ses, OCI_HTYPE_SESSION, (text* )"scott", strlen("scott"), OCI_ATTR_USERNAME, err); 
  OCIAttrSet(ses, OCI_HTYPE_SESSION, (text* )"tiger", strlen("tiger"), OCI_ATTR_PASSWORD, err); 

  r=OCISessionBegin (svc, err, ses, OCI_CRED_RDBMS, OCI_DEFAULT);
  checkerr(err, r);
  
clean_up:
  if (env) OCIHandleFree(env, OCI_HTYPE_ENV   );
  if (err) OCIHandleFree(err, OCI_HTYPE_ERROR );
  if (srv) OCIHandleFree(srv, OCI_HTYPE_SERVER);
  if (svc) OCIHandleFree(svc, OCI_HTYPE_SVCCTX);
  OCITerminate(OCI_DEFAULT);

    system("PAUSE");
    return EXIT_SUCCESS;
}
Try ask this question at the Oracle developers forum

Posted: Fri 02 Mar 2012 15:21
by dados
Ok, thanks.

But if it is an Oracle issue then it's kinda weird thank Quest's SQL Navigator is able to do it.

Reg,
Arni Thor

Posted: Sat 03 Mar 2012 14:22
by AlexP
Hello,

We have checked the Quest's SQL Navigator 6.5.0.2090 behaviour, and the downloaded Oracle libraries don't unload when changing the client version. I have sent you a Process Explorer screenshot showing that libraries from all the clients remain in memory.