Where are variables in C++ stored?

25,714

Solution 1

Named variables are stored:

  • On the stack, if they're function-local variables.
    C++ calls this "automatic storage"1 and doesn't require it to actually be the asm call stack, and in some rare implementations it isn't. But in mainstream implementations it is.
  • In a per-process data area if they are global or static.
    C++ calls this "static storage class"; it's implemented in asm by putting / reserving bytes in section .data, .bss, .rodata, or similar.

If the variable is a pointer initialized with int *p = new int[10]; or similar, the pointer variable p will go in automatic storage or static storage as above. The pointed-to object in memory is:

  • On the heap (what C++ calls dynamic storage), allocated with new or malloc, etc.
    In asm, this means calling an allocator function, which may ultimately get new memory from the OS via some kind of system call if its free-list is empty. "The heap" isn't a single contiguous region in modern OSes / C++ implementations.

C and C++ don't do automatic garbage collection, and named variables can't themselves be in dynamic storage ("the heap"). Objects in dynamic storage are anonymous, other than being pointed-to by other objects, some of which may be proper variables. (An object of struct or class type, as opposed to primitive types like int, can let you refer to named class members in this anonymous object. In a member function they even look identical.)

This is why you can't (safely/usefully) return a pointer or reference to a local variable.


This is all in RAM, of course. Caching is transparent to userspace processes, though it may visibly affect performance.

Compilers may optimize code to store variables in registers. This is highly compiler and code-dependent, but good compilers will do so aggressively.


Footnote 1: Fun fact: auto in C++03 and earlier, and still in C, meant automatic storage-class, but now (C++11) it infers types.

Solution 2

For C++ in general, the proper answer is "wherever your compiler decides to put them". You should not make assumptions otherwise, unless you somehow direct your compiler otherwise. Some variables can be stored entirely in registers, and some might be totally optimized away and replaced by a literal somewhere. With some compilers on some platforms, constants might actually end up in ROM.

The part of your question about "the processor's cache" is a bit confused. There are some tools for directing how the processor handles its cache, but in general that is the processor's business and should be invisible to you. You can think of the cache as your CPU's window into RAM. Pretty much any memory access goes through the cache.

On the other end of the equation, unused RAM sometimes will get swapped out to disk on most OSes. So its possible (but unlikely) that at some moments your variables are actually being stored on disk. :-)

Solution 3

Variables are usually stored in RAM. This is either on the Heap (e.g. global variables, static variables in methods/functions) or on the Stack (e.g. non-static variables declared within a method/function). Stack and Heap are both RAM, just different locations.

Pointers are a bit special. Pointers themselves follow the rules above but the data they point to is typically stored on the Heap (memory blocks created with malloc, objects created with new). Yet you can create pointers pointing to stack memory: int a = 10; int * b = &a;; b points to the memory of a and a is stored on the stack.

What goes into CPU cache is beyond compilers control, the CPU decides itself what to cache and how to long to cache it (depending on factors like "Has this data been recently used?" or "Is it to be expected that the data is used pretty soon again?") and of course the size of the cache has a big influence as well.

The compiler can only decide which data goes into a CPU register. Usually data is kept there if it's accessed very often in a row since register access is faster than cache and much faster than RAM. Some operations on certain systems can actually only be performed if the data is in a register, in that case the compiler must move data to a register before performing the operation and can only decide when to move the data back to RAM.

Compilers will always try to keep the most often accessed data in a register. When a method/function is called, usually all register values are written back to RAM, unless the compiler can say for sure that the called function/method will not access the memory where the data came from. Also on return of a method/function it must write all register data back to RAM, otherwise the new values would be lost. The return value itself is passed in a register on some CPU architectures, it is passed via stack otherwise.

Solution 4

Variables in C++ are stored either on the stack or the heap.

stack:

int x;

heap:

int *p = new int;

That being said, both are structures built in RAM.

If your RAM usage is high though windows can swap this out to disk.

When computation is done on variables, the memory will be copied to registers.

Solution 5

C++ is not aware of your processor's cache.

When you are running a program, written in C++ or any other language, your CPU will keep a copy of "popular" chunks of RAM in a cache. That's done at the hardware level.

Don't think of CPU cache as "other" or "more" memory...it's just a mechanism to keep some chunks of RAM close by.

Share:
25,714

Related videos on Youtube

Valentin Rocher
Author by

Valentin Rocher

Android developper in the South of France.

Updated on July 09, 2022

