Help My Edit Boxes Return Jargon

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
DGENXP
Posts: 124
Joined: Tue Dec 27, 2005 2:49 am
Contact:

Help My Edit Boxes Return Jargon

Post by DGENXP »

Hi I come to you in desperation as i am having very big problems with my code i have tried everything that i can to fix it but to no prevail

What the problem is. I am trying to call a vector which contains directory information which is stored in a const c8* which is contained in a list box under friendly names

Image

when i click the apply button the model loads in perfectly but when i select a different list member and go back to it later the information in the text box becomes jargon,

Image


Image

the below code is the coding behind these issues

Code: Select all

    if (SelectedObject != -1)
    {
    SMModDirectory->setText(stringw(SMModDir[SelectedObject]).c_str());
    }

Code: Select all

/////////////////////////////////
// Static Meshes Vectors

vector<const c8*> SMModDir;
stringc Test;
stringw Testb;

IGUIFileOpenDialog* LoadModelDir;
Please I would realy like the answer to this preferably as code it at all possible

Cheers

DGENXP
stef_
Posts: 53
Joined: Tue Apr 18, 2006 9:39 pm
Contact:

Post by stef_ »

You can debug yourself a little more, changing:

Code: Select all

  if (SelectedObject != -1)
    {
    SMModDirectory->setText(stringw(SMModDir[SelectedObject]).c_str());
    }
with:

Code: Select all

  if (SelectedObject != -1)
    {
    printf ("[debug] SelectedObject: %d\n", SelectedObject);
    printf ("[debug] SMModDir[SelectedObject]: %s\n",
              stringw(SMModDir[SelectedObject]).c_str());
    SMModDirectory->setText(stringw(SMModDir[SelectedObject]).c_str());
    }
and then, if you can't solve it, post here the results.

Bye
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Hmmm, is it correct to use c_str() in this case ?!?!?!
setText() uses wchar_t and not c_str (c8 ) !!!
So either you should use wchar_t all the time or you'll have to cast the c8 to wchar_t ...

As I see you make a wchar_t out of the c8 and then getting the c8 out of the new wchar_t again !?!?! :shock:

Maybe you should use this:

Code: Select all

SMModDirectory->setText(stringw(SMModDir[SelectedObject]));
But I'm not really sure if this works this way... :lol:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

setText() uses wchar_t and not c_str (c8 ) !!!
The method c_str() does not always return a c8*. The return type depends on the type that you are calling it on. If you look, you'll see that string is a class template, and c_str() is defined to return a const pointer to the template type. So, if you call c_str() on a core::stringw [or equivalently core::string<wchar_t>] you would get a const wchar_t*. If you called it on a core::stringc [or core::string<irr::c8>], you would get a const c8*.

Since he is calling c_str() on a core::stringw, it will be returning a const wchar_t*, which is just what the compiler wants. The code you provided won't compile because there is no implicit conversion from core::stringw to const wchar_t*.
Please I would realy like the answer to this
I'd be willing to bet that the problem is coming up because you are passing a pointer to a temporary that is being destroyed. Some quick analysis on the code...

Code: Select all

SMModDirectory->setText(stringw(SMModDir[SelectedObject]).c_str()); 
You create a temporary stringw from a const c8*. After the temporary is created, you call c_str() to get a pointer to the underlying wchar_t*. The call to c_str() returns a pointer to the temporary objects data. At this point, the temporary string object is no longer needed. The destructor is called, and now the pointer you have is pointing to garbage.

You could fix it by making a temporary string outside of the function call...

Code: Select all

const core::stringw selection(SMModDir[SelectedObject]);
SMModDirectory->setText(selection.c_str());
Travis
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Ohh, yeah, my fault... :cry: :lol:
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
DGENXP
Posts: 124
Joined: Tue Dec 27, 2005 2:49 am
Contact:

Post by DGENXP »

Hi

