wxString::Format uint64_t problem 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.
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

wxString::Format uint64_t problem

Post by aval57 »

To the wxperts out there,

uint64_t seems to throw wxString::Format out of whack, e.g.

Code: Select all

#include <cstdlib>
#include <iostream>
#include <wx/string.h>

using namespace std;

template<class T> 
void echo( T i, const char *s )
{
   cout << wxString::Format( "%Lu %s ", i, s ) << "\n";
}

int main(int argc, char *argv[])
{
   echo( (uint32_t)2, "hello world" );
   echo( (uint64_t)2, "hello world");
   system("pause");
}

// output:
//    2 hello world
//    2 (null) Press any key to continue . . .
Why is this?

Thanks,
Bahman
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

Hi aval57,

a shot in the dark: Could it be that you provide the wrong modifier? "L" denotes a long double afaik.

HTH, Chris

Edit: On a second thought: %lu should work.
this->signature=NULL;
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

Post by aval57 »

Hi Chris,

Makes no difference, template or not. I've tried all the modifiers in simple template-free cout statements, and the 64bit type always causes the subsequent string to go '(null)'. If it's a problem with the modifier, then a typecast in the template should fix things:

Code: Select all

template<class T> 
void echo( T i, const char *s )
{
   cout << wxString::Format( "%Lu %s ", (uint64_t)i, s ) << "\n";
}
but this only results in
2 (null)
2 (null)
Press any key to continue . . .
I think it's a quirk in the implementation of wxString::Format.

Bahman

EDIT: %lu chokes too. According to Borland BCB5.HLP L "doubles" as:
L (e E f g G ) : A long double
L (d i o u x X ) : An __int64
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

Hi aval57,

I just tried it myself (wxGTK 2.6.2 ANSI), gcc 4.0.3 20051201.
Funnily enough, it's the other way around here: the second call works, the first doesn't.
I implemented this with overloaded methods and it works:

Code: Select all

#include <cstdlib>
#include <iostream>
#include <wx/string.h>

using namespace std;

void echo2(uint32_t i,const char *s ){
   cout << wxString::Format( "%u %s ", i, s ) << "\n";
}

void echo2(uint64_t i,const char *s ){
   cout << wxString::Format( "%Lu %s ", i, s ) << "\n";
}

template<class T>
void echo( T i, const char *s )
{
   cout << wxString::Format( "%Lu %s ", i, s ) << "\n"; // line 18
}

int main(int argc, char *argv[])
{
   echo( (uint32_t)2, "hello world" ); // line 23
   echo( (uint64_t)2, "hello world");
   cout << "overloaded: " << endl;
   echo2( (uint32_t)2, "hello world" );
   echo2( (uint64_t)2, "hello world");
}
Output:
579523549316775938
2 hello world
overloaded:
2 hello world
2 hello world
Please note the compiler complains with -Wall:
test.cpp: In function 'void echo(T, const char*) [with T = unsigned int]':
test.cpp:23: instantiated from here
test.cpp:18: warning: format '%Lu' expects type 'long long unsigned int', but argument 2 has type 'unsigned int'
A few things:
1: %L is actually correct as it seems (for long longs)
2: I'm surprised that the call with the uint32_t doesn't work. uint32_t is type compatible with uint64_t, so it should work.
3: A plain printf shows the same faulty output as wxString::Format() does, so I doubt it's a bug in wx (wx uses the clibs printf, iirc).

However, going with overloads should help.

Chris
this->signature=NULL;
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

I should also mention that the output from echo( (uint32_t)2, "hello world" ); varies from call to call, so I guess it's a bad pointer problem here.

Edit: Did you try to do a plain printf("%Lu") on the uint64_t?
this->signature=NULL;
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

Post by aval57 »

Whoops, got temporarily banned due to an administrative snafu... I'm back.

Your're onto something, Chris. Printf fails on uint64_t as well, (though cout works ok); and running your code at this end (wxWidgets 2.6.0, DEV-C++ mingw32-gcc-3.4.2) gives
2 hello world
2 (null)
overloaded:
2 hello world
2 (null)
Press any key to continue . . .
I guess the easy fix is to bail out of wxString/printf and use cout instead. Any idea what's causing this, though?

Thanks,
Bahman
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

Ok, this is obviously an issue in the C runtime library used by MinGW. If I'm not mistaken, MinGW uses the Visual C++ 6 crt (msvcrt.dll). cout doesn't use the C routines, which may explain why it works there. I guess this isn't a bug, btw. You just need to find out which format types are supported in the MinGW runtime. Unfortunately, they don't seem to be as standartized as they should be :(. I did some googling, but no result.
"man 3 printf" tells me to use "%llu" for unsigned long long int, btw. You could try that too, but don't hold your breath...
this->signature=NULL;
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

Google good:

From here:
g) Significantly incompatible with Linux C.

