473,493 Members | 2,274 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Memory layout of a class with only static members?

I have something like

class Params {
public:
const static char nOne = 1;
const static int nTwo = 2;
const static char nThree = 3;
};

This is just a wrapper for globally used parameters in an embedded
system.

Now, I need to do a binary copy of this data to and from some Flash.
So, what I need is the start address and the size of the data.

Unfortunatelly, sizeof(Params) gives 1.

I added dummy variables at the beginning and the end that can be used
to retreive the information.

class Params {
public:
const static char nBegin = 0;

const static char nOne = 1;
const static int nTwo = 2;
const static char nThree = 3;

// new parameters can be added before nEnd

const static char nEnd = 0;
};

I thought that the begin is &Params::nBegin and the size of all data is
&Params::nEnd - &Params::nBegin + sizeof(Params::nEnd).

It works for this little test class above. But my real class contains
much more data and a test program in VS sorts them in memory
differently. In my case nBegin and nEnd are put together. I think for
memory alignment reasons.

Then I put the class in some special section and everything seems to
work.

My questions:

Does it now work only by accident or is this guarantied?

Are there any better ways to solve the problem without changing the
general layout of the class. In my real application the parameters are
referenced already 100s of times.

Thank you for your comments.

Sep 12 '06 #1
11 4506
I don't know about the inner workings of the compiler regarding the
layout of static members, however...
Now, I need to do a binary copy of this data to and from some Flash.
You already have at least two instances of Params: in flash and, I
guess, in your program's memory. Using static, you only get one
instance of the thing, but it seems you have more.

You may try like this:

struct Params
{
int p1;
int p2;
// ...
};

static Params& FlashParams =
*reinterpret_cast<Params*>(0xYOUR_PARAMS_IN_FLASH_ ADDRESS_HERE);

void Test()
{
int copy1 = FlashParams.p1;
int copy2 = FlashParams.p2;
Params RamParams = FlashParams;
// etc...
}

Hey, typing-wise, it's even shorter than Params::p1!

Of course, you need to take care not to call Test() before the
initialization of FlashParams (highly unusual situation in my line of
work, don't know about yours).

Sep 12 '06 #2

Goran schrieb:
I don't know about the inner workings of the compiler regarding the
layout of static members, however...
Now, I need to do a binary copy of this data to and from some Flash.

You already have at least two instances of Params: in flash and, I
guess, in your program's memory. Using static, you only get one
instance of the thing, but it seems you have more.
I declared the members as static because the program must not change
them.

Actually I have only 1 instance in my program memory. These are the
default parameters. But now we need some kind of parameter update
mechanism. In Flash there is just binary data that shall be copied to
the memory location where the static parameters reside. It's not
another parameter instance but plain binary data (of course in the
right format).
You may try like this:

struct Params
{
int p1;
int p2;
// ...
};

static Params& FlashParams =
*reinterpret_cast<Params*>(0xYOUR_PARAMS_IN_FLASH_ ADDRESS_HERE);

void Test()
{
int copy1 = FlashParams.p1;
int copy2 = FlashParams.p2;
Params RamParams = FlashParams;
// etc...
}
That was my other solution but then I have to change all the code where
parameters are referenced. Before I do this I want to be sure that
there are no easier solutions. And, of course I would like to know what
the standard says about this issue.
Hey, typing-wise, it's even shorter than Params::p1!
Long time ago I decided to use the "class with static members" approach
because it saves the global object (static Params ...). It looks like
this was somehow the wrong decision... :o)

Greetings

Henryk

Sep 12 '06 #3
Henryk wrote:
I have something like

class Params {
public:
const static char nOne = 1;
const static int nTwo = 2;
const static char nThree = 3;
};

This is just a wrapper for globally used parameters in an embedded
system.

Now, I need to do a binary copy of this data to and from some Flash.
So, what I need is the start address and the size of the data.
Incorrect assumption. You assume 1 (one) start address and a contiguous
block of memory after that. There is no reason for that. In fact, for
alignment
purposes, it often is better to store the chars together, the ints
together,
etctera. The order nTwo, nOne, nThree often is the most compact.

HTH,
Michiel Salters

Sep 12 '06 #4
On 12 Sep 2006 01:45:22 -0700 in comp.lang.c++, "Henryk"
<he************@gmx.dewrote,
>class Params {
public:
const static char nOne = 1;
const static int nTwo = 2;
const static char nThree = 3;
};
>Now, I need to do a binary copy of this data to and from some Flash.
So, what I need is the start address and the size of the data.
What data? You have three constants. There is actually no
guarantee they are going to occupy memory at all, unless you take
the address of each of them somewhere. There is no guarantee they
are going to be located anywhere near each other by any kind of
reckoning. In many cases a good compiler will just substitute the
const values into the generated code where needed.

Sep 12 '06 #5

