Login
Username:

Password:

Remember me



Lost Password?

Register now!

Sections

Who's Online
141 user(s) are online (122 user(s) are browsing Forums)

Members: 1
Guests: 140

LiveForIt, more...

Support us!

Headlines

 
  Register To Post  

c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Home away from home
Home away from home


See User information
@all
Lately found some issues in some port, and reduced it to some test case which simple fail on amigaos4 compiled with both clib2 and newlib. Through, one of many tests works for clib2, but not all. So, there is test case:

#include <cinttypes>
#include <cstdint>
#include <cstdio>
#include <cstring>

template<typename T>
bool test(int x, const char *fmt)
{
    
char buf_1[20] = {0};
    
snprintf(buf_1sizeof(buf_1), "%d"x);

    const 
T y x;
    
char buf_2[20] = {0};
    
snprintf(buf_2sizeof(buf_2), fmtx);

    const 
bool result = (strcmp(buf_1buf_2) == 0);
    if (
result)
        
fprintf(stderr"Ok (%s)\n"fmt);
    else
        
fprintf(stderr"Error (%s) "%s" != "%s"\n"fmtbuf_1buf_2);

    return 
result;
}

int main(int argccharargv[])
{
    
// https://en.cppreference.com/w/cpp/types/integer

    
test <uintptr_t>      (1"%" PRIuPTR);
    
test <uint_least64_t> (1"%" PRIuLEAST64);
    
test <uint_fast64_t>  (1"%" PRIuFAST64);
    
test <uint64_t>       (1"%" PRIu64);

    
test <intptr_t>       (1"%" PRIdPTR);
    
test <int_least64_t>  (1"%" PRIdLEAST64);
    
test <int_fast64_t>   (1"%" PRIdFAST64);
    
test <int64_t>        (1"%" PRId64);

    return 
0;
}


Now, compile it like this for newlib:

ppc-amigaos-g++ test-priuptr.cpp -o test-priuptr2_newlib

And like this for clib2:

ppc-amigaos-g++ -mcrt=clib2 test-priuptr.cpp -o test-priuptr2_newlib.

That what we have in output:

Newlib:

Quote:

9/0.Work:a> test-priuptr_newlib
Error (%llu) "1" != "160630978006482943"
Error (%llu) "1" != "160630978006482943"
Error (%llu) "1" != "160630978006482943"
Error (%llu) "1" != "160630978006482943"
Error (%lld) "1" != "160630978006482943"
Error (%lld) "1" != "160630978006482943"
Error (%lld) "1" != "160630978006482943"
Error (%lld) "1" != "160630978006482943"


Then, if i build the same test case with clib2, then:

Quote:

9/0.Work:a> test-priuptr_clib2
Ok (%lu)
Error (%llu) "1" != "4294967296"
Error (%llu) "1" != "4294967296"
Error (%llu) "1" != "4294967296"
Ok (%ld)
Error (%lld) "1" != "4294967296"
Error (%lld) "1" != "4294967296"
Error (%lld) "1" != "4294967296"



While if i compile for example for x86 then it:

Quote:

$ ./test-priuptr_x86.exe
Ok (%lu)
Ok (%lu)
Ok (%lu)
Ok (%lu)
Ok (%ld)
Ok (%ld)
Ok (%ld)
Ok (%ld)


Question is : WTF ?:) For clib2 only uintptr_t + PRIuPTR and uintptr_t + PRIdPTR works, while all others fail, and for newlib all fails.

Have anyone any explaining of this?


Edited by kas1e on 2020/2/6 5:59:25
Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Home away from home
Home away from home


See User information
@kas1e

Your test code has a problem where "int x" is 32-bit, but %llu/%lld needs a 64-bit value. The code might happen to work correctly on little-endian machines, provided that the next 32-bit value in memory happens to be 0. On big-endian machines like ours you're guaranteed to get a big number...

You should replace "int x" with "T x". T gets replaced with the template parameter (e.g., uintptr_t, uint64_t). Then the code should work.

%lu & %ld are for 32-bit values, which is why some clib2 tests are passing. Your results suggest that PRIuPTR is 32-bit for clib2 but 64-bit with newlib for some reason.

Hans

Join Kea Campus' Amiga Corner and support Amiga content creation
https://keasigmadelta.com/ - see more of my work
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Home away from home
Home away from home


See User information
@HAns
Quote:

You should replace "int x" with "T x". T gets replaced with the template parameter (e.g., uintptr_t, uint64_t). Then the code should work.


Nope, same error. Output start to be a bit different for newlib, but still errors of same kind

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Just can't stay away
Just can't stay away


