Initialization and Memory

C

Chris Forone

Hello,

if i write code like this:

#include <vector>

int main()
{
float big[] =
{
1.0f, 2.0f, 3.0f
};

std::vector<float> v(big, big + sizeof(big) / sizeof(big[0]));
}

are the floats twice in memory (one time from the literals, one time as
copies in the vector)? do compilers free initialisation memory after
initialization?

thanks for your short answer,
chris
 
J

Joshua Maurice

Chris said:
if i write code like this:

#include <vector>

int main()
{
float big[] =
{
1.0f, 2.0f, 3.0f
};

std::vector<float> v(big, big + sizeof(big) / sizeof(big[0]));
}

are the floats twice in memory (one time from the literals, one time as
copies in the vector)? do compilers free initialisation memory after
initialization?

I think your question shows a misunderstanding of how C++ is compiled
and run on common (read: nearly all) systems. There is not going to be
a dynamic allocation (a call to malloc(), operator new(), etc.,) to
"construct" the float array.

The float values are going to exist, in one form or another, in the
executable image, the executable file on disk. When the executable is
executed aka run, the executable file is copied wholesale into memory
(good enough for the purposes of this conversation). This is the first
instance of those float values in memory. Then, the thing is scheduled
and executed. We'll shortly get to main(), which will construct the
std::vector, very probably by calling operator new() which likely does
some bookkeeping and uses some underlying system calls to get you your
memory. Then, the float values are copied to the dynamically allocated
private internal array.

The first instance of the float values exist in the executable image
in the executable file, and AFAIK no common system is going to "free"
memory from the original executable image. Sure, it may be paged out
to disk, but any piece of memory may be paged out to disk (again good
enough for the purposes of this conversation). The float values, along
with the rest of the memory that was initially loaded as a copy of the
executable file, will not be freed. Those virtual addresses will
remain forever stuck holding those floats. No future stack object will
"reuse" that memory, and no future call to malloc(), operator new(),
etc., will "reuse" that memory and return it. Most (read: basically
all) common systems will make no attempt at analyzing which pieces of
the original executable image are no longer needed - giving up and
just leaving the original executable image unchanged and untouched.
The copy of the executable file is there for the life of the process.

Of course - a conforming implementation can do whatever it wants as
long as a conforming program couldn't tell the difference. That's the
pedants answer. I tried to give a slightly more useful answer, and I
will still emphasize that you shouldn't write broken code.

I'm also still at a loss as to what your original intended question
was. The answer I give can change greatly depending on the phrasing of
your actual question. Are you asking if you should write code
differently because of speed concerns? I need a better example then,
as the OP code does nothing.
 
J

Juha Nieminen

Gareth Owen said:
Possibly even three times (once in the data
segment, copied onto the stack, then copied into the vector).

The compiler might or might not be able to optimize copying such an array
onto the stack in this case (if it can deduce that it's basically being used
as a const array), but it's of course not guaranteed, and not even very
probable.

If the array taking stack space becomes a problem (quite unlikely, but if)
then it can be solved by declaring it "static const" (or even better,
"static constexpr" if using C++11). This will make the compiler (most
probably) elide copying the array to the stack.

An interesting question is what happens if the std::vector is constructed
with an initializer list in C++11, ie:

std::vector<float> v = { 1.0f, 2.0f, 3.0f };

How many times will those values be in memory at worst?
 
C

Chris Forone

thanks to all. i thought i can avoid a loader (because of portability)
for huge 3d data and put all into headers (as arrays).

chris
 
J

Jorgen Grahn

thanks to all. i thought i can avoid a loader (because of portability)
for huge 3d data and put all into headers (as arrays).

Why in headers rather than plain source files?

Doing it like this is not uncommon:

// foobar_image.cc
const unsigned char foobar_jpeg[] = { 47, 211, 99, ... };

//foobar_image.h
...
const unsigned char foobar_jpeg[];

// some other source file:
#include "foobar_image.h"
show_on_screen(foobar_jpeg);

All the data is in the executable, and only appears there
once. Same when the program executes (on any sensible machine).

If you make it non-const, that may cause some inefficiency.

Many people use tools to generate source files like foobar_image.cc
from the actual data. Some image formats (e.g. the original PPM
format) actually *are* C source code similar to the one above.

/Jorgen
 
G

gwowen

All the data is in the executable, and only appears there
once. Same when the program executes (on any sensible machine).

(probably) better even than that, because if you're running multiple
invocations of the same program:
i) the data will be in memory (the file cache) == fast!
ii) the cached data will be shared between invocations == efficient!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,999
Messages
2,570,243
Members
46,836
Latest member
login dogas

Latest Threads

Top