where is the error of code? (wxString::mb_str()) Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
newage
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun Dec 08, 2013 6:34 am

where is the error of code? (wxString::mb_str())

Post by newage »

This is my code:

Code: Select all

void Tree::Encoding(xx* node, const wxMBConv& src, const wxMBConv& encoding)
{
    if (!node)
        return;

    Property *prop;
    wxString str_tmp;
    const char *p;
    for (prop = node->props; prop; prop = prop->next)
    {
        //src to encoding
        str_tmp = wxString(wxString(prop->value, wxSafeConvUTF8).mb_str(src), encoding);

        //if has this, the program will death
        size_t len = wxStrlen(str_tmp.mb_str(wxSafeConvUTF8));//(for testing)

        //if has this, the program also will death. 
        /*
        free(prop->value);
        p = str_tmp.mb_str(wxSafeConvUTF8);
        prop->value = (char*)malloc(strlen(p) + 1);
        strcpy(prop->value, p);*/
    }
    
    //DFS
    Encoding(node->child, src, encoding);
    Encoding(node->next, src, encoding);
}
the program will death.
(DEBUG)
1.JPG
1.JPG (28 KiB) Viewed 2051 times
Click it.
2.JPG
2.JPG (8.22 KiB) Viewed 2051 times
Stop at row 3495(Sometimes is 3490)
4.JPG
4.JPG (71.95 KiB) Viewed 2051 times
call realloc(), but str is 0x0.

where is the error of code?
Thank you.
Last edited by newage on Sun Aug 10, 2014 6:54 pm, edited 1 time in total.
newage
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun Dec 08, 2013 6:34 am

Re: where is the error of code? (wxString::mb_str())

Post by newage »

wx3.0.1
win7 x64
gcc 4.8
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: where is the error of code? (wxString::mb_str())

Post by doublemax »

Code: Select all

str_tmp = wxString(wxString(prop->value, wxSafeConvUTF8).mb_str(src), encoding);
I'm not 100% sure what this is supposed to do, but you should probably check if the returned string is empty before continuing.

Code: Select all

p = str_tmp.mb_str(wxSafeConvUTF8);
This doesn't work. wxString::mb_str() returns a pointer to a temporary buffer which will be invalid after this line.

http://wiki.wxwidgets.org/Converting_ev ... to_char.2A

Also you should note that not every string can be converted to an 8-Bit encoding other than UTF-8. E.g. if you had a string with Chinese characters and you wanted to convert it to ISO8859-1, the returned buffer would be empty, because that's not possible.
Use the source, Luke!
newage
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun Dec 08, 2013 6:34 am

Re: where is the error of code? (wxString::mb_str())

Post by newage »

1:
#define wxSafeConvUTF8 wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL)

if repalce wxSafeConvUTF8 with wxConvUTF8, it will work.
As your said,maybe I should check if the string is empty.

2:
p = str_tmp.mb_str(xx);

I search bbs know that the code is not good(you reply to other people^_^).
But, why is it valid?

3:
free(prop->value);
prop->value = (char*)malloc(strlen(str_tmp.mb_str(xx)) + 1);
strcpy(prop->value, str_tmp.mb_str(xx));