See User information
@kas1e

As far as I understand the newlib inttypes.h header file that was included with the SDK was an internal newlib header that should only be used for building newlib itself. When I encountered and reported this problem a few years back I was told to either remove the file or make a new one with the correct values.

I added a fixed version of the inttypes.h header to be used instead, in newlib V53.49 but since the latest public SDK is much older it still has the broken header file.

If your trying to port a linux program you could try to look for a HAVE_INTTYPES_H define and disable it (what I did for dvdauthor IIRC) or you could edit the inttypes.h header to replace the macros with correct definitions.

Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Just can't stay away
Just can't stay away


See User information
@kas1e

Quote:

snprintf(buf_2, sizeof(buf_2), fmt, x);


The above line is wrong since x is always an int but the format string expects type T.

I'm not very experienced with C++ and templates but I think you should be able to fix it by casting it like so:

snprintf(buf_2, sizeof(buf_2), fmt, (T)x);

Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Home away from home
Home away from home


See User information
@salass00

Quote:
snprintf(buf_2, sizeof(buf_2), fmt, (T)x);

That's correct. My suggestion would screw up the %d snprintf() above. Your modification will ensure that the input value is the correct type.

@kas1e
Try salass00's suggestion. If it still isn't working, then check what sizeof() says it the size of each of the types you're testing. Sizeof() should report 4 for 32-bit types, and 8 for the 64-bit ones.

Hans

Join Kea Campus' Amiga Corner and support Amiga content creation
https://keasigmadelta.com/ - see more of my work
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Not too shy to talk
Not too shy to talk


See User information
@kas1e
Forget all the stuff from above (edit: well, not all, I overlooked Salass' newlib inttypes.h issue). There simply is a little typo in your code:

const T y = x;
char buf_2[20] = {0};
snprintf(buf_2, sizeof(buf_2), fmt, x);

You see, you never use y...
That's how it should be:

const T y = x;
char buf_2[20] = {0};
snprintf(buf_2, sizeof(buf_2), fmt, y);

Salass' cast (T)x would do too, of course, but the true problem here is the x/y typo. And in C++ you'd actually prefer to write static_cast<T>(x) instead of (T)x, but well.


Edited by Daytona675x on 2020/2/6 13:20:33
Edited by Daytona675x on 2020/2/6 17:03:58
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Home away from home
Home away from home


See User information
@All
Thanks all for help ! Yeah, there was a typo indeed. With that typo fixed all the clib2 tests passes fine, but newlib's ones fail on PRIuPTR and on PRIdPTR. Once i replaced inttypes.h from latest public SDK on one from latest beta of newlib as Salas00 says: all tests passes.

Phew! Thanks!

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Supreme Council
Supreme Council


See User information
And I think the moral of the story here is "Don't take code from other platforms as being bug free and great examples of talented coders".

:)

Simon

Comments made in any post are personal opinion, and are in no-way representative of any commercial entity unless specifically stated as such.
----
http://codebench.co.uk
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Amigans Defender
Amigans Defender


See User information
@Rigo

Quote:
"Don't take code from other platforms as being bug free and great examples of talented coders"


Exactly. Just a few days ago I ported a piece of Linux code that allowed writing 200 bytes into a 140-byte buffer. When I pointed that out, the author just said, "Oops..." )

The Rear Window blog

AmigaOne X5000 @ 2GHz / 4GB RAM / Radeon RX 560 / ESI Juli@ / AmigaOS 4.1 Final Edition
SAM440ep-flex @ 667MHz / 1GB RAM / Radeon 9250 / AmigaOS 4.1 Final Edition
Go to top
Re: c++11 : PRIu.... and PRId... all broken for both clib2 and newlib ?
Home away from home
Home away from home


See User information
@Rigo,Trixie

Well, it was just a fast written test case, to check if we have issues in newlib. So, once the test case was fixed it indeed points out us on newlib's issue, which was fixed in a beta of newlib.

If newlib didn't have that bug in the first place, there weren't needs for test-example, as we create it only when start to have issues related to it.

I mean it's wasn't code from the real-life app, its just test-case which was written because some bigger program give us related bugs, and so we made a test case to find out the real bug, and we find it in newlib, just lucky it was already fixed in beta by Salas00.

And moral there not only that endianes matter and programmers less and less care about, but that our official libc newlib have issues from time to time :)

Join us to improve dopus5!
AmigaOS4 on youtube
Go to top

  Register To Post

 




Currently Active Users Viewing This Thread: 2 ( 0 members and 2 Anonymous Users )




Powered by XOOPS 2.0 © 2001-2024 The XOOPS Project