Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #81933 > unrolled thread

Global const objects missing from object file

Started bySteve Keller <keller.steve@gmx.de>
First post2021-10-08 22:47 +0200
Last post2021-10-09 17:40 +0000
Articles 5 on this page of 25 — 10 participants

Back to article view | Back to comp.lang.c++


Contents

  Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-08 22:47 +0200
    Re: Global const objects missing from object file red floyd <no.spam.here@its.invalid> - 2021-10-08 15:09 -0700
      Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 08:28 +0200
        Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 12:03 +0300
        Re: Global const objects missing from object file David Brown <david.brown@hesbynett.no> - 2021-10-10 12:29 +0200
    Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-09 10:47 +0300
      Re: Global const objects missing from object file scott@slp53.sl.home (Scott Lurndal) - 2021-10-09 14:32 +0000
        Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-09 21:39 +0300
      Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 08:55 +0200
        Re: Global const objects missing from object file Bo Persson <bo@bo-persson.se> - 2021-10-10 10:34 +0200
          Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 15:55 +0200
            Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 17:28 +0300
              Re: Global const objects missing from object file Steve Keller <keller.steve@gmx.de> - 2021-10-10 20:42 +0200
                Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 22:44 +0300
        Re: Global const objects missing from object file Paavo Helde <myfirstname@osa.pri.ee> - 2021-10-10 12:14 +0300
          Re: Global const objects missing from object file Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-10-29 06:29 -0700
            Re: Global const objects missing from object file Bo Persson <bo@bo-persson.se> - 2021-10-29 15:55 +0200
              Re: Global const objects missing from object file Öö Tiib <ootiib@hot.ee> - 2021-10-29 22:20 -0700
              Re: Global const objects missing from object file Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-11-07 04:51 -0800
            Re: Global const objects missing from object file scott@slp53.sl.home (Scott Lurndal) - 2021-10-29 14:44 +0000
              Re: Global const objects missing from object file Tim Rentsch <tr.17687@z991.linuxsc.com> - 2021-11-07 05:08 -0800
                Re: Global const objects missing from object file scott@slp53.sl.home (Scott Lurndal) - 2021-11-07 14:21 +0000
        Re: Global const objects missing from object file David Brown <david.brown@hesbynett.no> - 2021-10-10 12:33 +0200
    Re: Global const objects missing from object file "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2021-10-09 15:05 +0200
    Re: Global const objects missing from object file Juha Nieminen <nospam@thanks.invalid> - 2021-10-09 17:40 +0000

Page 2 of 2 — ← Prev page 1 [2]


#82260

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2021-11-07 05:08 -0800
Message-ID<86ilx4aza8.fsf@linuxsc.com>
In reply to#82179
scott@slp53.sl.home (Scott Lurndal) writes:

> Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>
>> Paavo Helde <myfirstname@osa.pri.ee> writes:
>>
>>> In some sense the do not differ.  The const globals in C++ are
>>> primarily meant for replacing C #define.  Each C #define is TU-specific
>>> and gets fully preprocessed by the preprocessor, no other TU-s are
>>> involved.
>>
>> It appears you have sidestepped the central question here.  What a
>> definition like 'const int foo = 7;'  (without any mention anywhere
>> of 'extern') does in C++ is, AFAICT, exactly the same as a similar
>> definition with static, namely 'static const int foo = 7;'.
>
> Is that not dependent upon scope?  For example:
>
> class x {
>   static const unsigned long FRED = 0xabcdef00ul;
>
> };

Yes, it's true that leaving off 'static' here means something
significantly different.  Note however, (a) neither of these
forms is allowed in C so there is no question of incompatibility;
(b) the 'static'-less form wasn't allowed until C++11;  (c) only
the 'static' form works for the purpose of being usable in
constant expressions, so the question here is moot.

> requires an additional declaration in a compilation unit, e.g.
>
>   const unsigned long x::FRED;

In my tests such a declaration was needed only if the address of
the static member FRED was taken.  (I confess I didn't even try
to consult the C++ standard to see if that result is officially
okay or is merely a consequence of undefined behavior.)

> While
>
> namespace y {
>    const unsigned long FRED = 0xabcdef00ul;
> };
>
> doesn't require an additional declaration.

AFAICT declarations inside namespaces behave the same way as
declarations at file scope, that is, const-without-static
behaves just the same way as const-with-static (and the same
rules for declarations/definitions, etc).  So I don't think
this scenario is an exception to what I said earlier.

[toc] | [prev] | [next] | [standalone]


#82262

Fromscott@slp53.sl.home (Scott Lurndal)
Date2021-11-07 14:21 +0000
Message-ID<JhRhJ.65858$iq.35710@fx10.iad>
In reply to#82260
Tim Rentsch <tr.17687@z991.linuxsc.com> writes:
>scott@slp53.sl.home (Scott Lurndal) writes:
>

>> Is that not dependent upon scope?  For example:
>>
>> class x {
>>   static const unsigned long FRED = 0xabcdef00ul;
>>
>> };
>
>Yes, it's true that leaving off 'static' here means something
>significantly different.  Note however, (a) neither of these
>forms is allowed in C so there is no question of incompatibility;
>(b) the 'static'-less form wasn't allowed until C++11;  (c) only
>the 'static' form works for the purpose of being usable in
>constant expressions, so the question here is moot.
>
>> requires an additional declaration in a compilation unit, e.g.
>>
>>   const unsigned long x::FRED;
>
>In my tests such a declaration was needed only if the address of
>the static member FRED was taken.  (I confess I didn't even try
>to consult the C++ standard to see if that result is officially
>okay or is merely a consequence of undefined behavior.)

Actually, it depends more on context and the compilation options.

