 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
kaufmann@cs.uni-potsdam.d Guest
|
Posted: Tue Jul 05, 2005 5:53 pm Post subject: Question regarding initialization of non-local POD-Object |
|
|
Hello,
I have a non-local constant fooName defined like this:
const char* const fooName = "foo";
fooName is used in a function f that is called in the course of the
dynamic-initialization of a non-local object (f and the non-local
object live in different TUs)
My question: Is it guaranteed that on entering f fooName is already
initialized and therefore different to 0?
As far as I understand the C++ Standard it is because fooName is a
non-local object of POD-type which is initialized using a constant
expression and 3.6.2/1 states:
"[...]Objects of POD Types with static storage duration initialized
with constant expressions shall be initialized before any dynamic
initialization takes place"
I'm asking because at least on one compiler I tried fooName is
sometimes a null pointer when f is entered.
Is this a bug in the compiler? Or am I misinterpreting the C++
Standard?
Regards,
- Ben
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Jul 06, 2005 10:41 am Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]kaufmann (AT) cs (DOT) uni-potsdam.de[/email] wrote:
| Quote: | I have a non-local constant fooName defined like this:
const char* const fooName = "foo";
fooName is used in a function f that is called in the course
of the dynamic-initialization of a non-local object (f and the
non-local object live in different TUs)
My question: Is it guaranteed that on entering f fooName is
already initialized and therefore different to 0?
|
Yes.
| Quote: | As far as I understand the C++ Standard it is because fooName
is a non-local object of POD-type which is initialized using a
constant expression and 3.6.2/1 states:
"[...]Objects of POD Types with static storage duration
initialized with constant expressions shall be initialized
before any dynamic initialization takes place"
|
Exactly.
| Quote: | I'm asking because at least on one compiler I tried fooName is
sometimes a null pointer when f is entered.
|
That's bad. This isn't a new rule; it has existed since the
earliest days of C++. Personally, I've never encountered a
compiler which got this wrong. (Typically, a compiler/linker
will lay down an image of such variables in the executable file
on the disk, and the system will load it before ever executing a
single instruction in the users process.)
| Quote: | Is this a bug in the compiler? Or am I misinterpreting the C++
Standard?
|
A very serious bug in the compiler.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Wed Jul 06, 2005 10:45 am Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
Why create two variables when you only need one? Try:
const char fooName[] = "foo";
Cheers, Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Thu Jul 07, 2005 2:47 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
| Quote: | Why create two variables when you only need one? Try:
const char fooName[] = "foo";
|
Why create two identical arrays of const char if you only need one?
Where is the second variable in
const char* const fooName = "foo";
? "foo" is a literal.
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
wkaras@yahoo.com Guest
|
Posted: Fri Jul 08, 2005 1:03 am Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]kaufmann (AT) cs (DOT) uni-potsdam.de[/email] wrote:
| Quote: | Hello,
I have a non-local constant fooName defined like this:
const char* const fooName = "foo";
fooName is used in a function f that is called in the course of the
dynamic-initialization of a non-local object (f and the non-local
object live in different TUs)
My question: Is it guaranteed that on entering f fooName is already
initialized and therefore different to 0?
As far as I understand the C++ Standard it is because fooName is a
non-local object of POD-type which is initialized using a constant
expression and 3.6.2/1 states:
"[...]Objects of POD Types with static storage duration initialized
with constant expressions shall be initialized before any dynamic
initialization takes place"
I'm asking because at least on one compiler I tried fooName is
sometimes a null pointer when f is entered.
Is this a bug in the compiler? Or am I misinterpreting the C++
Standard?
|
In order to avoid breaking alot of old C code, I believe that
the type of a string literal is "char *" rather than "const char *"
as it should be. This may mean that, technically, the behavior
you are seeing is compliant with the Standard. But it still
seems really dumb, since the compiler must generate code to
initialize the pointer, which could be initialized by the
loader.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Fri Jul 08, 2005 11:15 am Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]wkaras (AT) yahoo (DOT) com[/email] wrote:
| Quote: | In order to avoid breaking alot of old C code, I believe that
the type of a string literal is "char *" rather than "const char *"
as it should be.
|
It is neither. "A ordinary string literal has type 'array of n const
char'" (2.13.4/1).
In order to avoid breaking a lot of old C code, there exists a
conversion to "an rvalue of type 'pointer to char' [...] Note: This
conversion is deprecated." (4.2/2).
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Fri Jul 08, 2005 1:23 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
In article <1120758734.270911.14180 (AT) g43g2000cwa (DOT) googlegroups.com>,
"wkaras (AT) yahoo (DOT) com" <wkaras (AT) yahoo (DOT) com> writes
| Quote: | In order to avoid breaking alot of old C code, I believe that
the type of a string literal is "char *" rather than "const char *"
as it should be. This may mean that, technically, the behavior
you are seeing is compliant with the Standard. But it still
seems really dumb, since the compiler must generate code to
initialize the pointer, which could be initialized by the
loader.
|
You are mistaken. The type of a string literal in C++ is char const *.
There is a special deprecated conversion designed to minimise breaking
legacy code that allows an unsafe conversion to char* in a very
restricted set of circumstances.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Mon Aug 01, 2005 12:31 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
const char* const fooName creates an ASCII-NUL terminated buffer with
'f', 'o', 'o', ' ', then the second variable is a constant pointer to
const char, intialised to address the former. Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Wed Aug 03, 2005 3:25 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
| Quote: | const char* const fooName creates an ASCII-NUL terminated buffer with
'f', 'o', 'o', ' ', then the second variable is a constant pointer to
const char, intialised to address the former.
|
const char* const fooName declares a variable named fooName of type
const pointer to const char. It does not create a buffer. "foo" is a
string literal which is stored somewhere in memory, but it's not a
variable. This code:
char const* p1 = "foo";
char const* p2 = "foo";
may cause one or two character buffers to be allocated. It's up to the
compiler. p1 and p2, on the other hand, are two variables which are
always distinct.
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Fri Aug 05, 2005 3:07 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
Hi Gerhard,
You're thinking from the C++ perspective of "variable", while I'm
thinking at the assembly level - in terms of reserved space in the
executable.
Anyway, you appear to have missed my point, which is that there is no
need for a pointer-to-character variable to keep track of a string
literal when we can directly allocate and access the string literal,
and have no intention of moving the pointer. It removes the OP's
problem if he allocates const char foo[] = "foo"; ... there is simply
no race condition involving a pointer's assignment.
Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Allan W Guest
|
Posted: Sat Aug 06, 2005 9:52 am Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
| Quote: | Hi Gerhard,
you appear to have missed my point, which is that there is no
need for a pointer-to-character variable to keep track of a string
literal when we can directly allocate and access the string literal,
and have no intention of moving the pointer. It removes the OP's
problem if he allocates const char foo[] = "foo"; ... there is simply
no race condition involving a pointer's assignment.
|
Hopefully this will help to explain.
void callFunc(const char*);
const char* const fooName1 = "foo";
const char fooName2[] = "foo";
int main() {
callFunc(fooName1);
callFunc(fooName2);
}
void callFunc(const char*) { /* do nothing */ }
Here's how the relevant parts can translate into assembly language.
On my Microsoft Windows XP computer, pointers are 4 bytes -- but
the concepts should be similar on any computer, at least before
optimization takes place.
const char* const fooName1 = "foo";
// compiles to a 4-byte pointer (shown in hexidecimal):
// 00 1C 40 42 ; Address of data
// and 4 MORE bytes of data:
// 66 6F 6F 00 ; 'f' 'o' 'o' ' '
callFunc(fooName1);
// compiles to 4 instructions, 14 bytes:
// A1 20 40 42 00 ;mov eax,dword ptr [fooName2] ; Read address
// 50 ;push eax ; and save on stack
// E8 40 F6 FF FF ;call dummyFunc ; Do the call
// 83 C4 04 ;add esp,4 ; Clean stack
// Total of 22 bytes.
const char fooName2[] = "foo";
// compiles to 4 bytes of data (no pointer needed):
// 66 6F 6F 00 ; 'f' 'o' 'o' ' '
callFunc(fooName2);
// compiles to 3 instructions, 13 bytes (comments mine):
// 68 1C 40 42 00 ;push offset fooName1 ; Save address on stack
// E8 4E F6 FF FF ;call callFunc ; Do the call
// 83 C4 04 ;add esp,4 ; Clean stack
// Total of 17 bytes.
The second call to callFunc() is not only trivially smaller, but
also trivially faster... (at least, before compiler optimizations
take place).
Yes, yes, premature optimization and all that, quite right... but
the point is, if your extra level of indirection (the pointer)
doesn't give you anything, don't use it.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Mon Aug 08, 2005 3:10 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
| Quote: | You're thinking from the C++ perspective of "variable", while I'm
thinking at the assembly level - in terms of reserved space in the
executable.
|
Considering that this is a C++ newsgroup, thinking from the C++
perspective is a venial sin, I would say.
| Quote: | Anyway, you appear to have missed my point, which is that there is no
need for a pointer-to-character variable to keep track of a string
literal when we can directly allocate and access the string literal,
and have no intention of moving the pointer. It removes the OP's
problem if he allocates const char foo[] = "foo"; ... there is simply
no race condition involving a pointer's assignment.
|
The problem of the original poster had nothing to do with a race
condition, nor with pointer assignment. It was about initialization of
POD type objects of static storage duration. And yes, that's from a C++
perspective again.
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Wed Aug 10, 2005 7:01 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
Hi Gerhard,
I hope Allan's spot-on post is explicit enough to convey the difference
between 'const char* p = "abc";' and "const char p[] = "abc";'. Still,
I see you don't see the relevance to the original poster's queries,
so...
Firstly, the question is about linkage, and is not specific to C++.
You've got to be able to think a level lower - in terms of the implicit
as well as explicit variables your C++ code is generating, as well as
objects, symbols, linkage and static initialisation - to understand
these issues.
Secondly, Ben was asking whether the pointer version was guaranteed to
be initialised before it was accessed, even if the accessing code was
part of a separate translation unit. Thus, he is asking whether
there's a race condition: not necessarily in the multi-threaded sense,
but definitely in the "which-initialisation code will the linker select
to run first" sense. It _could_ also be a race condition in the
multithreaded sense if code planning to use the pointer was running in
a distinct thread from that planning to initialise it.
Ultimately, my point is simply to follow the "keep it simple, [stupid]"
rule, and remove the unnecessary pointer from the situation. Allan
says this is premature optimisation, but that's not true. It's not an
optimisation, or a compromise, it's simply the purest expression of
what's wanted, and should be used by default. To access string
literals through pointers implies that you may want to point these
pointers elsewhere, but when they're const pointers that's not even
possible so it's a needless obfuscation and waste of CPU time,
executable and memory space.
Cheers,
Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Gerhard Menzl Guest
|
Posted: Wed Aug 17, 2005 5:19 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
[email]tony_in_da_uk (AT) yahoo (DOT) co.uk[/email] wrote:
| Quote: | Firstly, the question is about linkage, and is not specific to C++.
You've got to be able to think a level lower - in terms of the
implicit as well as explicit variables your C++ code is generating, as
well as objects, symbols, linkage and static initialisation - to
understand these issues.
|
I disagree, on two counts. First, there is absolutely no need to descend
to assembly language level in order to understand the C++ Standard rules
of initialization. The compiler is free to arrange these low level
matters in any way it sees fit, as long as the high level rules are
obeyed. Second, these rules are by definition specific to C++. The
initialization rules for C, Java, Ada, or whatever are entirely
irrelevant when it's a C++ compiler you are dealing with.
| Quote: | Secondly, Ben was asking whether the pointer version was guaranteed to
be initialised before it was accessed, even if the accessing code was
part of a separate translation unit. Thus, he is asking whether
there's a race condition: not necessarily in the multi-threaded sense,
but definitely in the "which-initialisation code will the linker
select to run first" sense. It _could_ also be a race condition in
the multithreaded sense if code planning to use the pointer was
running in a distinct thread from that planning to initialise it.
|
The term race condition is normally used in the context of concurrent
programming; applying it to comparatively simple order-of-initialization
issues is only going to cloud the issue, especially since the original
poster has not mentioned threads.
| Quote: | Ultimately, my point is simply to follow the "keep it simple,
[stupid]" rule, and remove the unnecessary pointer from the situation.
Allan says this is premature optimisation, but that's not true. It's
not an optimisation, or a compromise, it's simply the purest
expression of what's wanted, and should be used by default. To access
string literals through pointers implies that you may want to point
these pointers elsewhere, but when they're const pointers that's not
even possible so it's a needless obfuscation and waste of CPU time,
executable and memory space.
|
Come on. We're talking about (typically) four bytes of extra memory
space that are written exactly once, at the beginning of the program.
Apart from that, this is of no relevance for the original question:
const char* p = "abc";
is static initialization. Static initialization of POD objects must take
place before dynamic initialization, period; a compiler that doesn't
guarantee this is severely broken, as James Kanze has pointed out
already. If a compiler doesn't get this right, you cannot rely on it to
cause
const char p[] = "abc";
to execute in time either. It may or may not turn out to be a workaround
for a particular version of a particular non-conforming compiler. From a
Standard perspective, however, the advice is simply off the mark, as far
as the original question is concerned.
--
Gerhard Menzl
#dogma int main ()
Humans may reply by replacing the thermal post part of my e-mail address
with "kapsch" and the top level domain part with "net".
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
tony_in_da_uk@yahoo.co.uk Guest
|
Posted: Thu Aug 18, 2005 3:45 pm Post subject: Re: Question regarding initialization of non-local POD-Objec |
|
|
Gerhard,
I agree that the Standard _should_ allow people to understand that
const char* const p = "abc" is asking for two data elements (though the
pointer may well be optimised out), and should specify the required
programmatically observable behaviour of the
compiler/linker/loader/executable in performing initialisation. I
maintain that this thread is evidence of the failure of interested
parties to either consult the Standard or interpret it in such a way
that they provide the best advice to the original poster.
What I've suggested as a complement to the Standard is an understanding
of the constraints placed on the C++ compiler by the layout and
handling of generated objects in typical deployment environments. It
is these constraints that have shaped the C++ Standard, and how the C++
compiler works can sometimes be deduced by an understanding of these
factors.
These aspects obviously aren't clear to you, as you say `you cannot
rely on it to cause const char p[] = "abc" to execute in time either'.
In this case, the only data element (p) will be placed in a section of
the executable storing preinitialised data, and loaded by the Operating
System loader without the aid of any executable-provided code. If
necessary on a particular deployment environment, any pointers to the
data will be "patched" into the executable image by the loader before
starting the executable running. The original poster's concern was
that on some systems `const char* p = "abc"' could require code in the
executable to initialise the pointer, and I'm showing that since he
doesn't actually have any use for the pointer, he can discard it and
have one less problem to worry about.
Summarily, basic knowledge of Operating Systems, object layout,
linkage, and loaders makes this obvious.
You're correct in saying that the original poster didn't mention
threads, but he didn't specifically say he had a single-threaded
program either. Surely you're not maintaining that multi-threading is
so arcane in the context of initialisation order I shouldn't have
bothered to complicate the situation by mentioning it? Anyway way, as
threading may be relevant to the situation, I believe it's useful to
discuss whether a prospective solution is thread safe or not.
And as a stylistic issue, it's simply poor practice to write const
char* const p = "abc", as you've no use for the pointer, and it
suggests a lack of understanding of the layout of data that you do
actually intend to use. It's not a case of "[only] (typically) four
bytes" as you suggest - it's a matter of concision and clarity of
intent. You're not buying anything except obfuscation with your extra
four bytes.
In conclusion, your belief that `const char p[] = "abc" is just a
possible workaround for a particular version of a non-conforming
compiler' is complete nonsense. It is the proper programming practice
that removes even the question of initialisation order.
Tony
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|