Hello again,
I am getting an error when my application exits. It happens after the last object of the main function is destroyed. I guess it happens during the destruction of the static objects, but I can’t find which one because the debugger says there is no source code available for the location of the error.
These are the messages sent to the output window at the application exit:
The thread 'Win32 Thread' (0xb00) has exited with code 0 (0x0).
The thread 'DebuggerRCThread::ThreadProcStatic' (0xf7c) has exited with code 0 (0x0).
First-chance exception at 0x7c812a5b (kernel32.dll) in padol.exe: 0xC0020001: The string binding is invalid.
Unhandled exception at 0x7c812a5b (kernel32.dll) in padol.exe: 0xC0020001: The string binding is invalid.
And the call stack when the exception is thrown is:
kernel32.dll!_RaiseException@16() + 0x52 bytes
mscorwks.dll!COMPlusThrowBoot() + 0x1c bytes
mscorwks.dll!_StubRareDisableTHROWWorker@8() + 0x24 bytes
mscorwks.dll!_StubRareDisableTHROW() + 0x9 bytes 0035f883()
msvcp80d.dll!std::_DebugHeapDelete<std::locale::facet>() + 0x17 bytes
msvcp80d.dll!std::_Fac_node::~_Fac_node() + 0x18 bytes
msvcp80d.dll!std::_Fac_node::`scalar deleting destructor'() + 0xf bytes
msvcp80d.dll!std::_DebugHeapDelete<std::_Fac_node>() + 0x13 bytes
msvcp80d.dll!__Fac_tidy() + 0x35 bytes
msvcp80d.dll!_Init_atexit::~_Init_atexit() + 0x3d bytes
msvcp80d.dll!_DisableThreadLibraryCalls@4() + 0x12b8f bytes
msvcp80d.dll!__CRT_INIT@12() + 0x1f8 bytes
msvcp80d.dll!__DllMainCRTStartup@12() + 0x15e bytes
msvcp80d.dll!__DllMainCRTStartup@12() + 0x1f bytes
ntdll.dll!_LdrpCallInitRoutine@16() + 0x14 bytes
ntdll.dll!_LdrShutdownProcess@0() + 0x142 bytes
kernel32.dll!__ExitProcess@4() + 0x42 bytes
kernel32.dll!7c81cdee()
mscorwks.dll!SafeExitProcess() + 0x84 bytes
mscorwks.dll!DisableRuntime() - 0xc29ef bytes
mscorwks.dll!__CorExeMain@0() + 0xda bytes
mscoree.dll!__CorExeMain@0() + 0x34 bytes
kernel32.dll!_BaseProcessStart@4() + 0x23 bytes
Notes:
- The general project configuration properties are as follows:
- Configuration type: application (.exe)
- Use of MFC: use standard Windows libraries.
- Use of ATL: not using ATL
- CLR support: Old Syntax (/clr:oldSyntax)
- The application works good if compiled using Visual Studio 2003 (I am migrating it to Visual C++ Express 2005).
- The application uses STL and .NET libraries.
- I din't use any #pargma unmanaged.
- To remove static object is not an option.
Does anyone have the same problem Searching on the web I found similar problems and for older versions that are not applicable to my case.
A solution will be welcome too.
Thank you.

Error "The string binding is invalid" on application exit
Randy Trexler
Thank you for answering, nobug,
I did what you suggested and isolated the source of the error from the rest of the code. Here it is:
#include "Blocke.h"
#include <fstream>
#include <string>
#include <iterator>
class Token {
// inner types
public:
typedef std::basic_string<char> value_type;
// attributes
value_type value;
// constructor
explicit Token( void )
: value("INVALID") {}
Token( const Token& original )
: value(original.value) {}
};
class Tokenizer:
// bases
public std::iterator< std::input_iterator_tag, Token > {
// inner types
private:
class SymbolsIterator:
// bases
public std::iterator< std::input_iterator_tag, char > {
// attributes
private:
std::istreambuf_iterator<char> internalIterator;
// construtors
public:
SymbolsIterator(void)
: internalIterator() {}
SymbolsIterator( std::basic_istream<char>& sourceStream )
: internalIterator(sourceStream) { }
// operators
public:
inline const value_type operator*() {
return *internalIterator;
}
SymbolsIterator& operator++() {
++internalIterator;
return *this;
}
inline bool operator==( const SymbolsIterator& right ) {
return this->internalIterator == right.internalIterator;
}
inline bool operator!=( const SymbolsIterator& right ) {
return !this->operator==( right );
}
};
// attributes
protected:
SymbolsIterator nextSymbolIterator;
// constructor
public:
explicit Tokenizer( std::basic_istream<char>& sourceStream )
: nextSymbolIterator( sourceStream ) {
const std::locale locale = sourceStream.getloc();
System::Console::WriteLine(
S"locale={0}",
new System::String( locale.name().c_str() )
);
const std::num_get<char,SymbolsIterator>* numericParsingFacetPtr;
// removing the following line, the error goes away
numericParsingFacetPtr =
&std::use_facet< std::num_get<char,SymbolsIterator> >( locale );
}
};
void main(void) {
System::Console::WriteLine( S"main begin" );
std::ifstream sourceFileStream( "c:\temp\test.txt" );
Tokenizer tokenizer( sourceFileStream );
System::Console::WriteLine( S"main end" );
}
Please tell me which the error is.
MACSkeptic
Mike, I tried your second solution (using #pragma unmanaged) without success. It works in the sample code above, but not in my proyect. The reason could be that the Tokenizer is a template in the proyect, which is used in serveral places. Each of them uses several includes, and it is very annoying to modify the order of the includes in each source file.
So I tried a more punctual solution: to enclose the SymbolsIterator class definition with #pragma unmanaged and #pragma managed. This should work because it worked when I replaced it with the typedef std::istreambuf_iterator<char> SymbolsIterator
But against my will, it doesn’t. Do you know why
Perhaps, I should try your first solution: to compile using /clr:pure, with all the work it implies. But I am afraid to have problems because I use multiple inheritance a lot, and I am not sure that CLR supports it.
Harold-z80asmRules
Thank you a lot Mike, I will try your solution.
Anyway, did you notice that if the definition of the SimbolsIterator inner class is replaced by this:
typedef std::istreambuf_iterator<char> SymbolsIterator;
the error goes away
Perhaps the reason of the error is more specific.
swells
WalangAlam
Thank you again, Mike.
You convinced me now. I will convert my code to the new syntax and compile using /clr:pure
I moved it outside the Tokenizer class.
Mr. Romaryo
"to enclose the SymbolsIterator class definition with #pragma unmanaged and #pragma managed."
I'm not sure how you did this. SymbolsIterator was a nested class and #pragma managed/unmanaged only works at top level scope.
"to compile using /clr:pure, with all the work it implies. But I am afraid to have problems because I use multiple inheritance a lot, and I am not sure that CLR supports it."
That's the best solution. Trying to keep things under control with #pragma managed/unmanaged will probably result in a lot of work too and you can never be sure that you did not miss a case. Multiple inheritance is not a problem. /clr:pure does not mean that only managed types are used (ref class, value class) it only means that all the code is compiled to MSIL instead of MSIL and x86 assembly code like in the case of /clr and /clr:oldSyntax (yes, /clr has the same problem as /clr:oldSyntax, it's the mixed mode assembly that causes it, not the syntax itself). In addition to the fact that only MSIL code is generated the most important thing is that this code uses the managed version of the CRT library (msvcm80 instead of msvcp80) and this avoid the whole problem you are facing.
And be sure to read this:
http://msdn2.microsoft.com/en-us/library/ms173253(VS.80).aspx
T3Logic
Thank you again. Now, I understand a little more how all this works.
Regarding to the fact that I am using /clr:oldSyntax, is indiferent. The problem persists if the new syntax is used. ( default /clr option )
pinoyz
You got a nasty situation here. What seems to happen is this:
You may want to report this as a bug at:
http://connect.microsoft.com/VisualStudio
altough given the fact that you are using /clr:oldSyntax which is deprecated I wouldn't hold my breath for a fix...
The best solutin is to migrate to /clr:pure. Until then I found that a efficient fix is to add the following lines at the top of your cpp file:
#pragma unmanaged
#include <locale>
#pragma managed
This will cause the facet template to be insantiated as unmanaged code thus avoiding running managed code after the .NET runtime has shutdown.
Maramil
Indeed that works. The reason for this is that there is a instantiation of this case in the CRT so the compiler uses that one (which is native code) insted of creating another one (which results in managed code).
gracias
Hard to debug and diagnose. Take a good look at your code wherever you use unmanaged pointers. Disable various parts of that logic to see if that make the problem go away.
js111