Intel® Integrated Performance Primitives
Deliberate problems developing high-performance vision, signal, security, and storage applications.
6709 Discussions

IPP 6.0.0.062 for windows dynamic linking vs LoadLibrary issue

matthieu_darbois
New Contributor III
555 Views

Hi,

I've run into a weird problem while using some software using IPP and openCV.

My software only uses ippi (from ipp) and openCV libraries. All is linked against the dynamic version of ippi, ippcore & cxcore.

When it loads, it starts by loading dependency dlls : ippi, ippcore and cxcore. As you must know, openCV is programmed to automatically load ipp if present. It does this by using the LoadLibrary function. What happens is that the LoadLibrary will fail to load any ipp module except the ones dynamically linked by the software.

You can reproduce this behaviour using cxcore and cxcoretest projects from openCV.

I just modified cxcoretest_main.cpp from cxcoretest as follow

[cpp]#include "PATH_TO_IPP_6.0_IA32includeipp.h"

#pragma comment(lib, "PATH_TO_IPP_6.0_IA32\stublib\ippcore.lib")
#pragma comment(lib, "PATH_TO_IPP_6.0_IA32\stublib\ippi.lib")
int main( int argc, char** argv )
{
    const IppLibraryVersion* ippVersion = ippiGetLibVersion();

    printf("%s", ippVersion->Name);

    return test_system.run( argc, argv );
}[/cpp]

The worst about it is that when failing to load ipp 6.0 modules, openCV would try to load 5.3 module which are also installed on my computer resulting in libguide40 and libiomp5md to conflict....

I made the same test with ipp 5.3 version (by removing 6.0 module from cxswitcher.cpp and using 5.3 in cxcoretest_main.cpp) and it worked just fine (all modules are loaded)

What seems to happen is the following : ippMalloc function in ippcore doesn't seem to be properly initialized (it makes a call to some unitialized function pointer) when LoadLibrary function is called.

Is this a known regression ?

Will there be a new release shortly ?

Regards

Matthieu

0 Kudos
1 Solution
Vladimir_Dudnik
Employee
555 Views
Emmanuel,
this is not exactly correct. According Microsoft documentation it is possible to call LoadLibrary from DLL (this way IPP dispatcher load processor-specific DLLs). Of course there are some limitations, mentioned in MSDN
Regards,
Vladimir

View solution in original post

0 Kudos
6 Replies
Vladimir_Dudnik
Employee
555 Views
Unmodified OpenCV should be able to load IPP 6.0 DLLs dynamically. Could you please explain what specific issue you have with it?
Vladimir

0 Kudos
matthieu_darbois
New Contributor III
555 Views
Quoting - vdudnik
Unmodified OpenCV should be able to load IPP 6.0 DLLs dynamically. Could you please explain what specific issue you have with it?
Vladimir

Hi,

The issue here is not OpenCV related. I just used OpenCV to illustrate that issue because I discovered this problem using OpenCV and anyone can reproduce this behaviour using it.

As I understand, my previous post wasn't clear enough. I tried to make a simple test case not OpenCV related to illustrate this behaviour and it became weirder.

So let me explain it again :

On one hand, I've got a dynamic module which does some stuff and uses ipp modules when found (like OpenCV does). It does this with the help of the LoadLibrary function. The LoadLibrary function is called when the module is loaded (DllMain / C++ class initializer). We'll call it "foo.dll".

On the other hand, I've got an executable which uses functions from ippi module and foo module. It links with the ippi stublib and the foo stublib.

When I start the executable, foo.dll loads and will fail to load any ipp module except ippi

I could reproduce this behaviour with the following code.

main.cpp :

[cpp]#include 
#include 
#include "ipp-6.0-ia32includeipp.h"
#pragma comment(lib, "foo.lib")
#pragma comment(lib, "ipp-6.0-ia32stublibippi.lib")

__declspec(dllimport) const char* __cdecl GetIppsVersionName(void);

int main(int argc, char* argv[])
{
    const IppLibraryVersion* ippVersion;
    
    ippVersion = ippiGetLibVersion();
    printf("%sn", ippVersion->Name);


    printf("%sn", GetIppsVersionName());

    getc(stdin);
	return 0;
}[/cpp]

foo.cpp:

[cpp]#include 
#include 
#include "ipp-6.0-ia32includeipp.h"

HMODULE ippModule;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  fdwReason,
                       LPVOID lpReserved
					 )
{
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
            ippModule = LoadLibraryA("ipps-6.0.dll");
            break;
        default:
            break;
    }
    return TRUE;
}

typedef const IppLibraryVersion* (__stdcall * version_fn)(void);

__declspec(dllexport) const char* __cdecl DummyGetIppsVersionName(void)
{
    static const char error[] = "Couldn't load ipps-6.0.dll module";

    if (ippModule == NULL)
        return error;
    version_fn GetVersion = (version_fn)GetProcAddress(ippModule, "ippsGetLibVersion");

    return GetVersion()->Name;
}[/cpp]

Here is the printed output :

ippiv8-6.0.dll
Couldn't load ipps-6.0.dll module

The strangest thing occured when I swapped two lines in main.cpp

if you try using this

[cpp]
#pragma comment(lib, "ipp-6.0-ia32stublibippi.lib")
#pragma comment(lib, "foo.lib")[/cpp]

then the output will be

ippiv8-6.0.dll
ippsv8-6.0.dll

