[erlang-bugs] win32sysinfo.c doesn't understand DWORDLONG is unsigned and long

Björn-Egil Dahlberg egil@REDACTED
Thu Jan 28 18:59:14 CET 2010


Hi Matthew,

Thank you for reporting this issue.

I will have a look at this but I think you are correct.
%I64d seems to be the wrong thing here.

Regards,
Björn-Egil
Erlang/OTP


Matthew Sackman wrote:
> void get_avail_mem_ext() {
>     char answer[512];
>     MEMORYSTATUSEX ms;
>     ms.dwLength=sizeof(MEMORYSTATUSEX);
>     GlobalMemoryStatusEx(&ms);
>     sprintf(answer,"%d %I64d %I64d %I64d %I64d %I64d %I64d\n",
> 	    ms.dwMemoryLoad,
> 	    ms.ullTotalPhys,
> 	    ms.ullAvailPhys,
> 	    ms.ullTotalPageFile,
> 	    ms.ullAvailPageFile,
> 	    ms.ullTotalVirtual,
> 	    ms.ullAvailVirtual
> 	    );
>     return_answer(answer);
>     /*    
> 	DWORD     dwLength;
> 	DWORD     dwMemoryLoad;
> 	DWORDLONG ullTotalPhys;
> 	DWORDLONG ullAvailPhys;
> 	DWORDLONG ullTotalPageFile;
> 	DWORDLONG ullAvailPageFile;
> 	DWORDLONG ullTotalVirtual;
> 	DWORDLONG ullAvailVirtual;
>     */
> }
> 
> DWORD and DWORDLONG are unsigned and long. By printing with %I64d, you're
> reinterpreting them as signed ints, leading to windows users with 4GB of
> RAM being told they have negative amounts of RAM (or even 0). Eg:
> 
> $ cat foo.c
> #include <stddef.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <stdint.h>
> 
> main()
> {
>   uint64_t n = 4293308416;
>   printf("%I64d\n", n);
>   printf("%I64u\n", n);
>   printf("%I64lu\n", n);
>   return 0;
> }
> 
> $ gcc -o foo foo.c && ./foo
>                                                         -1658880
>                                                       4293308416
>                                                       4293308416
> 
> Elsewhere in win32sysinfo.c, there are %I64u format specifiers. It looks
> like the only occurrence of %I64d is in the get_avail_mem_ext function.
> 
> Because they're long, I *think* they should be %I64lu. I think what's
> happening is that the d makes it an int, thus the msb is set, hence the
> negative answer. And indeed, setting n to 4294967297 (i.e. 2^32 + 1)
> gives:
> 
>                                                                1
>                                                                1
>                                                       4294967297
> 
> Note that the above is running under a 64-bit Linux. I don't know if the
> behaviour of %I64 is the same under Windows. I also don't know what size
> an int is in a 32-bit application running on 64-bit windows. My C isn't
> all that great. My reading is that the %I64 just says to use the system
> locale, and to pad with whitespace up to 64 characters.
> 
> Matthew
> 
> ________________________________________________________________
> erlang-bugs mailing list. See http://www.erlang.org/faq.html
> erlang-bugs (at) erlang.org
> 



More information about the erlang-bugs mailing list