C: unsigned long long wrong value assigned only for HP-UX

If you have any problems with the title of this question,

I recently entered the world of C.

I have some code that basically shows the capacity and free space of a disk. It works great on several different Linux distributions I have tried, as well as Solaris and AIX. I recently put together the HP-UX PA-RISC package and got (in my opinion) a really strange error.

struct statfs fsStat; err = statfs(rootPath,&fsStat); unsigned long long totalBytes = (unsigned long long)(fsStat.f_bsize * fsStat.f_blocks); 

In GDB, when I do this:

 p (fsStat.f_bsize * fsStat.f_blocks) 

Result: 1335205888 But after doing the calculation, when I do

 p totalByes 

The result is 18446744071562067968

Any information that may even give me an idea of ​​what to try here will be really wonderful. I used to think that I knew how to program, until I started making multi-platform C :(

+4
source share
2 answers

Hypothesis:

Multiplication is overflowed, so fsStat.f_bsize * fsStat.f_blocks produced an overflow result of -2147483648. When it was converted to an unsigned long long , it produced 18446744071562067968, which is 0xffffffff80000000, the result of wrapping -2147483648 in a 64-bit unsigned format. GDB uses a different arithmetic than C, so it displays a mathematically correct result.

To fix this, change (unsigned long long) (fsStat.f_bsize * fsStat.f_blocks) to (unsigned long long) fsStat.f_bsize * fsStat.f_blocks to convert to a wider integer format before multiplication.

Better than unsigned long long , use either uint64_t (from <stdint.h> ) or the type supplied by the platform (some Linux header) for working with disk sizes.

+6
source

I assume that f_bsize and f_blocks are of type int . The value is probably overflowing with a negative value.

Try executing each of these values ​​to unsigned long long before multiplying them.

+4
source

Source: https://habr.com/ru/post/1496016/


All Articles