For example, printf and scanf of standard C 64-bit %llX and %lld don't yet work, instead you have to write Microsoft C: %I64X and %I64d. Possibly this incompatibility is a natural consequence of building .exe that work without installing a Cygwin .dll: the C programming language resists in many ways if you try to add your own % escapes to printf and scanf.
Edit: Hey, they have a wiki over there at MinGW:
http://www.mingw.org/MinGWiki/index.php/long%20long

That should do the trick!
this->signature=NULL;
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

Post by aval57 »

Awesome, Chris, this is the full answer, no doubt.

(The joke is I ran across -I64 yesterday, misread it as -EllSixtyFour and therefore got no result :)

Unhappily although

Code: Select all

printf( "%I64u %s", (uint64_t)2, "hello world\n" );
works fine,

Code: Select all

cout << wxString::Format( "%I64u %s", (uint64_t)2, "hello world\n" );
crashes the program, so it looks like it's time to call it a day.

Thanks,
Bahman
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

aval57 wrote: (The joke is I ran across -I64 yesterday, misread it as -OneSixtyFour and therefore got no result :)
Ah, the good old "Il1"-problem :wink:

Code: Select all

cout << wxString::Format( "%I64u %s", (uint64_t)2, "hello world\n" );
crashes the program, so it looks like it's time to call it a day.

Damn, I thought we'd solved it. Well, perhaps I'll have a look at the source for wxString::Format() tomorrow, maybe there's something useful in there.
If you really need to do this via Format(), you could also try to get a full backtrace on a debug build of wx...
this->signature=NULL;
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

Post by aval57 »

No, Format() was just my preferred method, if only because the code is more visually concise (to my eye, anyway). Going by that standard, though, plain old cout, working as it does without any addl typecasts/modifiers/overloads, looks better and better...

Thanks again
Bahman
User avatar
ABX
Can't get richer than this
Can't get richer than this
Posts: 810
Joined: Mon Sep 06, 2004 1:43 pm
Location: Poznan, Poland
Contact:

Re: wxString::Format uint64_t problem

Post by ABX »

aval57 wrote:uint64_t seems to throw wxString::Format out of whack
Different compilers accepts different format for 64 integers so wxWidgets provides own replacement wxLongLongFmtSpec, see http://www.wxwidgets.org/manuals/2.6.2/ ... ongfmtspec for details.

ABX
CVS Head, 2.8.X
wxMSW, wxWinCE, wxPalmOS, wxOS2, wxMGL, bakefile
gcc 3.2.3, bcc 5.51, dmc 8.48, ow 1.6, vc 7.1, evc 3/4, pods 1.2
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

Post by aval57 »

Thanks ABX

Code: Select all

cout << wxString::Format( "%" wxLongLongFmtSpec "u %s", wxULL((uint64_t)2), "hello world\n" );
still outputs
2 (null)
The problem isn't that I can't display the 64 bit integer, but that the string that follows it becomes '(null)'.

Bahman
chris
I live to help wx-kind
I live to help wx-kind
Posts: 150
Joined: Fri Oct 08, 2004 2:05 pm
Location: Europe

Post by chris »

Hi,

Code: Select all

cout << wxString::Format( "%" wxLongLongFmtSpec "u %s", wxULL(2), "hello world\n" );
crashed for me in wxVsnprintf_ when using the wxMSW 2.6.2 devpak from wxDev-Cpp 6.9beta (MinGW 3.4.2).

To get a useful backtrace I compiled wxMSW 2.6.2 myself, with "configure --disable-shared --enable-debug". No crash, correct output.
So, what does this tell us? And why is wxVsnprintf_ even called? I thought that one would only be used if there was no suitable vsnprintf on the host, but the Visual C++ 6.0 crt has one (at least it says so at MSDN).

Bahman, where does your wx come from? Did you compile it yourself or install a devpak or something?

Edit: Corrected URL.
this->signature=NULL;
aval57
Knows some wx things
Knows some wx things
Posts: 35
Joined: Thu Aug 25, 2005 5:38 am

Post by aval57 »

Good morning Chris! Your efforts are way above and beyond the call of duty, but then sometimes one 'catches a bug'.
I have upCase's 2.6.0 devpak and Andre Simon's 2.6.2 devpak. Compiling and running

Code: Select all

    printf( "%" wxLongLongFmtSpec "u %s", wxULL((uint64_t)2), "hello world\n" );
    cout << wxString::Format( "%" wxLongLongFmtSpec "u %s", wxULL((uint64_t)2), "hello world\n" );
with either devpak gave
2 (null)2 (null)
Bahman

PS perhaps you'd like to share your build as a devpak. (how-to)

UPDATE: Also tried NinjaNL's 2.7 devpak - same result on printf, crash on Format().
Post Reply