I am affraid that i tried all of the mentioned methods and every single one of them returned Jargon. Is it at all possible to convert a const c8* to a stringw i will paste the entire code here
Input Events

Code: Select all

class MyEventReceiver : public IEventReceiver                   
{
    public:  
    virtual bool OnEvent(SEvent event)
    {
        if (event.EventType == EET_GUI_EVENT)
        {
            s32 id = event.GUIEvent.Caller->getID();
            IGUIEnvironment* guienv = device->getGUIEnvironment();
            
            switch(event.GUIEvent.EventType)
            {
                case EGET_FILE_SELECTED:
                {
                    if (id == 10001)
                    {
                        LoadModelDir = (IGUIFileOpenDialog*)event.GUIEvent.Caller;
                        GetModDir(core::stringc(LoadModelDir->getFilename()).c_str());    
                    }
                }
                
case EGET_BUTTON_CLICKED:
                if (id == 102)
                {
                    SMModelName();
                    return true;
                }
                if (id == 104)
                {
                    guienv->addFileOpenDialog(L"Please select Model Directory",1,0,10001);
                    return true;
                }
                if (id == 199)
                {
                    SMApply();
                    return true;
                }
                if (id == 1002)
                {
                    NowModel();
                    return true;
                }
                
case EGET_LISTBOX_SELECTED_AGAIN:
                switch(id)
                {
                    case 101:
                        SelectedObject = -1;
                        SMListBox->setSelected(-1);
                    break;
                }
                
case EGET_LISTBOX_CHANGED:
                switch(id)
                {
                    case 101:
                        SelectedObject = SMListBox->getSelected();
                        ShowInfo();
                     break;
                }
            }
        }
        return false;
    }
};
Element Calls

Code: Select all

IGUITabControl* TopTabs;

IGUIEditBox* LoadDir;
IGUIEditBox* SaveDir;

/////////////////////////////////
// Static Meshes GUI
IGUIListBox* SMListBox;
IGUIEditBox* SMModDirectory;
IGUIImage* ThumbnailImage;

IGUIEditBox* SMModName;

int SelectedObject = -1;

/////////////////////////////////
// Static Meshes Vectors

vector<const c8*> SMModDir;
stringc Test;
stringw Testb;


IGUIFileOpenDialog* LoadModelDir;
Loader

Code: Select all

void NowModel()
{
    stringc NameBuffer = SMModName->getText();
    
    if ( NameBuffer == "")
    {
        device->getGUIEnvironment()-> addMessageBox( L"MISSING INFORMATION!!",
        L"Please Ensure That All Fields Have Been Filled");
    }
    if ( NameBuffer != "")
    {
        SMListBox->addItem(SMModName->getText());
        SMModDir.push_back("");
    }
}

void SMApply()
{
    if (SelectedObject == -1)
    {
        SMModDirectory->setText(L"");
    }
    else
    {
        Test = SMModDirectory->getText();
        SMModDir[SelectedObject] = Test.c_str();
        IAnimatedMesh* mesh = smgr->getMesh(SMModDir[SelectedObject]);
        IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
    }    
}


void ShowInfo()
{
    if (SelectedObject == -1)
    {
        SMModDirectory->setText(L"");
    }
    if (SelectedObject != -1)
    {
    stringw selection(SMModDir[SelectedObject]); 
    SMModDirectory->setText(selection.c_str()); 

    }
}

void GetModDir(const c8* fn)
{
    c8 filename[1024];
    strcpy(filename, fn);
    c8* found = 0;

    if (found = strstr(filename, ".DMF")) 
    {
         stringw StaticModel = LoadModelDir->getFilename(); 
         SMModDirectory->setText(StaticModel.c_str());
    }
    if (found = strstr(filename, ".dmf")) 
    {
         stringw StaticModel = LoadModelDir->getFilename(); 
         SMModDirectory->setText(StaticModel.c_str());
    }
    if (found = strstr(filename, ".MD2")) 
    {
         stringw StaticModel = LoadModelDir->getFilename(); 
         SMModDirectory->setText(StaticModel.c_str());
    }
    if (found = strstr(filename, ".md2")) 
    {
         stringw StaticModel = LoadModelDir->getFilename(); 
         SMModDirectory->setText(StaticModel.c_str());
    }
}
Ok There is the entire code that counts could anybody please answer the Jargon question