With gcc (on linux), if you compile with -O2 or -O3 (and do
not use the address operator), you don't need to add the
declaration.   If you don't use -O, then you will likely find
the linker complaining about a missing symbol.   I see this
quite regularly, to the point that we generally use enum for
constants (or const definitions in a namespace), even tho
enum (pre C++xx) doesn't lend itself to type safety.

[toc] | [prev] | [next] | [standalone]


#81963

FromDavid Brown <david.brown@hesbynett.no>
Date2021-10-10 12:33 +0200
Message-ID<sjufig$ekt$1@dont-email.me>
In reply to#81958
On 10/10/2021 08:55, Steve Keller wrote:
> Paavo Helde <myfirstname@osa.pri.ee> writes:
> 
>> Such global const definitions normally appear in a common header file
>> and would just cause duplicate linker symbols if they had external
>> linkage. Now they can be just optimized away in translation units
>> which do not use them.
>>
>> I believe the original motivation was to have an easy replacement of C
>> macros in header files, i.e. instead of
>>
>> #define a 42
>>
>> one can easily use
>>
>> const int a = 42;
>>
>> which would function almost exactly like a #define, plus it honors C++
>> namespaces and cannot be undefined.
> 
> If you write such "global" const objects into a header file they are
> in fact not global, because the implicit 'static' makes them local to
> file translation unit and this can even cause duplication:
> 
>     $ cat foo.hh
>     const int a = 42;
>     
>     const int *bar();
>     $ cat x.cc
>     #include "foo.hh"
>     
>     const int *bar() { return &a; }
>     $ cat y.cc
>     #include <iostream>
>     
>     #include "foo.hh"
>     
>     const int *foo() { return &a; }
>     
>     int main()
>     {
>         std::cout << (void *)foo() << '\n' << (void *)bar() << '\n';
>     }
>     $ g++ -Os -o foo x.cc y.cc
>     $ ./foo
>     0x56027d731008
>     0x56027d731004
> 
> For a small 'int' one may not care but for larger constant objects
> this may be really bad.
> 
> To avoid it, I think you still have to write the defintion into only
> one C++ source file using 'extern'
> 
>     extern const int = 42;

You don't (IMHO) want "extern" here - you want to make sure that this
file includes the header with the "extern const int a;" declaration.
(And you forgot the "a" in that line.)

> 
> and put
> 
>     extern const int a;
> 
> into the header file.  I still don't see the advantage for C++ to
> differ from C here.
> 

It is convenient when you have const objects defined within a file and
that are local to the file - there is no need for a "static".  (A lot of
people are far too lazy about putting "static" where it is appropriate
in their C and C++ coding.)

With C++17, you can also write:

	extern inline const int a = 42;

in the header, and you don't need a definition in a C++ file.

[toc] | [prev] | [next] | [standalone]


#81944

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2021-10-09 15:05 +0200
Message-ID<sjs428$165$1@dont-email.me>
In reply to#81933
On 8 Oct 2021 22:47, Steve Keller wrote:
> I am surprised I cannot define a global const object in one file and
> access it in another:
> 
> --------- x.cc ---------
> const int a = 42

Assuming the code actually has a semicolon here, so that it compiles. 
Copy and paste code to avoid such typos.


> ------------------------
> 
> --------- y.cc ---------
> extern const int a;
> 
> int foo() { return a; }
> ------------------------
> 
> When I compile both sources to objects I see access to 'a' as
> expected:
> 
>          movl    a(%rip), %eax
>          ret
> 
> But the object file x.o does not contain anything.  Why?

Because without `extern` the definition in `x.cpp` has internal linkage, 
as noted by Red Floyd in his response.

And since it's not visible outside the translation unit, and is not used 
within it, and its initialization has no side effects, it's optimized away.


> If I remove the 'const' in the definition and in the extern
> declaration it works as expected.  Also if add an 'extern' to the
> definition in x.cc so that it is
> 
> extern const int a = 42;
> 
> the object 'a' is created in x.o.  Can someone explain this?

See above.

A good way to avoid these problems is to place the declaration of `a`, 
with an `extern`, in a header file that you include both in the defining 
source file and in the using source file.

Because, when the compiler has seen the `extern`-ness of `a` once in a 
translation unit, then in any subsequent encounter of `a` that 
`extern`-ness is implied.


- Alf

[toc] | [prev] | [next] | [standalone]


#81949

FromJuha Nieminen <nospam@thanks.invalid>
Date2021-10-09 17:40 +0000
Message-ID<sjsk5p$v77$1@gioia.aioe.org>
In reply to#81933
Steve Keller <keller.steve@gmx.de> wrote:
> If I remove the 'const' in the definition and in the extern
> declaration it works as expected.  Also if add an 'extern' to the
> definition in x.cc so that it is
> 
> extern const int a = 42;
> 
> the object 'a' is created in x.o.  Can someone explain this?

This is one key difference between C and C++.

In C, const variables at the global namespace level have external linkage
by default. In other words, they are implicitly 'extern'.

In C++, const variables at the namespace level (including the global
namespace) have internal linkage by default. In other words, they are
implicitly 'static'.

In C, if you want a const variable in the global namespace to have
internal linkage, you need to explicitly specify 'static' in its
declaration.

In C++, if you want a const variable at a namespace level (including
the global namespace) to have external linkage, you need to explicitly
specify 'extern' in its declaration.

(In C++ this is true for *any* type, not just basic types.)

Previously this was a minor nuisance in C++ because a 'const' variable
in a header would be duplicated in each object file that used it, if
the compiler couldn't optimize it away (ie. "inline" it). If you wanted
only one instance of that const variable, you had to 'extern' it manually.

C++17 added support for "inline const" variables, which does this for
you automatically (in the same way as 'inline' does with functions).

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.c++


csiph-web