[ wxwindows-Bugs-1524157 ] Free memory calculation can be incorrect.

SourceForge.net noreply at sourceforge.net
Mon Jul 17 15:27:19 PDT 2006


Bugs item #1524157, was opened at 2006-07-17 16:27
Message generated for change (Tracker Item Submitted) made by Item Submitter
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=109863&aid=1524157&group_id=9863

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Common
Group: Platform specific
Status: Open
Resolution: None
Priority: 5
Submitted By: David Russak (russadw)
Assigned to: Nobody/Anonymous (nobody)
Summary: Free memory calculation can be incorrect.

Initial Comment:
It was discovered that the wxWidgets function,
wxGetFreeMemory, was erroneously
reporting less available memory than known to exist on
the system and at times 
even negative memory amounts. After examining the
following code (extracted 
from include/wx/utils.h) two problems become apparent -
explained after the
code snippets:

// wxGetFreeMemory can return huge amount of memory on
64-bit platforms
// define wxMemorySize according to the type which best
fits your platform
#if wxUSE_LONGLONG && defined(__WIN64__)
    // 64 bit Windowses have sizeof(long) only 32 bit long
    // we need to use wxLongLong to express memory sizes
    #define wxMemorySize wxLongLong
#else
    // 64 bit UNIX has sizeof(long) = 64
    // assume 32 bit platforms cannnot return more than
32bits of
    #define wxMemorySize long
#endif

Code problems:
1) The Solaris system on our Sparc architecture is 64
bits but programs
   are built by default as 32 bits. Therefore, the
definition for Solaris
   wxMemorySize is a 32 bit long. Using a long to store
the number of bytes of 
   RAM on our 16 GB machine causes an overflow condition.
2) Furthermore, using a long on a 32 bit machine may
also produce an over-
   flow condition since many 32 bit computers are
capable of containing up to 
   4 GB or more of RAM.

Additionally, the line of code from
src/unix/utilsunx.cpp that performs the 
available memory calculation on Solaris can also
exhibit a related truncation 
error that negatively affects 32 bit programs. Concider
the following line:

    return
(wxMemorySize)(sysconf(_SC_AVPHYS_PAGES)*sysconf(_SC_PAGESIZE));

The expected result is to take the return from each
sysconf, get the product
and cast to a wxMemorySize. Unfortunately, what happens
on a 32 bit application 
compiled on a 64 bit machine is truncation. The
function sysconf returns a 32 
bit signed value. Multiplied together with another 32
bit signed value the 
resultant can easily overflow.

The windows code also suffers from the same possible
truncation errors on a 32 
bit machine. The cast to wxMemorySize (which from the
definition above is 32
bits) can result in erroneous values if over 2 GBs.  

// Windows code
#if defined(__WIN64__)
    MEMORYSTATUSEX memStatex;
    statex.dwLength = sizeof (statex);
    ::GlobalMemoryStatusEx (&statex);
    return (wxMemorySize)memStatus.ullAvailPhys;
#else /* if defined(__WIN32__) */
    MEMORYSTATUS memStatus;
    memStatus.dwLength = sizeof(MEMORYSTATUS);
    ::GlobalMemoryStatus(&memStatus);
    return (wxMemorySize)memStatus.dwAvailPhys;
#endif

The better solution would be to use a 64 bit integer
for all OSes and for
Windows in particular use the code defined for
__WIN64__ as the only code 
(see Microsoft documentation for ::GlobalMemoryStatus and 
::GlobalMemoryStatusEx).



----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=109863&aid=1524157&group_id=9863




More information about the wx-dev mailing list