Opened 5 years ago

Closed 5 years ago

#15566 closed defect (fixed)

UTF-8 build assertion failure under Windows

Reported by: kosenko Owned by:
Priority: normal Milestone: 3.0.0
Component: base Version: stable-latest
Keywords: Cc: vaclavslavik
Blocked By: Blocking:
Patch: no


I have Visual C++ 2008 STL assertion failure when run minimal sample under wxMSW port with UTF-8 strings:

Microsoft Visual C++ Debug Library
Debug Assertion Failed!

Program: ...\wxWidgets\samples\minimal\vc_mswud\minimal.exe
File: C:\Program Files\Microsoft Visual Studio 9.0\VC\include\xstring
Line: 112

Expression: string iterator not dereferencable

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)
Abort   Retry   Ignore   

It is because of try to dereference "*wxString::end()". Here is a stack trace:

msvcp90d.dll!std::_Debug_message(const wchar_t * message=0x009550d8, const wchar_t * file=0x00954f18, unsigned int line=112)  Line 24   C++
minimal.exe!std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char> >::operator*()  Line 112 + 0x14 bytes  C++
minimal.exe!wxStringOperationsUtf8::DecIter<std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char> > >(std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char> > & i=0x0105d388 "")  Line 82 + 0x11 bytes    C++
minimal.exe!wxStringOperationsUtf8::AddToIter<std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char> > >(const std::_String_const_iterator<char,std::char_traits<char>,std::allocator<char> > & i=0x0105d388 "", int n=-1)  Line 108 + 0x9 bytes  C++
minimal.exe!wxString::const_iterator::operator-(int n=1)  Line 1000 + 0x59 bytes        C++
minimal.exe!wxString::reverse_iterator_impl<wxString::const_iterator>::operator*()  Line 1138 + 0x4c bytes      C++
minimal.exe!wxString::find_last_of(const wchar_t * sz=0x0105d2b8, unsigned int nStart=63, unsigned int n=2)  Line 972 + 0x13 bytes      C++
minimal.exe!wxString::find_last_of(const wchar_t * sz=0x0105d2b8, unsigned int nStart=4294967295)  Line 948     C++
minimal.exe!wxString::find_last_of(const wxScopedCharTypeBuffer<wchar_t> & sz={...}, unsigned int nStart=4294967295)  Line 3347 + 0x23 bytes    C++
minimal.exe!wxString::find_last_of(const wxString & str={...}, unsigned int nStart=4294967295)  Line 3248 + 0x68 bytes  C++
minimal.exe!wxFileName::SplitPath(const wxString & fullpathWithVolume={...}, wxString * pstrVolume=0x0012fa1c, wxString * pstrPath=0x0012f9e0, wxString * pstrName=0x0012f9a4, wxString * pstrExt=0x0012f968, bool * hasExt=0x0012f95f, wxPathFormat format=wxPATH_DOS)  Line 2452 + 0x3e bytes C++
minimal.exe!wxFileName::Assign(const wxString & fullpath={...}, wxPathFormat format=wxPATH_NATIVE)  Line 534 + 0x2d bytes       C++
minimal.exe!wxFileName::wxFileName(const wxString & fullpath={...}, wxPathFormat format=wxPATH_NATIVE)  Line 138 + 0x79 bytes   C++
minimal.exe!wxStandardPaths::GetAppDir()  Line 257 + 0x47 bytes C++
minimal.exe!wxStandardPaths::IgnoreAppSubDir(const wxString & subdirPattern={...})  Line 274 + 0x11 bytes       C++
minimal.exe!wxStandardPaths::IgnoreAppBuildSubDirs()  Line 295 + 0x26 bytes     C++
minimal.exe!wxStandardPaths::wxStandardPaths()  Line 337        C++
minimal.exe!`anonymous namespace'::wxStandardPathsDefault::wxStandardPathsDefault()  Line 47 + 0x16 bytes       C++
minimal.exe!`anonymous namespace'::`dynamic initializer for 'gs_stdPaths''()  Line 50 + 0xd bytes       C++
msvcr90d.dll!_initterm(void (void)* * pfbegin=0x0094eba0, void (void)* * pfend=0x0094f248)  Line 903    C
minimal.exe!__tmainCRTStartup()  Line 497 + 0xf bytes   C
minimal.exe!WinMainCRTStartup()  Line 399       C
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]      
minimal.exe!wxPrinterDCImpl::GetPaperRect()  Line 237 + 0x14 bytes      C++

This could be suppressed by the patch:

  • include/wx/stringops.h

    diff --git a/include/wx/stringops.h b/include/wx/stringops.h
    index 301a7bf..e58d6ba 100644
    a b struct WXDLLIMPEXP_BASE wxStringOperationsUtf8 
    7979    template<typename Iterator>
    8080    static void DecIter(Iterator& i)
    8181    {
    82         wxASSERT( IsValidUtf8LeadByte(*i) );
     82        //wxASSERT( IsValidUtf8LeadByte(*i) );
    8484        // Non-lead bytes are all in the 0x80..0xBF range (i.e. 10xxxxxx in
    8585        // binary), so we just have to go back until we hit a byte that is

Change History (3)

comment:1 Changed 5 years ago by vadz

  • Cc vaclavslavik added
  • Milestone set to 3.0
  • Status changed from new to confirmed

Vaclav, could you please have a look at this one? It seems that the assert is really wrong because AFAICS DecIter() can be called for the end iterator, as it is legal to decrement it -- but not to dereference. And I don't see how can we test whether i == end at this level so I don't know how to fix it otherwise than by removing the asserts :-(

BTW, I don't think this is Windows specific, I think an error would also be generated under Linux when using UTF-8 mode with _GLIBCXX_DEBUG defined.

comment:2 Changed 5 years ago by vaclavslavik

Vaclav, could you please have a look at this one?

There’s nothing to “look at”, the assert is wrong and as you say, there’s no straightforward way to keep it (we can test if it’s end() in wxString, where DecIter() and AddToIter() are called, but I’d rather loose the assert than add tons of clumsy if statements to wxString).

comment:3 Changed 5 years ago by VS

  • Resolution set to fixed
  • Status changed from confirmed to closed

(In [74976]) Remove assert from wxStringOperationsUtf8::DecIter().

The assert prevented decrementing end() iterator, which is a valid

Fixes #15566.

Note: See TracTickets for help on using tickets.