Discussion:
Access Violation using CCriticalSection in DLL
(too old to reply)
Brian Westcott
2007-04-07 15:27:56 UTC
Permalink
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL (That I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data to be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
Doug Harrison [MVP]
2007-04-07 16:25:43 UTC
Permalink
Post by Brian Westcott
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL (That I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data to be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
I think you must be using the word "program" when you mean "function", and
this makes your message a little confusing. Where are you declaring the
CCriticalSection? If its lifetime has ended by the time the DLL calls it,
you will have problems. That said, if the rest of your program can use it
successfully at the same time the DLL has problems, that would rule out a
lifetime issue. After verifying the CCriticalSection should still be valid
at the time the DLL uses it, and double-checking that "formatting the data"
isn't causing any buffer overflows, I'd compile the release mode version
with debug info and see if I could spot anything wrong under the debugger.
--
Doug Harrison
Visual C++ MVP
Brian Westcott
2007-04-07 17:12:18 UTC
Permalink
Sorry for the mangled description. The logger is actually a class that I
instantiate outside of the scope of my main program. CCriticalSection is
declared within the logger class. If I comment out calls to the logger in
the DLL, then the logger works OK once I return from the DLL, so lifetime
does not appear to be an issue.
I also am testing this by sending a very short message to the logger from
the DLL to ensure that I am not overrunning the Logger's buffer.
I have compiled evrything, including the DLL, with debug mode and
everything works when I run a debug version. When I execute the debug mode
without starting the debugger, it also works.
If I run the release mode of the main program with the debug version of the
DLL, then the program fails with an access violation in the call to Lock().
I get a beak at the point in the dbugger and the stack trace is:
NTDLL!7c918fea()
NTDLL!7c90104b()
Logger::EnterLogCriticalSection(), which is declared as:
void EnterLogCriticalSection() {ccs.Lock();}


ccs is the instantiated CCriticalSection in the Logger class.
If I take a look at ccs, it appears normal, except that
ccs.m_sect.OwningThread = NULL;

Is there any other info I can give that might help?
Post by Doug Harrison [MVP]
Post by Brian Westcott
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL (That I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data to be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
I think you must be using the word "program" when you mean "function", and
this makes your message a little confusing. Where are you declaring the
CCriticalSection? If its lifetime has ended by the time the DLL calls it,
you will have problems. That said, if the rest of your program can use it
successfully at the same time the DLL has problems, that would rule out a
lifetime issue. After verifying the CCriticalSection should still be valid
at the time the DLL uses it, and double-checking that "formatting the data"
isn't causing any buffer overflows, I'd compile the release mode version
with debug info and see if I could spot anything wrong under the debugger.
--
Doug Harrison
Visual C++ MVP
Doug Harrison [MVP]
2007-04-07 17:40:33 UTC
Permalink
Post by Brian Westcott
Sorry for the mangled description. The logger is actually a class that I
instantiate outside of the scope of my main program. CCriticalSection is
declared within the logger class. If I comment out calls to the logger in
the DLL, then the logger works OK once I return from the DLL, so lifetime
does not appear to be an issue.
I also am testing this by sending a very short message to the logger from
the DLL to ensure that I am not overrunning the Logger's buffer.
I have compiled evrything, including the DLL, with debug mode and
everything works when I run a debug version. When I execute the debug mode
without starting the debugger, it also works.
If I run the release mode of the main program with the debug version of the
DLL
There's your problem. In general, you can't expect to share C++ objects
between release and debug modules. Here, the layout of CCriticalSection
changes, which throws everything off. To see why, look inside <afxmt.h> at
the definition of CSyncObject, from which CCS derives. It contains:

#ifdef _DEBUG
CString m_strName;
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

This causes the debug and release versions to think the CRITICAL_SECTION
object contained in CCS resides in different locations in memory.
Post by Brian Westcott
then the program fails with an access violation in the call to Lock().
NTDLL!7c918fea()
NTDLL!7c90104b()
void EnterLogCriticalSection() {ccs.Lock();}
ccs is the instantiated CCriticalSection in the Logger class.
If I take a look at ccs, it appears normal, except that
ccs.m_sect.OwningThread = NULL;
That's normal for an unlocked CS.
Post by Brian Westcott
Is there any other info I can give that might help?
This was a very good description.
--
Doug Harrison
Visual C++ MVP
Joseph M. Newcomer
2007-04-09 05:14:30 UTC
Permalink
See below...
Post by Brian Westcott
Sorry for the mangled description. The logger is actually a class that I
instantiate outside of the scope of my main program. CCriticalSection is
declared within the logger class. If I comment out calls to the logger in
the DLL, then the logger works OK once I return from the DLL, so lifetime
does not appear to be an issue.
I also am testing this by sending a very short message to the logger from
the DLL to ensure that I am not overrunning the Logger's buffer.
I have compiled evrything, including the DLL, with debug mode and
everything works when I run a debug version. When I execute the debug mode
without starting the debugger, it also works.
If I run the release mode of the main program with the debug version of the
DLL,
*****
You can stop right there. this won't work, and any problems you encounter should be
expected. You cannot mix-and-match debug and release components like this.
****
Post by Brian Westcott
then the program fails with an access violation in the call to Lock().
NTDLL!7c918fea()
NTDLL!7c90104b()
void EnterLogCriticalSection() {ccs.Lock();}
ccs is the instantiated CCriticalSection in the Logger class.
If I take a look at ccs, it appears normal, except that
ccs.m_sect.OwningThread = NULL;
Is there any other info I can give that might help?
Post by Doug Harrison [MVP]
Post by Brian Westcott
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL (That I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data to be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
I think you must be using the word "program" when you mean "function", and
this makes your message a little confusing. Where are you declaring the
CCriticalSection? If its lifetime has ended by the time the DLL calls it,
you will have problems. That said, if the rest of your program can use it
successfully at the same time the DLL has problems, that would rule out a
lifetime issue. After verifying the CCriticalSection should still be valid
at the time the DLL uses it, and double-checking that "formatting the data"
isn't causing any buffer overflows, I'd compile the release mode version
with debug info and see if I could spot anything wrong under the debugger.
--
Doug Harrison
Visual C++ MVP
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Brian Westcott
2007-04-10 03:15:43 UTC
Permalink
I do not normally mix debug and release components, but I was trying to find
the source of the problem by using a debugger on at least the DLL
components.. My latest discoveries:
1) when I run the S/W in debug mode (all components) , it works.
2) When I run the same S/W, except compiled for release, it fails.
3) when I run the same program. compiled for release, on win2K, it works. I
am not recompiling this program on Win2K, I am simply copying the same
program from win XP and executing it. I have tried using the same copy of
MFC42.dll in both cases in case this was a Problem (it wasn't).

This S/W is many years old, and it has suddenly stopped running. Are there
changes made to WInXP that may be a factor??

The questions I am trying to get answered are:
1) There is obviously a difference between the way a debug compile and a
release compile work on Win XP. What is this difference?
2) Why does the release version work on Win2K and not on Win XP?
Post by Joseph M. Newcomer
See below...
Post by Brian Westcott
Sorry for the mangled description. The logger is actually a class that I
instantiate outside of the scope of my main program. CCriticalSection is
declared within the logger class. If I comment out calls to the logger in
the DLL, then the logger works OK once I return from the DLL, so lifetime
does not appear to be an issue.
I also am testing this by sending a very short message to the logger from
the DLL to ensure that I am not overrunning the Logger's buffer.
I have compiled evrything, including the DLL, with debug mode and
everything works when I run a debug version. When I execute the debug mode
without starting the debugger, it also works.
If I run the release mode of the main program with the debug version of the
DLL,
*****
You can stop right there. this won't work, and any problems you encounter should be
expected. You cannot mix-and-match debug and release components like this.
****
Post by Brian Westcott
then the program fails with an access violation in the call to Lock().
NTDLL!7c918fea()
NTDLL!7c90104b()
void EnterLogCriticalSection() {ccs.Lock();}
ccs is the instantiated CCriticalSection in the Logger class.
If I take a look at ccs, it appears normal, except that
ccs.m_sect.OwningThread = NULL;
Is there any other info I can give that might help?
Post by Doug Harrison [MVP]
Post by Brian Westcott
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL
(That
I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data
to
be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
I think you must be using the word "program" when you mean "function", and
this makes your message a little confusing. Where are you declaring the
CCriticalSection? If its lifetime has ended by the time the DLL calls it,
you will have problems. That said, if the rest of your program can use it
successfully at the same time the DLL has problems, that would rule out a
lifetime issue. After verifying the CCriticalSection should still be valid
at the time the DLL uses it, and double-checking that "formatting the data"
isn't causing any buffer overflows, I'd compile the release mode version
with debug info and see if I could spot anything wrong under the debugger.
--
Doug Harrison
Visual C++ MVP
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer
2007-04-10 15:04:55 UTC
Permalink
See below...
Post by Brian Westcott
I do not normally mix debug and release components, but I was trying to find
the source of the problem by using a debugger on at least the DLL
1) when I run the S/W in debug mode (all components) , it works.
****
Expected
****
Post by Brian Westcott
2) When I run the same S/W, except compiled for release, it fails.
****
See my essay "Surviving the release version" on my MVP Tips site. It also tells how to
create debugging information in the release version so you can debug a release version.
****
Post by Brian Westcott
3) when I run the same program. compiled for release, on win2K, it works. I
am not recompiling this program on Win2K, I am simply copying the same
program from win XP and executing it. I have tried using the same copy of
MFC42.dll in both cases in case this was a Problem (it wasn't).
****
See my essay. Also note that MFC42.dll is note the only dll involve. If you run
'depends', look at the list of modules and their versions on the machine that fails, and
look at the same list on the machine that runs it. It could be a difference in one of the
perhaps two dozen DLLs that typically appear in the depends list.
****
Post by Brian Westcott
This S/W is many years old, and it has suddenly stopped running. Are there
changes made to WInXP that may be a factor??
****
See above. The answer is "probably yes"
****
Post by Brian Westcott
1) There is obviously a difference between the way a debug compile and a
release compile work on Win XP. What is this difference?
****
Massive. The debug version uses a debug DLL (mfc42d.dll) and the release version uses a
release DLL (mfc42.dll). The debug version has a different stack frame layout than a
release version. The debug version checks things like stack consistency after calls (in
VS2003 and beyond it checks the integrity of the stack contents as well. The release
version is optimized code, the debug version is unoptimized code. The release version
heap is designed for performance, the debug version heap is designed for maximum integrity
checking. That's a start.
****
Post by Brian Westcott
2) Why does the release version work on Win2K and not on Win XP?
****
That's a deeper question. DLL Hell is a good first guess, but you need to build a
debuggable release version and start exploring.
****
Post by Brian Westcott
Post by Joseph M. Newcomer
See below...
Post by Brian Westcott
Sorry for the mangled description. The logger is actually a class that I
instantiate outside of the scope of my main program. CCriticalSection is
declared within the logger class. If I comment out calls to the logger in
the DLL, then the logger works OK once I return from the DLL, so lifetime
does not appear to be an issue.
I also am testing this by sending a very short message to the logger from
the DLL to ensure that I am not overrunning the Logger's buffer.
I have compiled evrything, including the DLL, with debug mode and
everything works when I run a debug version. When I execute the debug mode
without starting the debugger, it also works.
If I run the release mode of the main program with the debug version of the
DLL,
*****
You can stop right there. this won't work, and any problems you encounter should be
expected. You cannot mix-and-match debug and release components like this.
****
Post by Brian Westcott
then the program fails with an access violation in the call to Lock().
NTDLL!7c918fea()
NTDLL!7c90104b()
void EnterLogCriticalSection() {ccs.Lock();}
ccs is the instantiated CCriticalSection in the Logger class.
If I take a look at ccs, it appears normal, except that
ccs.m_sect.OwningThread = NULL;
Is there any other info I can give that might help?
Post by Doug Harrison [MVP]
Post by Brian Westcott
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL
(That
I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data
to
be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
I think you must be using the word "program" when you mean "function", and
this makes your message a little confusing. Where are you declaring the
CCriticalSection? If its lifetime has ended by the time the DLL calls it,
you will have problems. That said, if the rest of your program can use it
successfully at the same time the DLL has problems, that would rule out a
lifetime issue. After verifying the CCriticalSection should still be valid
at the time the DLL uses it, and double-checking that "formatting the data"
isn't causing any buffer overflows, I'd compile the release mode version
with debug info and see if I could spot anything wrong under the debugger.
--
Doug Harrison
Visual C++ MVP
Joseph M. Newcomer [MVP]
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Joseph M. Newcomer
2007-04-07 17:43:07 UTC
Permalink
(a) show the code, including the declarations of all variables involved
(b) precisely where does the access violation happen (it doesn't happen "in the DLL", it
happens at a specific line of code somewhere!)
(c) what is the call stack when the access violation happens? Show the lines of code and
values at the point where your code invokes whatever operation is causing the access
fault.
joe
Post by Brian Westcott
I have a log program that uses a CRiticalSection to synchronize writes to
the log file. It works OK in most of my programs. When I Load a DLL (That I
wrote) , I pass the address of the log program by reference to the DLL. When
I call the log program from within the DLL, I get an access violation when
the log program calls CCriticalSection::Lock after formatting the data to be
logged. When I compile and test all programs in Debug mode, the log program
works OK.
I am declaring the logger outside of the scope of my main program so
presumably that makes it global?
Can anyone tell me what is going on?
Joseph M. Newcomer [MVP]
email: ***@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
Loading...