473,327 Members | 2,012 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

Internals of an object

I sat through - what should have been a 10 minute discussion where at
issue is the 'security of a class'. Truth is I was puzzled by the
soruce, so much so that I lost track of the end result. In any event,
consider

#include <iostream>
using namespace std;

class Agent
{
private:
int iVal;
int jVal;
public:
Agent():iVal(1),jVal(2){}
void setVal(int newVal) { iVal = newVal; }
int getVali() const { return iVal; }
int getValj() const { return jVal; }
};

class MinAgent : private Agent
{
public:
int getVali() const { return Agent::getVali(); }
int getValj() const { return Agent::getValj(); }
};

int main(void)
{
MinAgent minAgent;
int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

cout << "iVal=" << minAgent.getVali() << endl; // iVal=1
cout << "jVal=" << minAgent.getValj() << endl; // jVal=2

cout << "Change values:" << endl;
*minAgentAddr = -23;
*(minAgentAddr+1) = -37;

cout << "iVal=" << minAgent.getVali() << endl; //iVal=-23
cout << "jVal=" << minAgent.getValj() << endl; //jVal=-37

return 0;
}

For starters, it appears to me that the impetus behind this

int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

is to fiddle with the internals of the object which puzzled me since
I'm unsure of a 'rational' reason to do such a thing and why is 'that'
even allowed?

Pictorially, I'm not following the deferencing of the 'object' and the
subsequent result. I understand the basic premise behind deferencing
pointers to change the contents of an address, but from an "object'
perspective these puzzle me.

*minAgentAddr = -23;
*(minAgentAddr+1) = -37;

So I tried to step through the source but Visual Studio didn't do me a
whole lot of justice so I thought:
minAgentAddr 'calls' function setVal which in turn sets iVal but that
makes no sense since minAgentAddr + 1 calls what? I'm confused.

Thanks in advance for your time.
Jul 22 '05 #1
5 1673
"ma740988" <ma******@pegasus.cc.ucf.edu> wrote in message
news:a5*************************@posting.google.co m...
I sat through - what should have been a 10 minute discussion where at
issue is the 'security of a class'. Truth is I was puzzled by the
soruce, so much so that I lost track of the end result. In any event,
consider

#include <iostream>
using namespace std;

class Agent
{
private:
int iVal;
int jVal;
public:
Agent():iVal(1),jVal(2){}
void setVal(int newVal) { iVal = newVal; }
int getVali() const { return iVal; }
int getValj() const { return jVal; }
};

class MinAgent : private Agent
{
public:
int getVali() const { return Agent::getVali(); }
int getValj() const { return Agent::getValj(); }
};

int main(void)
{
MinAgent minAgent;
int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

cout << "iVal=" << minAgent.getVali() << endl; // iVal=1
cout << "jVal=" << minAgent.getValj() << endl; // jVal=2

cout << "Change values:" << endl;
*minAgentAddr = -23;
*(minAgentAddr+1) = -37;

cout << "iVal=" << minAgent.getVali() << endl; //iVal=-23
cout << "jVal=" << minAgent.getValj() << endl; //jVal=-37

return 0;
}

For starters, it appears to me that the impetus behind this

int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

is to fiddle with the internals of the object which puzzled me since
I'm unsure of a 'rational' reason to do such a thing and why is 'that'
even allowed?

Pictorially, I'm not following the deferencing of the 'object' and the
subsequent result. I understand the basic premise behind deferencing
pointers to change the contents of an address, but from an "object'
perspective these puzzle me.

*minAgentAddr = -23;
*(minAgentAddr+1) = -37;

So I tried to step through the source but Visual Studio didn't do me a
whole lot of justice so I thought:
minAgentAddr 'calls' function setVal which in turn sets iVal but that
makes no sense since minAgentAddr + 1 calls what? I'm confused.

<snip>

No, main never calls setVal(). The reinterpret_cast is accessing and
modifying the internals of the class via low-level (and non-portable) means.
Such code is ugly, tricky, and best avoided.

