16

What are the standard C++ features and utilities for querying the properties of the hardware or operating system capabilities, on which the program is running?
For instance, std::thread::hardware_concurrency() gives you the number of threads the machine supports.
But how do you detect how much RAM the computer has, or how much RAM the process is using, or how much disk space is available to write to in a certain directory, or how much L2 cache is available?

I would prefer answers by means of () standards, but TR2 or proposals would be good as well.

Rapptz
  • 20,807
  • 5
  • 72
  • 86
user14717
  • 4,757
  • 2
  • 44
  • 68
  • 3
    There is no such thing in the standard library. I'm not sure it would even make sense to have it because it is a platform specific thing - how do you know your hardware even *has* things like RAM, disk space, directories, or L2 cache? Hence you should either use the platform's API, or a third party library which has provided a cross platform wrapper. Requests for library recommendations are off-topic here, so you might be better off with a more specific question. – JBentley Jul 07 '14 at 18:43
  • 1
    @JBentley: Good luck running a C++ program on hardware that doesn't have RAM! – Gabe Jul 07 '14 at 22:22
  • @Gabe There could be some intrinsic registers available ;) ... – πάντα ῥεῖ Jul 07 '14 at 22:30
  • 2
    **@Close-Voters:** Again, there's no asking for external libraries or resources! I've fixed the question. @Nick-Thompson: The OP might add a comment or edit the question, to disagree my interpretation of the question, in 1st place. – πάντα ῥεῖ Jul 07 '14 at 22:54
  • 1
    @Gabe `mmap` and holographic memory? – fluffy Jul 07 '14 at 23:07
  • 9
    @Gabe: RAM just means "random access memory". There is nothing either in principle or in practice that prevents an implementation of C++ from using only sequentially-accessed memory; perhaps the C++ program in question is *running a tape drive*. – Eric Lippert Jul 07 '14 at 23:21
  • @Eric: Yes there is: Pointers. Even if the access requires sequential seeking, the semantics of C++ are random access to memory. – Ben Voigt Jul 08 '14 at 23:27
  • @EricLippert Well well. With all due respect -- if you can't write to anything you'll be hard-pressed to compute anything meaningful. If you can, it's RAM (Semantically, and that's what the OP asked.) – Peter - Reinstate Monica Jul 09 '14 at 00:02
  • 1
    I do not understand why the commentators say "platform dependent" means it can't or shouldn't be part of C++. The standard library supports all kinds of important platform information, like bits in an integer etc. The amount of RAM is as important as the number of threads which can be reasonably run in parallel, so "platform specific" is really not a good reason. The amount of RAM or disk space can also be extremely important to the strategy used to solve a given problem, so it can be crucial information which allows a program to succeeed -- or not. – Peter - Reinstate Monica Jul 09 '14 at 00:12
  • 1
    @BenVoigt: No, they are not. Accessing memory *randomly* in C is *undefined behaviour*. Memory must be accessed *sequentially* by taking an *offset* from a *known to be correct pointer* such that the computed pointer is within the *sequential* block of valid memory associated with that pointer. If you have `p` in hand and you dereference `p+10` then a compiler is entirely within its rights to access `p+1`, `p+2` and so on along the way. – Eric Lippert Jul 09 '14 at 02:42
  • 1
    @BenVoigt: Think about it this way: Suppose every time you call malloc, a robot adds a new blank tape of the correct length to a pile of tapes. When you dereference a pointer, the robot puts the appropriate tape on the tape drive and spools it forwards or backwards as needed to access the desired byte. Are you telling me that it is *impossible* to create a C compiler for this architecture? – Eric Lippert Jul 09 '14 at 02:45
  • @Eric: Yes, I am telling you it is impossible to have a conformant implementation of C++ on such an architecture. One could implement a translator from the C language to the machine code of this architecture, but one could not meet the complexity requirements of the C and C++ runtime libraries. Also, in your earlier example, the machine may calculate `p+10` via 10 increments, but it may not be permitted to access the locations `p[1]`, `p[2]`, etc if you evaluate `*(p+10)` (which I believe to be what you mean by "dereference `p+10`"). In particular, consider `volatile char* p;`. – Ben Voigt Jul 09 '14 at 06:10
  • @Eric: Please do not confuse the array requirement of being *contiguously stored* with *sequential access*. Also, note that the requirement of random-access applies even when `p` is not a pointer to `volatile`, see 1.10p4 and 1.7p3 of C++11 (I'm reading C++14 draft n3797, but I think these paragraph numbers remain the same) – Ben Voigt Jul 09 '14 at 06:12
  • You can determine endianness via stand c++. See [this question][1]. [1]: http://stackoverflow.com/questions/1001307/detecting-endianness-programmatically-in-a-c-program – Dwayne Towell Jul 13 '14 at 14:22

4 Answers4

21

how do you detect how much RAM the computer has, or how much RAM the process is using, or how much disk space is available to write to in a certain directory, or how much L2 cache is available?

You don't. Precisely none of this is the purview of the C++ language, which describes an abstract machine.

The only reason it tells you the number of cores available is because otherwise its multi-threading model would be close to useless, and even then it does so in an abstract way ("hardware concurrency" is not "number of physical CPUs in your desktop PC").

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
17

"std::thread::hardware_concurrency() gives you the number of threads the machine supports ..."

No, it doesn't. To be precise (citing from here)

std::thread::hardware_concurrency() ... Returns number of concurrent threads supported by the implementation. The value should be considered only a hint. ...
... If the value is not well defined or not computable, returns ​0​.

Best this does is letting you know, how many CPU cores are available for real parallel execution of threads (see @Lightness Races in Orbit's answer here).
You still can have as many thread instances you want, until acquiring one fails.


"how do you detect how much RAM the computer has, or how much RAM the process is using, ..."

All of these capabilities like RAM available etc. are highly machine/OS dependent, and aren't queryable with standard c++ functions or classes (at least not I know of).

"... or how much disk space is available to write to in a certain directory, ..."

C++ standard library also has no notion of such thing like a filesystem or directories ...

"... or how much L2 cache is available"

... and even less notion about such highly MCU specific traits1.

C++ uses a completely abstract, machine architecture and operating system agnostic view of it's world.

1) Thank GOD, Bjarne and the c++ standards committee for this, otherwise I'd have serious problems, to write halfway portable code for the various targets I'm facing. If it fails, and cannot be proven an error from my side violating the standards, it's most probably a bug of the actual compiler implementation. That at least hinders my co-coders squirreling out, for getting onto unnecessary and obscure micro optimization attempts :-D.


All of the above said:

The closest you can get, asking for some machine architecture basic traits and capabilities using the current standards, is what's supported from <cstddef>, <limits> and <type_traits> IMHO.

Though some common 'state of the art' technologies and abstractions were adopted by the latest standard definitions (e.g. like std::thread, std::chrono or filesystem experimental library).

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • `bad_alloc` doesn't indicate that RAM is exhausted, though – Ben Voigt Jul 08 '14 at 23:29
  • @BenVoigt As this got so much attention, I'd like to improve. Could you advise how to express this more precisely, or edit if you're willing. – πάντα ῥεῖ Jul 16 '14 at 23:56
  • `bad_alloc` occurs if virtual address space is exhausted. This can happen prior to RAM exhaustion (for example with 32-bit or x32 code running on a 64-bit OS with > 4GB of RAM in the system). And RAM exhaustion can happen without running out of virtual address space, which typically results in use of a swapfile or swap partition. If you run out of swap as well, the behavior depends on whether overcommit is enabled. – Ben Voigt Jul 17 '14 at 00:03
  • @BenVoigt OK, THX a lot for clarifying. Of course that detail distinguishes the meanings of _'address space'_ and _'RAM'_ quite well. Would _"Out of (virtual) memory"_ describe this better than _"RAM is exhausted"_ from your POV? – πάντα ῥεῖ Jul 17 '14 at 00:08
  • I wouldn't describe it as "out of virtual memory", especially in context of a question about system status. If one process exhausts its virtual address space, that means it has reached the limit (out of) virtual memory *that can be allocated to that process*, but tells nothing about whether the system has virtual memory remaining. Oh, I guess that `bad_alloc` could also indicate hitting a limit configured by `ulimit` (or similar) even though the address space would support a higher limit. Still says nothing about overall system memory. – Ben Voigt Jul 17 '14 at 01:12
  • @BenVoigt But all of this refers to OS specific behaviors. I have bound that exception to other OS, that doesn't support a process concept at all. Even bare metal applications could use the exception that _"No more dynamically allocatable memory is available"_? :-/ ... – πάντα ῥεῖ Jul 17 '14 at 01:17
  • This question is clearly not about bare metal applications. On a bare metal application you provide the C++ runtime, and you determine what the conditions for `std::bad_alloc` will be. You could not have dynamic allocation at all; throwing `std::bad_alloc` from `::operator new(size_t)` unconditionally, and then the exception would carry no information at all. – Ben Voigt Jul 17 '14 at 01:25
  • @BenVoigt OK, I wanted to have the answer covering the broadest applicable term for getting into such situation, that there's no more memory allocatable. I mentioned bare metal because you may even implement a simple dynamic memory management for such systems (and I did). The question neither was about a particular OS environment. What would you suggest would be the best way to express what I mean? Or should I remove this part of the answer at all? – πάντα ῥεῖ Jul 17 '14 at 01:31
  • I suggest removing that line, since `bad::alloc` clearly gives information about the "abstract machine" you mentioned earlier. – Ben Voigt Jul 17 '14 at 01:35
7

As others have pointed out, functions for obtaining such properties of the system are typically platform-specific. The STL and boost do not provide platform-independent wrappers, so you'll have to rely on other third party libraries.

I've successfully used SIGAR in the past:

The Sigar API provides a portable interface for gathering system information such as:

  • System memory, swap, cpu, load average, uptime, logins
  • Per-process memory, cpu, credential info, state, arguments, environment, open files
  • File system detection and metrics
  • Network interface detection, configuration info and metrics
  • TCP and UDP connection tables
  • Network route table

As a side note, Boost Filesystem does actually provide boost::filesystem::space to query "how much disk space is available to write to in a certain directory".

TC.
  • 4,133
  • 3
  • 31
  • 33
  • Sorry that I have to downvote this. I was just about writing a comment, why closing this question as being OT because asking about external references and libraries should not be applied. If you have any answer for this it should sail very close to the paths' and concepts of the next [c++1y](http://en.wikipedia.org/wiki/C%2B%2B14) standard. Your proposal looks really far from any standard concepts IIRC. – πάντα ῥεῖ Jul 07 '14 at 19:39
  • BTW there's plenty of such frameworks and libraries out there (check [Poco](http://pocoproject.org/). [Platinum C++](http://www.pt-framework.org/), etc.), but none of them nearly comes what's disscussed as _'to be future standard'_ at all. – πάντα ῥεῖ Jul 07 '14 at 19:50
6

Determining the amount of RAM or hard disk space available is operating-system level functionality. Because there are many different strategies available to tackle those issues, there's no platform independent way to get that information. The APIs for whatever OS you are developing for should provide functionality for determining those values.

For example, the windows API appears to provide this function: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366589%28v=vs.85%29.aspx which can help you to determine how much physical / virtual memory is available.

Determining the amount of cache space available is a different matter, the following answer might help you: https://stackoverflow.com/a/12838695/3798126

Community
  • 1
  • 1
bfair
  • 1,101
  • 7
  • 16