How Are Objects Stored in Memory in C++

How are objects stored in memory in C++?

Almost. You cast to an Object*, and neglected to take an address. Let's re-ask as the following:

((int*)&myObject)[0] == i1

You have to be really careful with assumptions like this. As you've defined the structure, this should be true in any compiler you're likely to come across. But all sorts of other properties of the object (which you may have omitted from your example) will, as others said, make it non-POD and could (possibly in a compiler-dependent way) make the above statement not true.

Note that I wouldn't be so quick to tell you it would work if you had asked about i3 -- in that case, even for plain POD, alignment or endianness could easily screw you up.

In any case, you should be avoiding this kind of thing, if possible. Even if it works fine now, if you (or anybody else who doesn't understand that you're doing this trick) ever changes the structure order or adds new fields, this trick will fail in all the places you've used it, which may be hard to find.

Answer to your edit: If that's your entire class definition, and you're using one of the mainstream compilers with default options, and running on an x86 processor, then yes, you've probably guessed the right memory layout. But choice of compiler, compiler options, and different CPU architecture could easily invalidate your assumptions.

How are objects stored in memory?

I'll start with the easiest-to-answer question:

Would it make a difference if the members of my Person class were fields rather than properties?

No. The properties in your code are just syntactic sugar. When the code is compiled, these properties with { get; set; } will be turned into fields, with a getter and a setter.

are there any major / obvious flaws in my understanding?

Yes. I will mention them when I answer the below questions.

Secondly, for value type members of a class (I.E Age), are they stored within the object itself (so within the same memory address as the object), or do they get allocated their own address, and the object then points to it? (Such as my diagram shows)

Your first statement is correct. Value types are stored within the object. There isn't a pointer in a Person object pointing to an int. In other words, your diagram is wrong.

but for reference type members, does the object hold a pointer to the pointer? (I.E The name pointer referencing the char collection in my diagram)

In this case, char[] is a reference type as you have noticed. But it's actually holding a bunch of chars, which are value types. So no, the characters are stored within the char array, just like the way Age is stored in Person. On the other hand, if this were a string[], there would be a pointer pointing to the array which would contain pointers pointing to string objects. This also means that your diagram is wrong.

Where the following objects are stored in memory?

The only true answer is, wherever the compiler feels like. That's probably not the answer you want, so let's examine what a reasonable compiler would probably choose.

  1. cPtr would probably not be stored in memory at all. It fits in a register (pointers almost always fit in CPU registers), and you never take its address, so it will probably be located in one or more registers. It might be written to stack and then read back to preserve its value across the strncpy and printf calls, or its value may be preserved in some other way. (Note that the compiler doesn't need to preserve its value after the free call, since you never use it again.)
  2. malloc will almost always return a heap pointer, since that's where allocating dynamic memory is the easiest, if not the only possible location. So the buffer will be in the heap.
  3. The compiler has a choice here. It might reference a linked malloc from some shared library, in which case it will reside in shared library code, or it might just inline all or part of the function, in which case some or all of it might reside in your program's code.
  4. This assumes a POSIX environment. In every such environment I know, this is handled by a system call, sbrk. Thus, this code will reside within the operating system's kernel code.

EDIT: since some people mentioned the static string, "Good luck on this test", I figured discussing that one would be worthwhile as well. This string appears in three contexts:

  • as a macro replacement (through #define), which is handled by the preprocessor before compiling, and thus doesn't go anywhere at all in the final output;
  • as an argument to the strncpy function, in which case it is included as read-only data, either together with the program's executable code or in a separate section made exclusively for read-only data;
  • as an argument to the sizeof operator. This is the most interesting case of the three. Technically, it should be equivalent to the previous one; however, many compilers can statically calculate the size of a constant string (it's very straightforward, after all), and thus they can replace sizeof(TEXT) with a plain 23 and avoid emitting the string altogether (for that occurrence).

Where are arrays stored in memory?

The answer to the question of where arrays, or indeed any variables, are stored depends on whether you are considering the abstract machine or the real hardware. The C standard specifies how things work on the abstract machine, but a conforming compiler is free to do something else on the real hardware (e.g., due to optimization) if the observable effects are the same.

(On the abstract machine, arrays are generally stored in the same place as other variables declared in the same scope would be.)

For example, a variable might be placed in a register instead of the stack, or it might be optimized away completely. As a programmer you generally shouldn't care about this, since you can also just consider the abstract machine. (Admittedly there may be some cases where you do care about it, and on microcontrollers with very limited RAM one reason might be that you have to be very frugal about using the stack, etc.)

As for your code for reading the memory: it cannot possibly work. If size is the size of the memory available to variables, you cannot fit the array bufferf[size] in that memory together with everything else.

Fortunately, copying the contents of the memory to a separate buffer is not needed. Consider your line bufferf[e] = *(mem_start + e) – since you can already read an arbitrary index e from memory at mem_start, you can use *(mem_start + e) (or, better, mem_start[e], which is exactly equivalent) directly everywhere you would use bufferf[e]! Just treat mem_start as pointing to the first element of an array of size bytes.

Also note that if you are programmatically searching for the contents of the array tab, its elements are ints, so they are more than one byte each – you won't simply find five adjacent bytes with those values.

(Then again, you can also just take the address of tab[0] and find out where it is stored, i.e., ((unsigned char *) tab) - mem_start is the index of tab in mem_start. However, here observing it may change things due to the aforementioned optimization.)

How is an array of objects stored in memory?

Not at all correct. An array T[N] contains N elements of type T, directly stored in contiguous memory. The array occupies N * sizeof(T) bytes of memory.

Conversely, to answer your second question, any run of N * sizeof(T) bytes of memory can be used to hold N elements of type T (subject to some alignment constraints perhaps).

Related Topics

Leave a reply