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
|
|
0
|
|
|
|
Reply
|
4one (114)
|
6/12/2012 5:35:32 AM |
|
Chris Forone <4one@gmx.at> writes:
> 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)?
It's impossible to be definitive, and assuming x86 or something
similar... almost certainly. At the very least, once in the executable
image (data segment, or stack initialisation code, or equivalent) and
once in the vector. Possibly even three times (once in the data
segment, copied onto the stack, then copied into the vector).
How that data segment interacts with the memory space of the executable
is not covered in the standard.
static const float big[] = ... ;
int main ()
{
std::vector<float> v(big, big + sizeof(big) / sizeof(big[0]));
}
would give you a copy in the data segment (part of the executable image)
and a copy in heap memory (in the vector).
You've effectively taken the address of big[] and passed it to an
external function. That makes it extremely hard to optimize it away,
unless the compiler knows the semantics of the vector constructor
(unlikely).
Of course, under the "as if" rule, the compiler would be allowed
optimize it away, but its effectively impossible.
> do compilers free initialisation memory after initialization?
Free it? no. Page it out to disk? Maybe, sometimes, it depends.
|
|
0
|
|
|
|
Reply
|
gwowen (518)
|
6/12/2012 6:05:41 AM
|
|
Chris Forone wrote:
> 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.
|
|
0
|
|
|
|
Reply
|
joshuamaurice (576)
|
6/12/2012 9:35:09 AM
|
|
Gareth Owen <gwowen@gmail.com> wrote:
> 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?
|
|
0
|
|
|
|
Reply
|
nospam270 (2853)
|
6/12/2012 9:55:47 AM
|
|
Joshua Maurice <joshuamaurice@gmail.com> wrote in news:1cc7ddf7-954f-4a7f-
85a5-0181f5fd35a4@d6g2000pbt.googlegroups.com:
> 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
Just a comment: if the page is not modified, then there is no need to page
it out, it already exists on the disk as part of the executable image. OS
can just discard the page from the physical memory and reload it from the
executable image file whenever needed.
This mechanism probably gets used much more for pages containg the actual
program code, as an executable typically contains more code than
preinitialized data, and the code parts are less likely to get modified
during the run (self-modifying code is not very popular currently AFAIK).
This does not change much of course related to array initializations, it
does not matter much in which file a memory page is backed up.
Cheers
Paavo
|
|
0
|
|
|
|
Reply
|
myfirstname1 (586)
|
6/12/2012 9:01:04 PM
|
|
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
|
|
0
|
|
|
|
Reply
|
4one (114)
|
6/13/2012 1:58:42 PM
|
|
On Wed, 2012-06-13, Chris Forone wrote:
> 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
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
|
|
0
|
|
|
|
Reply
|
nntp24 (1554)
|
6/13/2012 2:21:11 PM
|
|
On Jun 13, 3:21=A0pm, Jorgen Grahn <grahn+n...@snipabacken.se> wrote:
> 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) =3D=3D fast!
ii) the cached data will be shared between invocations =3D=3D efficient!
|
|
0
|
|
|
|
Reply
|
gwowen (518)
|
6/14/2012 9:13:51 AM
|
|
|
7 Replies
30 Views
(page loaded in 0.171 seconds)
|