Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CRITICAL_SECTION not initialized globally in DllMain

1,094 views
Skip to first unread message

Fabian

unread,
Jul 6, 2009, 8:08:01 AM7/6/09
to

Hi,

I want to use a CRITICAL_SECTION within a DLL function declared as extern
"C". With EnterCriticalSection I get an Access violation exception even
though I have initialized the CRITICAL_SECTION object before.

My CRITICAL_SECTION object is declared in a header file as follows:

static CRITICAL_SECTION csCalibrate;

The initialization in DllMain():

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
InitializeCriticalSection(&csCalibrate);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
DeleteCriticalSection(&csCalibrate);
break;
}
return TRUE;
}

The function code:

extern "C" int BEADALIGNMENT_API FindRotationCenter( const char* const
FileAngleOne, const char* const FileAngleTwo, double Theta, double& PosX,
double& PosY, double& PosZ )
{
EnterCriticalSection(&csCalibrate); // raises "Access violation writing
location 0x00000010"
// ...
LeaveCriticalSection(&csCalibrate);
}

DllMain is executed. The CRITICAL_SECTION object is initialized. But in my
FindRotationCenter function it reappears as uninitialized. Any idea?

Thanks for your help,

Fabian

Leo Davidson

unread,
Jul 6, 2009, 9:58:34 AM7/6/09
to
>         switch (ul_reason_for_call)
>         {
>         case DLL_PROCESS_ATTACH:
>                 InitializeCriticalSection(&csCalibrate);
>                 break;
>         case DLL_THREAD_ATTACH:
>         case DLL_THREAD_DETACH:
>         case DLL_PROCESS_DETACH:
>                 DeleteCriticalSection(&csCalibrate);
>                 break;
>         }

You are deleting the critical section on thread attach and thread
detach. I think you missed a couple of break; lines there. :)

BTW, if your DllMain doesn't do anything on thread attach/detach then
you can improve performance a bit by calling DisableThreadLibraryCalls
() during process attach.

Alexander Grigoriev

unread,
Jul 6, 2009, 9:58:04 AM7/6/09
to

break after DLL_THREAD_ATTACH, DLL_THREAD_DETACH. You don't want to delete
the CS there.

"Fabian" <Fab...@discussions.microsoft.com> wrote in message
news:267FE375-2B69-40BE...@microsoft.com...

dan...@resplendence.com

unread,
Jul 6, 2009, 10:00:02 AM7/6/09
to
What is the point of declaring a static variable if it's already global.
Does static global not mean it's valid only in the context of the same
source file ?

//Daniel


"Fabian" <Fab...@discussions.microsoft.com> wrote in message
news:267FE375-2B69-40BE...@microsoft.com...

rogero

unread,
Jul 6, 2009, 10:26:58 AM7/6/09
to
On Jul 6, 3:00 pm, <dan...@resplendence.com> wrote:
> What is the point of declaring a static variable if it's already global.
> Does static global not mean it's valid only in the context of the same
> source file ?

It means each source file gets it's *own* copy of the variable.
This, I believe, explains the AV - the variable that gets initialised
is in one source file and is a *different* variable to the one in the
FindRotationCenter.

Roger.

Fabian

unread,
Jul 6, 2009, 11:28:01 AM7/6/09
to

Hi Leo,

> You are deleting the critical section on thread attach and thread
> detach. I think you missed a couple of break; lines there. :)

You're right. I overlooked that. Thanks very much.

Fabian

Fabian

unread,
Jul 6, 2009, 11:46:01 AM7/6/09
to
Hi Roger,

"rogero" wrote:

If I only declare it global in the header file the linker strikes:

Error 1 error LNK2005: "struct _RTL_CRITICAL_SECTION csCalibrate"
(?csCalibrate@@3U_RTL_CRITICAL_SECTION@@A) already defined in
dllmain.obj FindRotationCenter.obj BeadAlignment

How else do I solve this?

Thx,

Fabian

Fabian

unread,
Jul 6, 2009, 11:57:01 AM7/6/09
to

Actually I solved it. I forgot to define it:

declaration in header file:

extern "C" CRITICAL_SECTION csCalibrate;

definition in cpp file:

CRITICAL_SECTION csCalibrate;

m

unread,
Jul 6, 2009, 6:37:17 PM7/6/09
to

As you have discovered, declaring variables in header files is a bad idea.
In this case, the same header file being included in multiple compilation
units (.c or .cpp source files) causes multiple declarations of the same
variable; unless, as when you specified static, the declarations are local
scope (internal linkage) to the compilation unit. To find out more, read
the C or C++ spec or some of the commentary in MSDN.

"Fabian" <Fab...@discussions.microsoft.com> wrote in message

news:7C4EE0DA-B153-43D9...@microsoft.com...

Fabian

unread,
Jul 7, 2009, 2:11:01 AM7/7/09
to
Hi m,

> As you have discovered, declaring variables in header files is a bad idea.
> In this case, the same header file being included in multiple compilation
> units (.c or .cpp source files) causes multiple declarations of the same
> variable; unless, as when you specified static, the declarations are local
> scope (internal linkage) to the compilation unit. To find out more, read
> the C or C++ spec or some of the commentary in MSDN.

Sure, I usually don't use globals at all (if Singletons don't count). But in
this specific case with a synchronization object across different C functions
I didn't come up with an alternative solution. Can you give me a hint?

Christian Kaiser

unread,
Jul 7, 2009, 2:55:08 AM7/7/09
to

Well your "extern" is perfect, but you don't need "extern "C"".

extern CRITICAL_SECTION g_myCS;

and in ONE source file you define it (without "extern"). That's the
way to go.

You can, however, use a class construct:

class CCritSect
: public CRITICAL_SECTION
{
public:
CCritSect() {
::InitializeCriticalSection(this); }
~CCritSect() {
::DeleteCriticalSection(this); }
};

Then you use in the header file "extern CCritSect g_myCS;", and in one
CPP file "CCritSect g_myCS;", and you don't need to care about
initialization etc. in WinMain(), this is done by the C startup code
(runtime).

Christian

"Fabian" <Fab...@discussions.microsoft.com> wrote in message

news:99C39F39-E472-46DF...@microsoft.com...

m

unread,
Jul 9, 2009, 12:05:48 AM7/9/09
to

Be aware that if an application is linked with a custom entry point, the CRT
init routines may not be called at all; or after some other code that may
try to use the CS. In my experience, the best way to deal with these
situations is to have a module specific global pointing to a structure of
context variables that are initialized at startup and cleaned up on
shutdown.


"Christian Kaiser" <bc...@gmx.de> wrote in message
news:OiTGf$s$JHA....@TK2MSFTNGP05.phx.gbl...

0 new messages