Error "The string binding is invalid" on application exit

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.

 



Answer this question

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

    As far as I know this is not posible.
  • WalangAlam

    Thank you again, Mike.
    You convinced me now. I will convert my code to the new syntax and compile using /clr:pure

    Mike Danes wrote:

    "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.

    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:

    • std::num_get template gets instantiated as managed code
    • CRT "registers" an instance of this facet in a list of facets that will be destroyed at exit
    • at exit, the destructor of this facet it called and here it breaks. Its destructor is managed code but this "at exit" happens when the CRT is unloaded, AFTER the .NET runtime has shutdown and the .NET runtime throws that exception.

    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

    Your program is crashing in the STL cleanup code that deletes the heap blocks that it used. Bad news, the heap structure is damaged. The problem is almost certainly not caused by the STL code but by some bad pointer write in your code. The fact that it worked in .NET 2003 doesn't mean much, you just got lucky.

    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

    Is it possible to use the managed version of the CRT library while using the /clr:old_syntax option
  • Error "The string binding is invalid" on application exit