David Harmon schrieb:
On 12 Sep 2006 01:45:22 -0700 in comp.lang.c++, "Henryk"
<he************@gmx.dewrote,
class Params {
public:
const static char nOne = 1;
const static int nTwo = 2;
const static char nThree = 3;
};
Now, I need to do a binary copy of this data to and from some Flash.
So, what I need is the start address and the size of the data.

What data? You have three constants. There is actually no
guarantee they are going to occupy memory at all, unless you take
the address of each of them somewhere. There is no guarantee they
are going to be located anywhere near each other by any kind of
reckoning. In many cases a good compiler will just substitute the
const values into the generated code where needed.
Const variables are ROMable and as far as I know the compiler *should*
not replace the references by the actual values. That was one of the
the reason we used this approach. We can change the value on one memory
location. I checked the executable file before and this compiler (GCC
for PowerPC) does not optimize away my const parameters.

Back to problem, we now use a separate memory section for the parameter
data with a known address and and a known size. So I can copy this part
forth and back without considering any alignment issues inside this
section.

Henryk

Sep 12 '06 #6
Henryk wrote:
class Params {
public:
const static char nOne = 1;
const static int nTwo = 2;
const static char nThree = 3;
};

Now, I need to do a binary copy of this data to and from some Flash.
So, what I need is the start address and the size of the data.

Unfortunatelly, sizeof(Params) gives 1.
I might be dense, but if you have data that needs to be changed on a
regular base ("copy of this data ... from some Flash."), choosing const
attributes seems to be the wrong thing to do in the first place. Sure,
you could try to const_cast<away the const. But after all, what stops
the compiler from inserting known const values directly into the code,
without any object memory reference? What stops it, from not generating
an object in memory at all?

I think I can deduce why you went this direction in the first place.
You probably want to have a property API that can be queried without
initialisation and/or construction of an object like:
int v = a::property1
It seems though, that you really DO need an object, if you need write
access to it. This is a flaw in your original design.

I think rereading the first chapters of KR would be a good idea, to get
your head free for the Non-OO obfuscated basic language features to
use:

--- file a.h
struct A {
int property1;
int property2;
int property3;
};
extern A a;

--- file a.cpp
#include "a.h"
A a={5,4,3};

--- file main.cpp
#include <iostream>
#include "a.h"
int main () {
std::cout << "Property 1: " << a.property1 << "\n";
std::cout << "Property 2: " << a.property2 << "\n";
std::cout << "Property 3: " << a.property3 << "\n";
}

Can't get any more basic than that, can it ? ;-)

Sep 12 '06 #7
Henryk wrote:
Const variables are ROMable and as far as I know the compiler *should*
not replace the references by the actual values. That was one of the
the reason we used this approach. We can change the value on one memory
location. I checked the executable file before and this compiler (GCC
for PowerPC) does not optimize away my const parameters.

Back to problem, we now use a separate memory section for the parameter
data with a known address and and a known size. So I can copy this part
forth and back without considering any alignment issues inside this
section.

Henryk
Do you want your data unchangable (const) or do you want to "copy back
and forth" (non nonst)? The time for a decision is now ;-) . Anyway, if
you really want const, see the code in my posting below and change A
a={5,6,7}; to const A a={5,6,7}. You'll probably use some extra flash
routine to write to this const data and know better than I about it ;-)

Sep 12 '06 #8

F.J.K. schrieb:
Henryk wrote:
Const variables are ROMable and as far as I know the compiler *should*
not replace the references by the actual values. That was one of the
the reason we used this approach. We can change the value on one memory
location. I checked the executable file before and this compiler (GCC
for PowerPC) does not optimize away my const parameters.

Back to problem, we now use a separate memory section for the parameter
data with a known address and and a known size. So I can copy this part
forth and back without considering any alignment issues inside this
section.

Henryk

Do you want your data unchangable (const) or do you want to "copy back
and forth" (non nonst)? The time for a decision is now ;-) . Anyway, if
you really want const, see the code in my posting below and change A
a={5,6,7}; to const A a={5,6,7}. You'll probably use some extra flash
routine to write to this const data and know better than I about it ;-)
I know this is not consistent at some point: The parameters are const
for SW. The const prefix saves me from changing some parameters
accidently in my code. There is only 1 situation where the parameters
is changed:

Right after startup the flash is checked for valid parameter set and if
one was found it is loaded into the memory section where the SW
parameters reside.

My "copy back and forth" was related to some tests I did. This is not
operational.

Now, based on the new requirements, I think that your and Goran's
proposal is cleaner and the switch from the static members to a static
object is not that big deal.

Greets

Henryk

Sep 12 '06 #9