In the first case, ippcore-6.0.dll and ippi-6.0.dll appears in the debugger as loaded whereas in the second case ippiv8-6.0.dll is also loaded. Curiously the same behaviour apply for 5.3 in my test case but not in OpenCV (weird again...)

What went wrong at which point ?

0 Kudos
Emmanuel_W_
New Contributor I
555 Views

Hi,

The issue here is not OpenCV related. I just used OpenCV to illustrate that issue because I discovered this problem using OpenCV and anyone can reproduce this behaviour using it.

As I understand, my previous post wasn't clear enough. I tried to make a simple test case not OpenCV related to illustrate this behaviour and it became weirder.

So let me explain it again :

On one hand, I've got a dynamic module which does some stuff and uses ipp modules when found (like OpenCV does). It does this with the help of the LoadLibrary function. The LoadLibrary function is called when the module is loaded (DllMain / C++ class initializer). We'll call it "foo.dll".

On the other hand, I've got an executable which uses functions from ippi module and foo module. It links with the ippi stublib and the foo stublib.

When I start the executable, foo.dll loads and will fail to load any ipp module except ippi

I could reproduce this behaviour with the following code.

main.cpp :

#include #include #include "ipp-6.0-ia32includeipp.h" #pragma comment(lib, "foo.lib") #pragma comment(lib, "ipp-6.0-ia32\stublib\ippi.lib") __declspec(dllimport) const char* __cdecl GetIppsVersionName(void); int main(int argc, char* argv[]) { const IppLibraryVersion* ippVersion; ippVersion = ippiGetLibVersion(); printf("%sn", ippVersion->Name); printf("%sn", GetIppsVersionName()); getc(stdin); return 0; }

foo.cpp:

#include #include #include "ipp-6.0-ia32includeipp.h" HMODULE ippModule; BOOL APIENTRY DllMain( HMODULE hModule, DWORD fdwReason, LPVOID lpReserved ) { switch( fdwReason ) { case DLL_PROCESS_ATTACH: ippModule = LoadLibraryA("ipps-6.0.dll"); break; default: break; } return TRUE; } typedef const IppLibraryVersion* (__stdcall * version_fn)(void); __declspec(dllexport) const char* __cdecl DummyGetIppsVersionName(void) { static const char error[] = "Couldn't load ipps-6.0.dll module"; if (ippModule == NULL) return error; version_fn GetVersion = (version_fn)GetProcAddress(ippModule, "ippsGetLibVersion"); return GetVersion()->Name; }


Here is the printed output :

ippiv8-6.0.dll
Couldn't load ipps-6.0.dll module

The strangest thing occured when I swapped two lines in main.cpp

if you try using this

#pragma comment(lib, "ipp-6.0-ia32\stublib\ippi.lib") #pragma comment(lib, "foo.lib")



then the output will be

ippiv8-6.0.dll
ippsv8-6.0.dll

In the first case, ippcore-6.0.dll and ippi-6.0.dll appears in the debugger as loaded whereas in the second case ippiv8-6.0.dll is also loaded. Curiously the same behaviour apply for 5.3 in my test case but not in OpenCV (weird again...)

What went wrong at which point ?

Hi,

I believe you are not allowed to call LoadLibrary from dllmain (see MSDN documentation)

Emmanuel

0 Kudos
Vladimir_Dudnik
Employee
556 Views
Emmanuel,
this is not exactly correct. According Microsoft documentation it is possible to call LoadLibrary from DLL (this way IPP dispatcher load processor-specific DLLs). Of course there are some limitations, mentioned in MSDN
Regards,
Vladimir

0 Kudos
matthieu_darbois
New Contributor III
555 Views
Quoting - vdudnik
Emmanuel,
this is not exactly correct. According Microsoft documentation it is possible to call LoadLibrary from DLL (this way IPP dispatcher load processor-specific DLLs). Of course there are some limitations, mentioned in MSDN
Regards,
Vladimir

Hi,

Thanks for your input. I've just looked at MSDN documentation to see what are the limitations.

So, in my previous example, it appears that ippcore-6.0.dll is assumed to be loaded when trying to load ipps-6.0.dll. But initialization code (DllMain) from ippcore-6.0.dll had not been called yet.

So in my case, I'll just do it otherwise. As for OpenCV, it doesn't follow recommendations in MSDN and that's what causing such a mess...

Regards,

Matthieu

0 Kudos
Emmanuel_W_
New Contributor I
555 Views
Quoting - vdudnik
Emmanuel,
this is not exactly correct. According Microsoft documentation it is possible to call LoadLibrary from DLL (this way IPP dispatcher load processor-specific DLLs). Of course there are some limitations, mentioned in MSDN
Regards,
Vladimir

Hi Vladimir,

This is indeed a tricky subject. Here is what the documentation says under DllMain (I do believe the restriction was not as clearly stated in the past but I didn't install an older MSDN library to check ;) )

The entry-point function should perform only simple initialization or termination tasks. It must not call the LoadLibrary or LoadLibraryEx function (or a function that calls these functions), because this may create dependency loops in the DLL load order. This can result in a DLL being used before the system has executed its initialization code. Similarly, the entry-point function must not call the FreeLibrary function (or a function that calls FreeLibrary) during process termination, because this can result in a DLL being used after the system has executed its termination code.

Also in the MSFT "Dll best practice document":

Call LoadLibrary or LoadLibraryEx (either directly or indirectly). This can cause a deadlock or a crash.

...

Of course if you want to load your own dll and you know you don't introduce any loop then there is no technical limitation.

Emmanuel

0 Kudos
Reply