As above, I write the str_tmp.mb_str(xx) twice.
Can I just write it once to do it?(It's impossible?)

Thanks a lot for doublemax,you reply to me many times.^_^
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: where is the error of code? (wxString::mb_str())

Post by doublemax »

p = str_tmp.mb_str(xx);

I search bbs know that the code is not good(you reply to other people^_^).
But, why is it valid?
You mean why it's invalid? If you look at the documentation for wxString::mb_str(), you see that it doesn't actually return a pointer. It returns a wxCharBuffer which can be implicitly converted to a (const char *). But this is a temporary object that will be destroyed immediately by the compiler. So if you store the pointer, the data will be invalid
As above, I write the str_tmp.mb_str(xx) twice.
Can I just write it once to do it?(It's impossible?)
The solution is in the link i posted. You can store the wxCharBuffer object, so you don't have to do the conversion twice.

Code: Select all

wxString s( wxT("some string") );
wxCharBuffer buffer = s.ToUTF8();
foo( buffer.data() );  // data() returns const char *
bar( buffer.data(), strlen(buffer.data()) );  // in case you need the length of the data
Use the source, Luke!
newage
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun Dec 08, 2013 6:34 am

Re: where is the error of code? (wxString::mb_str())

Post by newage »

as there.
http://forums.wxwidgets.org/viewtopic.p ... TypeBuffer


http://docs.wxwidgets.org/trunk/classwx ... uffer.html

Code: Select all

template<typename T>
class wxScopedCharTypeBuffer< T >
wxScopedCharTypeBuffer<T> is a template class for storing characters.

Data are stored in reference-counted buffer. In other words, making a copy of wxScopedCharTypeBuffer<T> will not make another copy of the stored string data, it will still point to the same location in memory.

wxScopedCharTypeBuffer<T> supports two storage modes: owned and non-owned. "Owned" data buffer (created with CreateOwned() or wxCharTypeBuffer<T> derived class) owns the data and frees them when the last buffer pointing to them is destroyed.

"Non-owned" buffer (created with CreateNonOwned()), on the other hand, references data owned by somebody else – typical use is by wxString::mb_str() or wxString::wc_str(), which may return non-owned buffer pointing to wxString's internal store.

Because of this, the validity of data stored in wxScopedCharTypeBuffer<T> is limited by the lifetime of the "parent" object that created the buffer (e.g. the wxString on which mb_str() was called).

If you need to preserve the data for longer, assign it to wxCharTypeBuffer<T> instead of wxScopedCharTypeBuffer<T>. On the other hand, use wxScopedCharTypeBuffer<T> if the buffer is to be destroyed before the "parent" object – typical use would be creating it on the stack and destroying when it goes out of scope (hence the class' name). 
wx/string.h 1735
const wxScopedCharBuffer wxString::utf8_str () const

Code: Select all

    const wxScopedCharBuffer utf8_str() const
        { return wxCharBuffer::CreateNonOwned(m_impl.c_str(), m_impl.length()); }
wx/buffer.h 76

Code: Select all

    // Creates "non-owned" buffer, i.e. 'str' is not owned by the buffer
    // and doesn't get freed by dtor. Used e.g. to point to wxString's internal
    // storage.
    static
    const wxScopedCharTypeBuffer CreateNonOwned(const CharType *str,
                                                size_t len = wxNO_LEN)
    {
        if ( len == wxNO_LEN )
            len = wxStrlen(str);

        wxScopedCharTypeBuffer buf;
        if ( str )
            buf.m_data = new Data(const_cast<CharType*>(str), len, Data::NonOwned);
        return buf;
    }
correct:
wxString str = "xxx";
const char *p = str.utf8_str();
...(do something about p)
//I think p is valid.
//p is point to str.But str is valid(not destory)

p = NULL;

error:
void foo(const char **p)
{
wxString str = "xxx";
*p = str.utf8_str();
...(do something about p)
//I think p is valid in here.
//Because p is point to str,the str is valid(not destory)

}
int main()
{
const char *p;
foo(&p);
...(do some about p)
//I think p is invalid in here.
//Because p is point to str,the str is invalid(already destory)

}

Do you agree with me?(I don't know if I'm right.)
User avatar
doublemax
Moderator
Moderator
Posts: 19158
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: where is the error of code? (wxString::mb_str())

Post by doublemax »

Yes, it seems my knowledge was outdated and you are right. So forget everything i wrote.
Use the source, Luke!
newage
Knows some wx things
Knows some wx things
Posts: 28
Joined: Sun Dec 08, 2013 6:34 am

Re: where is the error of code? (wxString::mb_str())

Post by newage »

Thank doublemax. ^_^
Post Reply