3

I am occasionally getting odd behavior from boost::lower, when called on a std::wstring. In particular, I have seen the following assertion fail in a release build (but not in a debug build):

Assertion failed: !is_singular(), file C:\boost_1_40_0\boost/range/iterator_range.hpp, line 281 

I have also seen what appear to be memory errors after calling boost::to_lower in contexts such as:

void test(const wchar_t* word) {
    std::wstring buf(word);
    boost::to_lower(buf);
    ...
}

Replacing the calls boost::tolower(wstr) with std::transform(wstr.begin(), wstr.end(), wstr.begin(), towlower) appears to fix the problem; but I'd like to know what's going wrong.

My best guess is that perhaps the problem has something to do with changing the case of unicode characters -- perhaps the encoding size of the downcased character is different from the encoding size of the source character?

Does anyone have any ideas what might be going on here? It might help if I knew what "is_singular()" means in the context of boost, but after doing a few google searches I wasn't able to find any documentation for it.

Relevant software versions: Boost 1.40.0; MS Visual Studio 2008.

Edward Loper
  • 15,374
  • 7
  • 43
  • 52

2 Answers2

4

After further debugging, I figured out what was going on.

The cause of my trouble was that one project in the solution was not defining NDEBUG (despite being in release mode), while all the other modules were. Boost allocates some extra fields in its data structures, which it uses to store debug information (such as whether a data structure has been initialized). If module A has debugging turned off, then it will create data structures that don't contain those fields. Then when module B, which has debugging turned on, gets its hands on that data structure, it will try to check those fields (which were not allocated), resulting in random memory errors.

Defining NDEBUG in all projects in the solution fixed the problem.

Edward Loper
  • 15,374
  • 7
  • 43
  • 52
3

An iterator range should only be singular if it's been constructed with the default constructor (stores singular iterators, i.e doesn't represent a range). As it's rather hard to believe that the boost's to_lower function manages to create a singular range, it suggests that the problem might also be elsewhere (a result of some undefined behavior, such as using uninitialized variables which might be initialized to some known value in debug builds).

Read more on Heisenbugs.

Community
  • 1
  • 1
UncleBens
  • 40,819
  • 6
  • 57
  • 90