Solved

Problem with char* and convering to WCHAR

Posted on 2007-03-22
20
440 Views
Last Modified: 2013-12-04
I'm using VS .NET 2005 and for some reason the variable filename which is a char* is getting populated with Garbage and the variable wideFilename is not being being found???  filename is being passed into the function as a parameter like so:
     Sound( "./Assets/Sound.wav" );  //filename=./Assets/Sound.wav

then it is used by the code below
      WCHAR *wideFilename = new WCHAR[strlen( filename ) + 1];
      MultiByteToWideChar( CP_ACP, 0, filename, -1, wideFilename, strlen( filename ) + 1 );
      wideFilename[strlen( filename )] = 0;

I'm hoping someone might know why this isn't working correctly.  THanks,
0
Comment
Question by:ptrennum
  • 9
  • 6
  • 5
20 Comments
 
LVL 86

Expert Comment

by:jkr
ID: 18772110
Actually, ypur code seems to be OK and produces the correct results when run, e.g.

#include <windows.h>
#include <string.h>
#include <iostream>

using namespace std;

void main () {

char* filename = "./Assets/Sound.wav";

      WCHAR *wideFilename = new WCHAR[strlen( filename ) + 1];
      MultiByteToWideChar( CP_ACP, 0, filename, -1, wideFilename, strlen( filename ) + 1 );
      //wideFilename[strlen( filename )] = 0; <--- not necessary

wcout << wideFilename << endl;

delete [] wideFilename;
}

Probably you are misinterpreting what you see in the debugger.
0
 

Author Comment

by:ptrennum
ID: 18772233
what i'm doing is trying to load a sound.  Here is the whole function in case it helps.  it's the call to LoadObjectFromFile that is failing.  I get this error 'Access violation reading location 0xbaadf015.'  

m_sound = new Sound( "./Assets/Sound.wav" );

Sound( char *filename )
{
WCHAR *wideFilename = new WCHAR[strlen( filename ) + 1];
      MultiByteToWideChar( CP_ACP, 0, filename, -1, wideFilename, strlen( filename ) + 1 );
      //wideFilename[strlen( filename )] = 0;

      g_engine->GetSoundSystem()->GetLoader()->LoadObjectFromFile( CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wideFilename, (void**)&m_segment );
      
SAFE_DELETE_ARRAY( wideFilename );

      m_segment->Download( g_engine->GetSoundSystem()->GetPerformance() );
}
0
 

Author Comment

by:ptrennum
ID: 18772276
the value I'm getting for filename using the quickwatch window when I'm inside the function body is '‰' which obviosuly it isn't supposed to be.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 18772309
if Sound is a class and Sound(char* filename) is the  constructor then I don't understand yor last code:

m_sound = new Sound( "./Assets/Sound.wav" );

