You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@stdcxx.apache.org by Anton Pevtsov <An...@moscow.vdiweb.com> on 2006/03/31 18:19:05 UTC

Problems with 0-lengths strings after an exception thrown in 11s configuration

The following code works incorrectly on Windows, compiler MSVC-7.1. But
the problem is unstable, so I am not sure that this test will fail
everywhere.

#include <rw_printf.h>  
#include <rw_char.h>    

#include <string>
#include <cstddef>
#include <stdexcept>
#include <new>

template <class charT, class Traits>
void test_insert (char* str, std::size_t str_len, bool bthrow) 
{
    typedef std::basic_string <charT, Traits, 
                               std::allocator<charT> > String;

    static charT wstr [100];
    rw_widen (wstr, str, str_len);

    String s (wstr, str_len);
    std::size_t sz = s. size ();
    if (sz != str_len)
        rw_printf ("string size is %zu for string %{#*s}, expected
%zu\n", 
                   sz, str, str_len);

    charT* out = new charT [str_len + 1];

    try {
        if (bthrow)
            s.insert (10, wstr, str_len);
        else
            s.insert (0, wstr, str_len);
    }
    catch (std::out_of_range& e) {
        _RWSTD_UNUSED(e);
        rw_printf ("out_of_range cougth\n");
    }
    catch (bad_alloc& e) {
        _RWSTD_UNUSED(e);
        rw_printf ("bad_alloc cougth\n");
    }
    catch (...) {
        rw_printf ("unknown exception cougth\n");
    }

    delete[] out;
}


void main (int argc, char* argv[])
{
    char empty[] = "";
    char test[] = "ab\0cd";

    test_insert<wchar_t, UserTraits<wchar_t> > (test, 5, true);
    test_insert<wchar_t, UserTraits<wchar_t> > (empty, 0, false);
}

I receive the following output:

out_of_range cougth
string size is 677733217 for string (null), expected 0
bad_alloc cougth

The problem seems to be in the _RW::__nullref dereferencing - its fields
contains garbage.
I found that __nullref is declared as

extern _RWSTD_EXPORT unsigned long __nullref [];
And intialized as:
_RWSTD_EXPORT unsigned long __nullref [sizeof (StringRef) / 4 + 2];

Is it correct to cast it to _RW::__null_ref<_CharT, _Traits, _Allocator>
and use fileds of this class after the cast?
Also the sample works OK if I just throw out_of_range exception instead
of the s.insert (10, wstr, str_len); call... 

Martin, could you look into this when you have a chance, please?


Thanks,
Anton Pevtsov



Re: Problems with 0-lengths strings after an exception thrown in 11s configuration

Posted by Martin Sebor <se...@roguewave.com>.
Anton Pevtsov wrote:

> The following code works incorrectly on Windows, compiler MSVC-7.1. But
> the problem is unstable, so I am not sure that this test will fail
> everywhere.

It would be good to test on other platforms. I expect to have
access to UNIX while traveling but debugging anything on Windows
might be difficult.
[...]
> out_of_range cougth
> string size is 677733217 for string (null), expected 0
> bad_alloc cougth
> 
> The problem seems to be in the _RW::__nullref dereferencing - its fields
> contains garbage.

That should never happen. The object is a POD and should be all
zeros.

> I found that __nullref is declared as
> 
> extern _RWSTD_EXPORT unsigned long __nullref [];
> And intialized as:
> _RWSTD_EXPORT unsigned long __nullref [sizeof (StringRef) / 4 + 2];
> 
> Is it correct to cast it to _RW::__null_ref<_CharT, _Traits, _Allocator>
> and use fileds of this class after the cast?

I believe so. The __null_ref object represents the empty string
whose all members are 0. This is a hack for Windows not collapsing
static data members of a class template into a single instance
across shared library boundaries. Since you're using an archive
library this shouldn't even be an issue.

> Also the sample works OK if I just throw out_of_range exception instead
> of the s.insert (10, wstr, str_len); call... 

So there seems to be a difference in behavior between throwing
from within the library and from the test itself. I would try
throwing directly from within the test but by calling the
__rw_throw() function to see if it changes things. There might
be an issue there.

> 
> Martin, could you look into this when you have a chance, please?

I'll try but I may not have much time until I get back. If this
is stopping you from making progress you might want to either
switch to Linux or put the exception tests on the back burner
and move on to the other string tests.

Martin