Cheers

DGENXP
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Well, this c_str() thing should be the error (I hope I'm not wrong again)...

you call this:

Code: Select all

GetModDir(core::stringc(LoadModelDir->getFilename()).c_str());
and the function itself is declared lke this:

Code: Select all

void GetModDir(const c8* fn) 
Now in the first code you try to convert a stringw to stringc, but this doesn't work this way (AFAIK) !!!
To convert a char to wchar_t you should use mbstowcs(...)
(for wchar_t to char it's wcstombs)
for how to use them, have a look at this thread :http://irrlicht.sourceforge.net/phpBB2/ ... php?t=5888
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
vitek
Bug Slayer
Posts: 3919
Joined: Mon Jan 16, 2006 10:52 am
Location: Corvallis, OR

Post by vitek »

Acki, I have no problem converting from wide to narrow and back. Maybe it doesnt' work on other platforms, but it works fine with Win32/VC.
could anybody please answer the Jargon question
There are lots of issues with you code. The one that is most important is in your SMApply function...

Code: Select all

Test = SMModDirectory->getText(); 
SMModDir[SelectedObject] = Test.c_str(); 
You set a string from the model directory edit box. That is all fine and dandy. You then cache that pointer in the SMModDir array. The next time you click apply [or otherwise change Test], the pointer you put into SMModDir becomes invalid. I encourage you to use a core::array<core::stringc> or similar for storing your mod dir array.

Something else that I also thought was weird...

Code: Select all

void GetModDir(const c8* fn) 
{ 
    c8 filename[1024]; 
    strcpy(filename, fn); 
    c8* found = 0; 

    if (found = strstr(filename, ".DMF")) 
You copy a string just so you can search it for a substring, all the while risking a buffer overflow. In addition to that, there is the issue of the parameter type. When calling this function, you create a temporary narrow string to pass in, and then inside the function you access the original wide character string. That is silly.

Code: Select all

// kill two birds with one stone... no buffer overflow, no temporaries.
void GetModDir(const wchar_t* fn) 
{ 
  if (wcsstr(fn, L".DMF") || wcsstr(fn, L".dmf")) 
  {
    SMModDirectory->setText(fn); 
  } 
  if (wcsstr(fn, L".MD2") || wcsstr(fn, L".md2")) 
  { 
    SMModDirectory->setText(fn); 
  } 
}
Travis
Acki
Posts: 3496
Joined: Tue Jun 29, 2004 12:04 am
Location: Nobody's Place (Venlo NL)
Contact:

Post by Acki »

Ohh, yeah (again), I see !!!
He is storing the pointer to the string and not the string itself !!!
Right, c_str() returns the pointer and not the string...
You'll have to copy the string with wcscpy(...) or similar !!!


But I also suggest you to use an array of wide strings...
while(!asleep) sheep++;
IrrExtensions:Image
http://abusoft.g0dsoft.com
try Stendhal a MORPG written in Java
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Just a short note:
vitek wrote:

Code: Select all

SMModDirectory->setText(stringw(SMModDir[SelectedObject]).c_str()); 
You create a temporary stringw from a const c8*. After the temporary is created, you call c_str() to get a pointer to the underlying wchar_t*. The call to c_str() returns a pointer to the temporary objects data. At this point, the temporary string object is no longer needed. The destructor is called, and now the pointer you have is pointing to garbage.
This code should be safe, destructors are only called at the end of an expression, not in between. So there should be no problem here.

And conversion between char and wchar_t should work with direct casts for all characters below char 127 and if the there is no special encoding active. So any direct conversion (without wcstombs() etc) is likely to fail.
Post Reply