Sound( char *filename )
{
  ...

would not compile in a cpp. It should be

Sound::Sound( char *filename )
{
    ...

}

void Sound::anotherMemberFunction()
{
    m_sound = new Sound( "./Assets/Sound.wav" );
    ...
}

Or did you extract the Sound constructor from it's class definition?

Regads, Alex
0
 
LVL 86

Expert Comment

by:jkr
ID: 18772355
I'd try to move

SAFE_DELETE_ARRAY( wideFilename );

to the end of the function, i.e.

Sound( char *filename )
{
WCHAR *wideFilename = new WCHAR[strlen( filename ) + 1];
      MultiByteToWideChar( CP_ACP, 0, filename, -1, wideFilename, strlen( filename ) + 1 );
      //wideFilename[strlen( filename )] = 0;

      g_engine->GetSoundSystem()->GetLoader()->LoadObjectFromFile( CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wideFilename, (void**)&m_segment );
     
      m_segment->Download( g_engine->GetSoundSystem()->GetPerformance() );

  SAFE_DELETE_ARRAY( wideFilename );

}

Maybe 'Download()' sill accesses the original string parameter which is not duplicated.
0
 

Author Comment

by:ptrennum
ID: 18772360
sorry for the confusion I will post everything in hopes it will better explain.

//the creation of the sound from a seperate .cpp
m_sound = new WAGSound( "Sound.wav" );

//the sound constructor from sound.cpp
WAGSound::WAGSound( char *filename )
{
      WCHAR *wideFilename = new WCHAR[strlen( filename ) + 1];
      MultiByteToWideChar( CP_ACP, 0, filename, -1, wideFilename, strlen( filename ) + 1 );
      //wideFilename[strlen( filename )] = 0;

      // Load the sound file, then destroy the file name.
      g_engine->GetSoundSystem()->GetLoader()->LoadObjectFromFile( CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wideFilename, (void**)&m_segment );
      SAFE_DELETE_ARRAY( wideFilename );

      // Download the segment's data to the perfromance.
      m_segment->Download( g_engine->GetSoundSystem()->GetPerformance() );
}
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 18772365
>>>> the value I'm getting for filename using the quickwatch window
Try a rebuild. It looks like a build failure, e. g. cause of precompiled headers.

0
 

Author Comment

by:ptrennum
ID: 18772386
I tried a clean and rebuild, I also moved the safe delete down to bottom.  Still nothing.  When I hover over the wideFilename with my mouse in debug I get no intelli sense and if I try to quick watch it I get this:
            wideFilename      CXX0017: Error: symbol "wideFilename" not found      
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 18772426
Set a break point to the first statement of the constructor. Move the mouse to the filename argument after breaking in the debugger and check the tool-tip  If it is still garbage you should check the call stack window. I would assume the constructor was called from somewhere else, e. g. from a static construction. Do you have a default for the char argument in the class header?

class WGASound
{
  public:
   WGASound(char* filename = "anyfile");
};

If so, remove the default. It makes not much sense. Also change your argument to a const char* what is more usual.

Regads, Alex
0
 
LVL 86

Expert Comment

by:jkr
ID: 18772445
What Version of VC++ is that? For verification purposes, you could

WAGSound::WAGSound( char *filename )
{
      MessageBoxA(NULL,filename,"ANSI Filename",MB_OK);
      WCHAR *wideFilename = new WCHAR[strlen( filename ) + 1];
      MultiByteToWideChar( CP_ACP, 0, filename, -1, wideFilename, strlen( filename ) + 1 );
      //wideFilename[strlen( filename )] = 0;

      MessageBoxW(NULL,wideFilename,"UNICODE Filename",MB_OK);
      // Load the sound file, then destroy the file name.
      g_engine->GetSoundSystem()->GetLoader()->LoadObjectFromFile( CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wideFilename, (void**)&m_segment );

      // Download the segment's data to the perfromance.
      m_segment->Download( g_engine->GetSoundSystem()->GetPerformance() );
      SAFE_DELETE_ARRAY( wideFilename );

}
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 18772461
>>>> when I hover mouse in debug I get no intelli sense
Ah. I got an idea? Do you have a class member named "filename". Or a baseclass has? Then the debugger can not decide which to show and shows nothing. And indeed you must change that.
0
 

Author Comment

by:ptrennum
ID: 18772529
I don't have a class member called filename
I used the message boxes and the value appears correct! However I am still getting a fail on the call to g_engine->GetSoundSystem()->GetLoader()->LoadObjectFromFile( CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wideFilename, (void**)&m_segment );

the error the compiler returns is:Unhandled exception at 0x004026d8 in TestWAGEngine.exe: 0xC0000005: Access violation reading location 0xbaadf015.

I'm using VS.NET 2005
0
 

Author Comment

by:ptrennum
ID: 18772537
the class header looks like this
class WAGSound
{
public:
      WAGSound( char *filename );
      virtual ~WAGSound();

      void Play( bool loop = false, unsigned long flags = DMUS_SEGF_AUTOTRANSITION );

      IDirectMusicSegment8 *GetSegment();

private:
      IDirectMusicSegment8 *m_segment; // DirectMusic segment for the sound.
};
0
 
LVL 86

Expert Comment

by:jkr
ID: 18772543
Have you tried to display the names as above?
0
 

Author Comment

by:ptrennum
ID: 18772576
Yes I put in the message boxes you suggested and the names come out fine.  Just like they are supposed to.
0
 

Author Comment

by:ptrennum
ID: 18772597
even when I use the complete path to the sound file I still get the same error.  Arrrrrrrgggg
0
 
LVL 86

Accepted Solution

by:
jkr earned 300 total points
ID: 18772622
Any chance that 'g_engine' is causing the trouble? How is 'm_segment' declared? If all that ca nbe ruled out, try to break down

    g_engine->GetSoundSystem()->GetLoader()->LoadObjectFromFile( CLSID_DirectMusicSegment, IID_IDirectMusicSegment8, wideFilename, (void**)&m_segment );

to

pSoundSystem = g_engine->GetSoundSystem();
pLoader = pSoundSystem->GetLoader();
pLoader->LoadObjectFromFile(...);

and check whether all the pointers involved are valid.
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 200 total points
ID: 18772652
Delete all breakpoints and set only one to the line

      m_sound = new WAGSound( "Sound.wav" );

Check if the argument is valid so far.

Step into the constructor. If the argument is still garbage, open the Watch 1 window in the IDE and type filename. If you still get garbage only you have to use another name for the variable cause for any reason the debugger cannot show it. You also might check if you are using a valid debug database. Search with Windows explorer whether you have a new project.pdb file. check whether there are multiple versions of that file (check all disks). If so, the debugger may have used the wrong version. You must have a new .pdb file in your project debug directory (and nowhere else).

 
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 18772669
>>>> and the names come out fine.
Then it is a debugger problem only. Did you change to const char* ?

0
 

Author Comment

by:ptrennum
ID: 18772706
WOOOHOOOO - there was a problem with the pointer returned from  GetSoundSystem.  It wasn't returning the correct pointer.  Thank you both so much!!!
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now