Comments

  • Valentin Rocher
    Valentin Rocher almost 2 years

    Where are variables in C++ stored?

    Inside the RAM or the processor's cache?

    • Todd Gamblin
      Todd Gamblin over 15 years
      This question makes no sense, since (most) caches are transparent and are really just a part of the memory system. It's also flawed because it really depends on the architecture and the compiler where C++ (or any compiled language's) variables get stored.
    • Onorio Catenacci
      Onorio Catenacci over 15 years
      @Tal, as others have said, as stated the question is kind of vague. Maybe you want to look at people's comments and see if you can ask a little more specific question.
    • Admin
      Admin over 15 years
      What can we do with questions that should be unasked? Can I tag them with "Mu"?
    • Admin
      Admin over 15 years
      OK, I've gone and done it. en.wikipedia.org/wiki/W%C3%BA
  • Dan Lenski
    Dan Lenski over 15 years
    Compilers for normal, non-embedded architectures do not place variables in "ROM."
  • Rickyx
    Rickyx over 15 years
    ROM conventionally means memory that is written only during manufacture - const variables are still stored in the computer's RAM, but just aren't written to during the program execution
  • kevinthompson
    kevinthompson over 15 years
    Actually, variables are not stored in the heap. You may have a variable that points to something in the heap, but the variable itself will be in a register, on a stack, or be statically allocated.
  • Max Lybbert
    Max Lybbert over 15 years
    Stroustrup often talks about variables stored in ROM. As does the C++ Standards committee ( open-std.org/jtc1/sc22/wg21/docs/PDTR18015.pdf pg. 75). In reality, it's not physical ROM, but instead a section of the executable for data (in ELF it's the .text section).
  • Paul de Vrieze
    Paul de Vrieze over 15 years
    In most modern systems, the stack is not fixed in size, but is automatically extended by the operating system on the occurrence of a page fault (because of an empty stack).
  • Dan Lenski
    Dan Lenski over 15 years
    Kristopher, a valid point. In the C++ definition, the variable is the pointer, not the pointed-to array, so you're right.
  • xtofl
    xtofl over 15 years
    In your answer, it becomes very clear that two different things are going on: the language's "object model" and the RAM/SwapFile/Caching system. Nice answer!
  • Todd
    Todd over 15 years
    Hi Paul. Thanks for the comment. You're right that the stack is virtual memory and can be paged. My point was that it was fixed in size when allocated at thread start. This is governed by the linker.
  • user231536
    user231536 over 14 years
    I understand that the compiler can decide to do whatever it wants. Are there compilers that currently do something very different from the usual (automatic=stack or registers, allocated=help etc) ?
  • David Thornley
    David Thornley over 14 years
    Note that storing variables in registers is highly platform-dependent also. Different architectures have different numbers of registers, and not all registers are the same in all architectures.
  • Chethan
    Chethan almost 13 years
    @Kristopher: well, your statement is not entirely true. member variables of class ojects are stored/allocated on heap.
  • Peter Cordes
    Peter Cordes about 5 years
    @user231536: for architectures like PIC and 8051 where it's hard to use the call-stack for the standard C model, yes, apparently some compilers exist that will put automatic storage-class variables in static storage. (And you have to specially declare functions to be reentrant if you want that.) Supercat commented on this in Why do C to Z80 compilers produce poor code? That Q&A in general is full of examples of C that doesn't map easily to asm. (And some asm that's just bad vs. what a modern optimizing compiler could do.)
  • Peter Cordes
    Peter Cordes about 5 years
    Stack size on Linux (for the "main" thread's stack) is restricted by a ulimit -s setting that the process inherits from its parent, not set by a linker. Also, the whole size is not technically mapped at process startup (so only a small initial size even shows up in /proc/self/maps), let alone wired in the HW page tables. But it is reserved so other mappings like mmap(MAP_ANONYMOUS) don't steal it. Touching memory below the stack pointer triggers automatic expansion of the mapping. What is "automatic stack expansion"?
  • Peter Cordes
    Peter Cordes about 5 years
    This expansion is separate from demand-paging the allocated stack memory, which happens for heap allocations and the BSS. (new heap pages, and the BSS on process startup, are typically copy-on-write mapped to a single physical page of zeros, so reads don't allocate a new physical page. But the virtual address space is fully mapped.)
  • Peter Cordes
    Peter Cordes about 3 years
    @Chethan: You mean if the whole class object itself is allocated on the heap? Yes, that's possible, but not required. In C++, you can have a myclass foo = { ... }; variable at local or global scope, so the class object itself (and thus all its members) is in automatic (stack) or static storage, not dynamic (heap). Using dynamically-allocated storage to store aggregate objects with named sub-objects isn't fundamentally different from how you can use a pointer to such memory as an array with numbered elements. You can still only get at it via some pointer or reference.
  • Peter Cordes
    Peter Cordes about 3 years
    @KristopherJohnson and Dan: I updated this answer to be more precise about dynamic storage; it's actually a pretty important point that dynamically allocated objects are always anonymous, vs. some garbage-collected languages where locals can escape and get promoted to heap objects. I tried to not crowd out the truly useful info too much, but Dan you might want to edit down some of what I said or move it around.