Henryk wrote:
Const variables are ROMable and as far as I know the compiler *should*
not replace the references by the actual values.
Not portable, not even with the same compiler. Since a const object
will *never* change (that is what the keyword means and the fact that
you "can" is taken care of by the standard by saying if you do then
your program is ill-formed and illicits undefined behavior) then the
compiler is free to use the "as-if" (if there is no other explicit rule
in the standard to govern this) and optimize away the actual variable.
Since the variable never changes then optimizing it away and passing
the value into places expecting it works "as-if" the variable existed.
It can't do this if the address of the variable is used for any reason
though it still can in other places (in other words you could be using
different objects depending on how this data is used). The compiler is
free to assume a const object will not change because if it does it is
free to do anything at all, including not functioning at all as
expected.

That was one of the
the reason we used this approach.
The reasoning is flawed. You'll want to stop doing it. You are
relying on implementation defined behavior and it might not be what you
are thinking.

We can change the value on one memory
location. I checked the executable file before and this compiler (GCC
for PowerPC) does not optimize away my const parameters.
const parameters or const variables? There is a big difference.
Back to problem, we now use a separate memory section for the parameter
data with a known address and and a known size. So I can copy this part
forth and back without considering any alignment issues inside this
section.
There are no alignment issues beyond the fact that these variables are
quite likely not aligned at all. They have no set memory layout except
for each individual variable's given layout (ie sizeof(float) bytes in
contiguous memory to store a float). The variables are not part of any
instance of your class and are not necissarily anywhere near each other
in memory (unlike if they WHERE part of your class). Your class
actually has no size at all, but it gets one byte because it is
necissary to be able to store variables of that type. Consider static
variables as globals only accessable by, or through, your class...this
link is by name only and for the compiler, it doesn't reflect compiled
program layout.

Sep 12 '06 #10
Henryk wrote:
Now, based on the new requirements, I think that your and Goran's
proposal is cleaner and the switch from the static members to a static
object is not that big deal.
Just out of interest. What _exactly_ do you think, the static attribute
is doing to help you? I think the only thing it does is stopping you to
see the trivial solution, id est having a global variable with the
preference data. ;-)

Sep 12 '06 #11
On 12 Sep 2006 05:28:05 -0700 in comp.lang.c++, "Henryk"
<he************@gmx.dewrote,
>Const variables are ROMable and as far as I know the compiler *should*
not replace the references by the actual values. That was one of the
the reason we used this approach. We can change the value on one memory
location. I checked the executable file before and this compiler (GCC
for PowerPC) does not optimize away my const parameters.
But you asked "Does it now work only by accident or is this
guarantied?" The answer as far as the c++ standard is concerned is,
not only is it not guaranteed, but much less is guaranteed that you
seem to be supposing. Anything about const variables being ROMable
is outside those guarantees.

If you are looking for a solution that has some basis in guarantees
made by the language, then I would be proposing something along the
lines of:

1. Abandon static members. They offer just about nothing in the way
of guarantees about layout in memory.

2. Create your variables as members (not static members) of a POD
struct. That's just about the only thing that comes close to any
guarantee about layout in memory.

3. Use a const instance of the struct for initialization. Something
of the form below should *I hope* be ROMable:
static const Params initial_params = { 1, 2, 3 };

4. Use a non-const instance for the copy in RAM. Then you are
indeed guaranteed that it has the same POD layout as the ROM and can
be copied right over.

Sep 12 '06 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
3580
by: DanielBradley | last post by:
Hello all, I have recently been porting code from Linux to cygwin and came across a problem with static const class members (discussed below). I am seeking to determine whether I am programming...
10
1825
by: Steven T. Hatton | last post by:
I just read something interesting in one of the PDFs located here: http://www.cs.wustl.edu/~schmidt/C++/ Sorry, I don't recall which file it was, and I'm too lazy to dig it up again ;) It says...
5
14405
by: kuvpatel | last post by:
Hi I want to refer a class called LogEvent, and use one of its methods called WriteMessage without actually having to create an instance of Logevent. I have tried using the word sealed with...
4
7272
by: Mike | last post by:
This question has been in the back of my head for some time, so I'll ask. If I have a method that has 200 Lines of code and I create 1000 instances of the class to which the method belongs, are...
7
4676
by: toton | last post by:
Hi, I have a STL vector of of characters and the character class has a Boost array of points. The things are vector<Characterchars; and class Character{ private: array<Point,Npoints; }; Now...
2
2450
by: Narendra | last post by:
void function1(void *); void main() { int size_offset = 0; typedef struct { int a; int b; int c; char ch;
8
2869
by: crjjrc | last post by:
Hi, I've got a base class and some derived classes that look something like this: class Base { public: int getType() { return type; } private: static const int type = 0; };
10
2021
by: sumsin | last post by:
The C++ Object Model book says that 'Nonstatic data members are allocated directly within each class object. Static data members are stored outside the individual class object. Static and...
2
6895
by: Andrus | last post by:
I need compile in-memory assembly which references to other in-memory assembly. Compiling second assembly fails with error Line: 0 - Metadata file 'eed7li9m, Version=0.0.0.0, Culture=neutral,...
0
7157
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7195
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6873
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7367
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5453
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
4889
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3088
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3078
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1400
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.