Sutter wrote a good GOTW about accessing an object's private members
(http://www.gotw.ca/gotw/076.htm). The example called "the cheat" is the
one that best resembles the code you provided.

--
David Hilsee
Jul 22 '05 #2

"ma740988" <ma******@pegasus.cc.ucf.edu> skrev i en meddelelse
news:a5*************************@posting.google.co m...
I sat through - what should have been a 10 minute discussion where at
issue is the 'security of a class'.
Security in a class is not dealt with in C++ (it is not dealt with in any
other language that i know of, for that matter). The privacy of member
variables and functions is there simply to avoid shooting yourself in the
foot.

[snip]
For starters, it appears to me that the impetus behind this

int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

is to fiddle with the internals of the object which puzzled me since
I'm unsure of a 'rational' reason to do such a thing and why is 'that'
even allowed?


The purpose of reinterpret_cast is to tell the compiler that you know better
and should be used rarely if ever. One place where the is okay is where some
object somehow crosses a language barrier (e.g. call-backs in Windows).
Here, the reinterpret_cast is justified.
[snip]
/Peter
Jul 22 '05 #3
ma******@pegasus.cc.ucf.edu (ma740988) wrote:
class Agent
{
private:
int iVal;
int jVal;
public:
Agent():iVal(1),jVal(2){}
void setVal(int newVal) { iVal = newVal; }
int getVali() const { return iVal; }
int getValj() const { return jVal; }
};

class MinAgent : private Agent
{
public:
int getVali() const { return Agent::getVali(); }
int getValj() const { return Agent::getValj(); }
};

int main(void)
{
MinAgent minAgent;
int *minAgentAddr = reinterpret_cast<int*>(&minAgent);
Non-portable (minAgent may have different alignment requirements
to int), and undefined behaviour if it is de-referenced, because
the class may have padding before the first object.

But in the majority of cases, Agent's memory location will
consist of two ints. So &minAgent will be the same address
as &minAgent.iVal , and &minAgent + 1 will be the same
address as &minAgent.jVal. To rely on this behaviour would
be foolish, of course.
int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

I'm unsure of a 'rational' reason to do such a thing and why is 'that'
even allowed?
Your question applies to reinterpret_cast in general; and the answer
is that, in some cases it is useful (especially, cases where you
have established by other means that nothing undefined is going
to happen). For example in this case, if you want to change
private data in someone else's object , and you know that on
your platform, iVal will always be at the start of the object.
Pictorially, I'm not following the deferencing of the 'object' and the
subsequent result. I understand the basic premise behind deferencing
pointers to change the contents of an address, but from an "object'
perspective these puzzle me.

*minAgentAddr = -23;
*(minAgentAddr+1) = -37;


This could be rewritten (recalling that minAgentAddr is an int *):
minAgentAddr[0] = -23;
minAgentAddr[1] = -37;

Clearer?
Jul 22 '05 #4
ol*****@inspire.net.nz (Old Wolf) wrote in message news:<84*************************@posting.google.c om>...
[...]

Non-portable (minAgent may have different alignment requirements
to int), and undefined behaviour if it is de-referenced, because
the class may have padding before the first object.

But in the majority of cases, Agent's memory location will
consist of two ints. So &minAgent will be the same address
as &minAgent.iVal , and &minAgent + 1 will be the same
address as &minAgent.jVal. To rely on this behaviour would
be foolish, of course.
int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

I'm unsure of a 'rational' reason to do such a thing and why is 'that'
even allowed?


Your question applies to reinterpret_cast in general; and the answer
is that, in some cases it is useful (especially, cases where you
have established by other means that nothing undefined is going
to happen). For example in this case, if you want to change
private data in someone else's object , and you know that on
your platform, iVal will always be at the start of the object.

I suspect 'always be at the start of the object' means, when viewed
from the perspective of minAgentAddr the object has been more or less
'transformed' and as such iVal and jVal are now viewed as:

Some Value Some Address
iVal - xxx 0x......
jVal - xxx 0x......
Pictorially, I'm not following the deferencing of the 'object' and the
subsequent result. I understand the basic premise behind deferencing
pointers to change the contents of an address, but from an "object'
perspective these puzzle me.

*minAgentAddr = -23;
*(minAgentAddr+1) = -37;


This could be rewritten (recalling that minAgentAddr is an int *):
minAgentAddr[0] = -23;
minAgentAddr[1] = -37;

Clearer?

Jul 22 '05 #5
Old Wolf <ol*****@inspire.net.nz> wrote:
int *minAgentAddr = reinterpret_cast<int*>(&minAgent);

I'm unsure of a 'rational' reason to do such a thing and why is 'that'
even allowed?
Your question applies to reinterpret_cast in general; and the answer
is that, in some cases it is useful (especially, cases where you
have established by other means that nothing undefined is going
to happen). For example in this case, if you want to change
private data in someone else's object , and you know that on
your platform, iVal will always be at the start of the object.


I'd let me add something, as a long C++ practicer :)))

The reinterpret_cast operator should be used ONLY and EXCLUSIVELY to cast
between char* (const char*, if another is also const) and the other type
(in both ways). The C++ standard does not exclude other uses of
reinterpret_cast, but this is the only use of reinterpret_cast, which works.
This operator is used ONLY to get access to the internal representation and
to allocate an object in memory, obtained by some "unusual" way.

One of the correct examples of use of reinterpret_cast is the definition of
std::string in gcc. This string is implemented in such a way that first there
is allocated all memory required to hold all characters of created string,
including reserved space and internal structure:

{{ refs, size } c[0] c[1] c[2] ... c[size] c[size+1] ... c[size+reserved]}

std::string has one and the only field "dat", which is of "char*" type and
points to c[0]. To get access to the private fields (of Rep private class) the
reinterpret_cast is used:

Rep* rep = reinterpret_cast<Rep*>( dat ) - 1;

This is portable, safe and correct. The reinterpret_cast operator is used
to switch between the raw "internal representation" and a "concrete" object
type. Of course, "refs" and "size" are integers.

No casts between two "concrete" type objects are correct for reinterpret_cast!
--
1 6 1 7 4 4 2 548 g4bc7a4 66z 3xt7w v1y z9p1 120 32
(( Michal "Sektor" Malecki w4 66 64 73 7564 24 5 v 34 4
)) ektor van Skijlen 1 5 5 1 844 a v r z 4
Software engineer, Motorola GSG Poland 1 2 2a 1 4
WARNING: Opinions presented by me on usenet groups are my personal opinions
ONLY and are not connected to the employer.
Jul 22 '05 #6

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

Similar topics

7
by: ej | last post by:
I'm trying to figure out how to get at some of the internal interpreter state for exception handlers and debug statements in general. I just read through Section 8 of the Python Tutorial. I see how...
4
by: Niklaus | last post by:
Hi, I would like to know more about casts.What exactly happens when casts are applied to a variable.I know that if an object of type int is applied an cast of float the result would be of type...
3
by: Nadav | last post by:
Hi, I am writing a mixed mode application, I have a mixed mode Assembly manipulating a managed byte array, to access this array in unmanaged code I '__pin' the array, As I understand, pining an...
6
by: MattC | last post by:
I noticed when storing large amounts of information in the StateServer Service that this does not increase in size, the worker process itself seems to grow. I set up a test case to try and prove...
9
by: mailtogops | last post by:
Hi, I have this question in mind for many years.. C++ class provides encapsulation which encapsulate its members and member function. class Experiment { private:
8
by: Grizlyk | last post by:
Hello I want to understand the exception habdling in C++ more, because i think no one can apply anything free (free - without remembering large unclear list of rules and exceptions from rules...
1
by: Jobs Gooogle | last post by:
Skills: .Net VC++ Java C++ Windows Internals Unix Internals Location: Bangalore, Hyderabad, Delhi (NCR), Chennai Experience: 3+ Yrs Hand-On Please forward your profiles to mailto:...
18
by: Guru Jois | last post by:
Hai, Can I get some docs or links to learn the C compiler internals from basic to advanced. It must contains good documentation of how compilers allocates memory to variables. Bye Guru Jois
5
by: Larry Bates | last post by:
Peter Anderson wrote: Names are pointers in Python that point to values in memory. Names are "bound" to these values with assignment. Names are NOT buckets where you put values as is the case...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...

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.