Solved

Unicode/STL/Varargs problem

Posted on 2001-08-06
7
1,589 Views
Last Modified: 2013-11-20
Hi.  I am very stumped by this problem.
I have a small Unicode MFC project (_UNICODE is defined).
VC 6.0 / Win2K .  Also it uses STL strings.

Building the code below works ok.
But uncommenting the line in test_msgs() causes
incorrect strings to pop up in the dialog.
And if the function is called a 2nd time, the app crashes.

Any ideas?  Thank you very much.

#include <stdarg.h>
#include <string>

typedef unsigned short unichar;

class ustring : public std::basic_string<unichar>
{
public:
     ustring() {}
     ustring(const unichar *rhs) : std::basic_string<unichar>(rhs) {}
     ustring(const ustring &rhs) : std::basic_string<unichar>(rhs) {}
};

static void popup_msg(const ustring &msg, ...) {
     wchar_t buf[2048];

     va_list args;
     va_start(args, msg);
     vswprintf(buf, msg.c_str(), args);
     va_end(args);

     AfxMessageBox(CString(buf),MB_OK);
}

void test_msgs(void) {
     wchar_t wbuf[80];

     lstrcpy(wbuf,L"WChar test: %s");
     CString cstr="test 10";

     // When I uncomment the following line, it breaks
     //ustring ustr1=L"test 11";

     ustring ustr2(wbuf);
     popup_msg(ustr2,cstr);
}
0
Comment
Question by:bwilhelm
7 Comments
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6357218
there are MS definition for UNICODE STL strings its called wstring (so you can get read of ustring)
0
 
LVL 2

Expert Comment

by:missionImpossible
ID: 6358555
first, if you use unicode you should define both the symbol _UNICODE and UNICODE ; some of the microsoft-code is not being changed to _UNICODE yet.

the line: CString cstr="test 10";
should look like this:

  CString cstr= L"test 10";  //or
  CString cstr= _T("test 10");

there are also wrapper-classes to handle wchar_t, for.ex _bstr_t, f.ex.:
_bstr_t bstrBuf( L"test 10");
there are several assign-operators you can use to transform char to wchar_t.

instead of lstrcpy() you should use _tcscpy() or wcscpy(), because lstrcpy() is not for unicode use.
0
 
LVL 1

Expert Comment

by:jizhang
ID: 6365469

The problem here in:

// When I uncomment the following line, it breaks
//ustring ustr1=L"test 11";

is ustri is a class, you need constructor to create an instence.
The parameter should be  unichar -- unsigned short int, wchar_t

You can do:

wchar_t  asc[8]= {0x74,0x65,0x73,0x74,0x20,0x31,0x31,NULL};  //alloc and init
ustring ustr1(asc);   // construct
popup_msg(ustr1,cstr);  // display

You will get right display.

The values in init are:
char       unicode       ascii
t               0x0074        0x74
e             0x0065        0x65
s             0x0073        0x73
space    0x0020        0x20
1             0x0031        0x31
NULL -- unicode string end.

Ji Zhang
0
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 

Author Comment

by:bwilhelm
ID: 6369160
Thanks for your tips.
I tried them all and still have the same problem.

Here's the latest, pared down a little lot.
Do you have any other suggestions?  Thanks a lot. - Bruce

#include <stdarg.h>
#include <string>

typedef std::basic_string<wchar_t> unistr;

#define DISPLAY_STR(str)          AfxMessageBox(CString(str),MB_OK)

// this function works
static void popup_msg1(const unistr &msg, wchar_t *wptr) {
    wchar_t buf[2048];

    swprintf(buf,msg.c_str(),wptr);

    DISPLAY_STR(buf);
}

// this function does not work
static void popup_msg2(const unistr &msg, ...) {
    wchar_t buf[2048];

    va_list args;
    va_start(args,msg);
    // the following line crashes
    vswprintf(buf,msg.c_str(),args);
    va_end(args);

    DISPLAY_STR(buf);
}

void test_msgs2(void) {
    wchar_t wbuf[80], wbuf2[80];
    wcscpy(wbuf,_T("WChar Test: %s"));
    wcscpy(wbuf2,_T("test 12"));

    unistr ustr(wbuf);
    popup_msg1(ustr,wbuf2);     // this call succeeds
    popup_msg2(ustr,wbuf2);     // this call crashes
}
0
 
LVL 9

Accepted Solution

by:
ShaunWilde earned 300 total points
ID: 6371568
ahhh - sorry I should have looked more closely - this is a known problem with using references and the va_* macros see

http://support.microsoft.com/support/kb/articles/Q119/3/94.asp

you can use their fix or you could just change your code

static void popup_msg2(const unistr *msg, ...) {
   wchar_t buf[2048];

   va_list args;
   va_start(args,msg);
   // the following line crashes
   vswprintf(buf,msg->c_str(),args);
   va_end(args);

   DISPLAY_STR(buf);
}

...

popup_msg2(&ustr,wbuf2);  
0
 

Author Comment

by:bwilhelm
ID: 6372494
Thanks, that is exactly the problem I was seeing.
0
 
LVL 9

Expert Comment

by:ShaunWilde
ID: 6372915
glad to help - I learnt something from this also
0

Featured Post

Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
format the code in java 6 101
Hibernate methods 2 77
matchUp  challenge 9 115
Use of condition with 'serial' in ansible 2 70
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …

808 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