Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

who's at fault, me or compiler?

378 views
Skip to first unread message

already...@yahoo.com

unread,
Jun 24, 2020, 6:11:35 AM6/24/20
to
#include <cstdlib>
#include <algorithm>

struct bar {
static const int foo = 42;
};
int main()
{
return std::max(rand(), bar::foo);
}


Both up to date g++ and clang++ -O0 under MSYS2 fail during link claiming 'undefined reference to bar::foo'.

With optimization enabled everything works fine, but that's because an optimizer eliminates reference to bar::foo.

VS2017 and 2019 link it just fine, regardless of optimization level.


Now, thinking a little about the root of the problem, I figured out how to write a simpler reproducer that does not depend on optimization level:

#include <cstdio>
struct bar {
static const int foo = 42;
};
int main()
{
return printf("%p\n", &bar::foo);
}

Juha Nieminen

unread,
Jun 24, 2020, 6:46:06 AM6/24/20
to
already...@yahoo.com wrote:
> #include <cstdlib>
> #include <algorithm>
>
> struct bar {
> static const int foo = 42;
> };
> int main()
> {
> return std::max(rand(), bar::foo);
> }
>
>
> Both up to date g++ and clang++ -O0 under MSYS2 fail during link claiming 'undefined reference to bar::foo'.
>
> With optimization enabled everything works fine, but that's because an optimizer eliminates reference to bar::foo.

The problem is that std::max() takes a reference to its parameter, which
means that it needs an actual object, ie. an actual instance of that object.

Technically speaking you have to instantiate all class variables
(ie. "static" variables inside a class). The declaration of the variable is not
an instantiation. Just a declaration. That means that if you have:

struct bar
{
static int foo;
};

that's not enough. You have to also instantiate that variable somewhere:

int bar::foo = 42;

Static const integral variables are a bit more complicated. With them you
only need to instantiate them if you need their address (ie. you need a
pointer or reference to them), but if that's the case, you have to
instantiate them, else the compiler cannot get an address to it.
That's why you are getting a linker error.

> Now, thinking a little about the root of the problem, I figured out how to write a simpler reproducer that does not depend on optimization level:
>
> #include <cstdio>
> struct bar {
> static const int foo = 42;
> };
> int main()
> {
> return printf("%p\n", &bar::foo);
> }

This is even clearer because here you are trying to get a pointer to variable
that has only been declared but hasn't been instantiated. You have to
instantiate it if you want a pointer to it:

const int bar::foo = 42;

already...@yahoo.com

unread,
Jun 24, 2020, 7:15:49 AM6/24/20
to
I know how C++ worked in 20th century. Just hoped that this bad days gone.
It seems, they are only gone in Microsoft world.

However even in gcc/clang word it is not quite as bad as you're saying.
The code below passes compilation/link just fine. So, situation is pretty bad, but not quite as bad as in 20th century.

#include <cstdio>
struct bar {
static const int foo = 42;
};
const int bar::foo;

already...@yahoo.com

unread,
Jun 24, 2020, 11:03:41 AM6/24/20
to
On Wednesday, June 24, 2020 at 1:11:35 PM UTC+3, already...@yahoo.com wrote:
> #include <cstdlib>
> #include <algorithm>
>
> struct bar {
> static const int foo = 42;
> };
> int main()
> {
> return std::max(rand(), bar::foo);
> }
>
>
> Both up to date g++ and clang++ -O0 under MSYS2 fail during link claiming 'undefined reference to bar::foo'.
>
> With optimization enabled everything works fine, but that's because an optimizer eliminates reference to bar::foo.
>
> VS2017 and 2019 link it just fine, regardless of optimization level.
>

So, unless I am missing something, in 2020 C++ still has no nice portable syntax for typed constants that can be declared at class==struct scope and don't come in conflict with basic DRY principle.

Here is the best workaround I was able to find:

//---- beg
#include <cstdlib>
#include <algorithm>

struct bar {
static constexpr int foo() { return 42};
};
int main()
{
return std::max(rand(), bar::foo());
}
//---- end

It appears portable, but quite ugly.
I wouldn't use it in practice because it hurts my sense of esthetic.

Juha Nieminen

unread,
Jun 24, 2020, 11:03:58 AM6/24/20
to
already...@yahoo.com wrote:
>> const int bar::foo = 42;
>
> I know how C++ worked in 20th century. Just hoped that this bad days gone.
> It seems, they are only gone in Microsoft world.
>
> However even in gcc/clang word it is not quite as bad as you're saying.
> The code below passes compilation/link just fine. So, situation is pretty bad, but not quite as bad as in 20th century.

I have absolutely no idea what you are talking about. The behavior
and requirements of class variables has always been the same. That
hasn't changed. And in your code you did exactly as I instructed:

> #include <cstdio>
> struct bar {
> static const int foo = 42;
> };
> const int bar::foo;
> int main()
> {
> return printf("%p\n", &bar::foo);
> }

So I have no idea what you are talking about, "they are only gone
in Microsoft world". What is gone in "Microsoft world"?

already...@yahoo.com

unread,
Jun 24, 2020, 11:29:46 AM6/24/20
to
On Wednesday, June 24, 2020 at 6:03:58 PM UTC+3, Juha Nieminen wrote:
> already...@yahoo.com wrote:
> >> const int bar::foo = 42;
> >
> > I know how C++ worked in 20th century. Just hoped that this bad days gone.
> > It seems, they are only gone in Microsoft world.
> >
> > However even in gcc/clang word it is not quite as bad as you're saying.
> > The code below passes compilation/link just fine. So, situation is pretty bad, but not quite as bad as in 20th century.
>
> I have absolutely no idea what you are talking about. The behavior
> and requirements of class variables has always been the same. That
> hasn't changed. And in your code you did exactly as I instructed:
>

No, my code has initializer (= 42) within class declaration. Yours has it outside.
Initializer residing within class declaration (so, most likely in the in header file) is better than in implementation (most likely in separate file).
It's better from the perspective of programmer that is going to use the interface, because if he want to see an actual value of the bar::foo, it's here in the "interface" file. He is not forced to look in the implementation file.
It is also better from the perspective of compiler, because even without LTCG or similar technique compiler can see the actual value and use the knowledge for optimization.

AFAIR, initializer within class declaration was not allowed in 20th century, except may be last years or two. So, I count it as improvement.

> > #include <cstdio>
> > struct bar {
> > static const int foo = 42;
> > };
> > const int bar::foo;
> > int main()
> > {
> > return printf("%p\n", &bar::foo);
> > }
>
> So I have no idea what you are talking about, "they are only gone
> in Microsoft world". What is gone in "Microsoft world"?

Bad old days.

Alf P. Steinbach

unread,
Jun 24, 2020, 11:31:08 AM6/24/20
to
In spite of the initialization the declaration of `bar::foo` is just a
declaration, not a definition.

That means that no storage is allocated.

When the address of `bar::foo` is used (even just internally in
pass-by-reference) you introduce a dependency on the storage whose
address is taken, but there's no such, so ideally the linker complains.

- - -

A compiler & linker may still erroneously accept the code. One reason,
as you note, is that optimization can remove the problem before it's
noticed. Also, it was for a time common practice, and as noted below
there is apparently something in C++17 that allows this code.

Visual C++ 2019, in blissful ignorance, accepts both your examples,
compiled as C++11, C++14 and C++17.

MinGW g++ 9.2. produces a linker error for C++11 and C++14, but is okay
with the examples as C++17.

I do not know of any change in C++17 that should make the examples valid
(modulo the pointer argument in the last, which should be `(void*)`).

But perhaps there is, or perhaps it's just a compiler quirk.

- - -

A C++17 workaround, if C++17 doesn't make the code valid, is to declare
the variable as `inline`.

In C++14 and earlier one could use one of

* Providing a /definition/ of the variable.
For a header only module this involved placing the variable in a
class template, which is then fully specialized with arbitrary params.

* Using an `enum` instead of an integral type constant.
Curiously enumerations are not formally integral types.

* Using a `constexpr` function.


- Alf

already...@yahoo.com

unread,
Jun 24, 2020, 11:35:55 AM6/24/20
to
On Wednesday, June 24, 2020 at 6:03:41 PM UTC+3, already...@yahoo.com wrote:
> On Wednesday, June 24, 2020 at 1:11:35 PM UTC+3, already...@yahoo.com wrote:
> > #include <cstdlib>
> > #include <algorithm>
> >
> > struct bar {
> > static const int foo = 42;
> > };
> > int main()
> > {
> > return std::max(rand(), bar::foo);
> > }
> >
> >
> > Both up to date g++ and clang++ -O0 under MSYS2 fail during link claiming 'undefined reference to bar::foo'.
> >
> > With optimization enabled everything works fine, but that's because an optimizer eliminates reference to bar::foo.
> >
> > VS2017 and 2019 link it just fine, regardless of optimization level.
> >
>
> So, unless I am missing something, in 2020 C++ still has no nice portable syntax for typed constants that can be declared at class==struct scope and don't come in conflict with basic DRY principle.
>
> Here is the best workaround I was able to find:
>
> //---- beg
> #include <cstdlib>
> #include <algorithm>
>
> struct bar {
> static constexpr int foo() { return 42};
> };
> int main()
> {
> return std::max(rand(), bar::foo());
> }
> //---- end
>
> It appears portable, but quite ugly.
> I wouldn't use it in practice because it hurts my sense of esthetic.
>


O.k. I was missing something. There exists a better workaround:

#include <cstdlib>
#include <algorithm>

struct bar {
static inline const int foo = 42;
};
int main()
{
return std::max(rand(), bar::foo);
}


It requires C++17, which I have but some of the people I am working with can not have, so I am not sure if I'm going to apply it right now. But that's my problems, not of C++ standard.

Öö Tiib

unread,
Jun 24, 2020, 11:49:04 AM6/24/20
to
On Wednesday, 24 June 2020 13:11:35 UTC+3, already...@yahoo.com wrote:
> #include <cstdlib>
> #include <algorithm>
>
> struct bar {
> static const int foo = 42;
> };
> int main()
> {
> return std::max(rand(), bar::foo);
> }
>
>
> Both up to date g++ and clang++ -O0 under MSYS2 fail during link claiming 'undefined reference to bar::foo'.

Use constexpr.
C++17 makes the definition redundant for constexpr (but allowed)
https://timsong-cpp.github.io/cppwp/n4659/depr.static_constexpr#1

#include <cstdlib>
#include <algorithm>

struct bar {
static constexpr int foo = 42;
};
// constexpr int bar::foo; <- unneeded but valid

already...@yahoo.com

unread,
Jun 24, 2020, 11:51:54 AM6/24/20
to
Actually, I see that it is in spirit of the language. That's similar to how templates are handled in many situations.
Are you sure that it's explicitly disallowed by the Standard?

> MinGW g++ 9.2. produces a linker error for C++11 and C++14, but is okay
> with the examples as C++17.
>
> I do not know of any change in C++17 that should make the examples valid
> (modulo the pointer argument in the last, which should be `(void*)`).
>
> But perhaps there is, or perhaps it's just a compiler quirk.
>
> - - -
>
> A C++17 workaround, if C++17 doesn't make the code valid, is to declare
> the variable as `inline`.
>

Thanks. I already figured it out a hour or so ago. Good to know that it works not just by chance on 3 compilers I tested, but by Standard.

> In C++14 and earlier one could use one of
>
> * Providing a /definition/ of the variable.
> For a header only module this involved placing the variable in a
> class template, which is then fully specialized with arbitrary params.
>

A bit ugly, isn't it?

> * Using an `enum` instead of an integral type constant.
> Curiously enumerations are not formally integral types.

enum is untyped. An 'int' type in my example, that happens to be fully compatible with enum, was here just for sake of illustration. The types I want to use in real code, are different.

'class enum" can be typed, but it has even worse usability issues.
Requires ALOT of explicit casting just about everywhere.

>
> * Using a `constexpr` function.
>

That's my first workaround (see above). Very ugly.

>
> - Alf

Alf P. Steinbach

unread,
Jun 24, 2020, 11:56:40 AM6/24/20
to
[P:\temp]
> type foo.cpp
#include <cstdio>
struct bar {
static constexpr int foo = 42;
};
int main()
{
return printf("%p\n", (void*)&bar::foo);
}

[P:\temp]
> g++64 foo.cpp -std=c++14
h:/installed/mingw/nuwen/mingw
9-2/bin/../lib/gcc/x86_64-w64-mingw32/9.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe:
C:\Users\AlfP\AppData\Local\Temp\ccMtRldi.o:foo.cpp:(.rdata$.refptr._ZN3bar3fooE[.refptr._ZN3bar3fooE]+0x0):
undefined reference to `bar::foo'
collect2.exe: error: ld returned 1 exit status


... with MinGW g++ 9.2.


- Alf





Alf P. Steinbach

unread,
Jun 24, 2020, 12:02:14 PM6/24/20
to
Yes. It was the C++14 and earlier super-ugly way to express the kind of
linkage that one now has with `inline` variables. It was allowed by a
special exemption for templates in the One Definition Rule.



>> * Using an `enum` instead of an integral type constant.
>> Curiously enumerations are not formally integral types.
>
> enum is untyped. An 'int' type in my example, that happens to be fully compatible with enum, was here just for sake of illustration. The types I want to use in real code, are different.
>
> 'class enum" can be typed, but it has even worse usability issues.
> Requires ALOT of explicit casting just about everywhere.
>
>>
>> * Using a `constexpr` function.
>>
>
> That's my first workaround (see above). Very ugly.

Agreed.

But, to avoid the Static Initialization Fiasco(tm) problem, it can be a
good idea to use the function, essential a Meyer's singleton, in general.


- Alf

Öö Tiib

unread,
Jun 24, 2020, 12:03:30 PM6/24/20
to
I said C++17 ... it does C++14

already...@yahoo.com

unread,
Jun 24, 2020, 12:04:29 PM6/24/20
to
It works on gcc and clang only when -std=c++17 explicitly specified.
As a practical solution it is not as good as "const inline". Both of them require C++17, but "const inline" makes it more explicit.
In effect an innocent user that forgot to specify -std=c++17 will get incomprehensible link error in the first case vs quite intelligible warning (or error) in the second case.
It's a pity, actually, because esthetically 'constexpr' is less ugly than rather monstrous 'const inline'.

Juha Nieminen

unread,
Jun 25, 2020, 2:16:06 AM6/25/20
to
already...@yahoo.com wrote:
> So, unless I am missing something, in 2020 C++ still has no nice portable syntax for typed constants that can be declared at class==struct scope and don't come in conflict with basic DRY principle.

You don't seem to understand that you want a *pointer* to such a variable.
The pointer has to point somewhere. You can't have a pointer to a
compile-time constant. It has to actually point to a real address, and the
value you specified needs to be found there.

That means that the variable needs to be instantiated in one compilation
unit. The compiler (or more precisely the linker) needs to find it
somewhere.

As you noticed, C++17 added the possibility of automatizing that a bit
by using the "inline" keyword. It will instantiate the variable for you
(in each compilation unit where it's used, and the linker is then
instructed to use only one of them and discard the rest).

already...@yahoo.com

unread,
Jun 25, 2020, 4:58:14 AM6/25/20
to
On Thursday, June 25, 2020 at 9:16:06 AM UTC+3, Juha Nieminen wrote:
> already...@yahoo.com wrote:
> > So, unless I am missing something, in 2020 C++ still has no nice portable syntax for typed constants that can be declared at class==struct scope and don't come in conflict with basic DRY principle.
>
> You don't seem to understand that you want a *pointer* to such a variable.

You don't seem to understand that everything "you understand" about low level things I understand at least as well or better.
What I probably don't understand/know as well as yourself is a "new" C++11/14/17 things.

> The pointer has to point somewhere. You can't have a pointer to a
> compile-time constant. It has to actually point to a real address, and the
> value you specified needs to be found there.
>
> That means that the variable needs to be instantiated in one compilation
> unit. The compiler (or more precisely the linker) needs to find it
> somewhere.
>
> As you noticed, C++17 added the possibility of automatizing that a bit
> by using the "inline" keyword. It will instantiate the variable for you
> (in each compilation unit where it's used, and the linker is then
> instructed to use only one of them and discard the rest).

And I expected that it was here since C++03 and without special keyword.
Was disappointed to find out that it wasn't.
I really see zero advantage for C++ users (as opposed to C++ compiler's maintainers) in all that mess. IMHO, the way Microsoft handling it, i.e. things just work, is The Correct Way.
System-provided linker can't handle that? Come on, it's not 1970s any more! You (C++ compiler vendor) can develop your own linker or to help a system vendor to enhance his linker for your needs. Anything less is laziness. Esp. considering that very similar linker abilities are necessary for templates.



bol...@nowhere.co.uk

unread,
Jun 25, 2020, 5:14:01 AM6/25/20
to
On Thu, 25 Jun 2020 06:15:53 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>already...@yahoo.com wrote:
>> So, unless I am missing something, in 2020 C++ still has no nice portable
>syntax for typed constants that can be declared at class==struct scope and
>don't come in conflict with basic DRY principle.
>
>You don't seem to understand that you want a *pointer* to such a variable.
>The pointer has to point somewhere. You can't have a pointer to a
>compile-time constant. It has to actually point to a real address, and the

You can't? Whats this then:

const char *ptr = "hello world";


Juha Nieminen

unread,
Jun 26, 2020, 6:49:33 AM6/26/20
to
already...@yahoo.com wrote:
> On Thursday, June 25, 2020 at 9:16:06 AM UTC+3, Juha Nieminen wrote:
>> already...@yahoo.com wrote:
>> > So, unless I am missing something, in 2020 C++ still has no nice portable syntax for typed constants that can be declared at class==struct scope and don't come in conflict with basic DRY principle.
>>
>> You don't seem to understand that you want a *pointer* to such a variable.
>
> You don't seem to understand that everything "you understand" about low level things I understand at least as well or better.

I appreciate your humility.

> What I probably don't understand/know as well as yourself is a "new" C++11/14/17 things.

I don't really understand why you are talking about the new C++ standards
in this respect. I don't get your point.

Class variables (ie. "static" variables inside the scope of a class) have
always worked in this manner, all the way since the first standard, C++98
(and probably for as long as any version of C++ has supported static
variables inside a class scope). If you declare a class variable, you need
to tell the compiler where it should instantiate it, because the instance
must only be found in one compilation unit (if you instantiate it in
several compilation units you'll get a linker error because of duplicate
names). It's no different from function definitions.

Somehow you write as if this had changed between C++98 and C++11. It didn't.

C++17 added support for the 'inline' keyword in variables (including
class variables), which makes them work (from the perspective of the linker)
in the same way as 'inline' functions have always worked. In other words,
if the linker finds the same variable signature in more than one
compilation unit, it's instructed to not give an error about duplicate
names and instead just take one of them and discard the rest.

> And I expected that it was here since C++03 and without special keyword.

Why are you singling out C++03 in particular? Static variables inside a
class have *always* worked the same way, since C++98 and prior.

> IMHO, the way Microsoft handling it, i.e. things just work, is The Correct Way.

And how exactly does Microsoft handle this?

Juha Nieminen

unread,
Jun 26, 2020, 6:54:59 AM6/26/20
to
bol...@nowhere.co.uk wrote:
>>You don't seem to understand that you want a *pointer* to such a variable.
>>The pointer has to point somewhere. You can't have a pointer to a
>>compile-time constant. It has to actually point to a real address, and the
>
> You can't? Whats this then:
>
> const char *ptr = "hello world";

That's a string literal, not a compile-time constant. String literals are
instantiated wherever they are used (like happens here).

If you have a string literal in a header file, chances are that it will
be duplicated in every compilation unit where it's used (whether the
compiler will merge all these instances into one is implementation-defined,
but in most implementations unlikely to happen).

The difference to a class variable (ie. a "static" variable inside the
scope of a class) is that it must genuinely be instantiated only once.
Every use of that variable must refer to the same physical instance.
You mustn't have duplicated instances of it. (This is because all the
code that uses that variable must see the same variable, especially
if its value changes.)

bol...@nowhere.co.uk

unread,
Jun 26, 2020, 7:32:43 AM6/26/20
to
On Fri, 26 Jun 2020 10:54:48 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>bol...@nowhere.co.uk wrote:
>>>You don't seem to understand that you want a *pointer* to such a variable.
>>>The pointer has to point somewhere. You can't have a pointer to a
>>>compile-time constant. It has to actually point to a real address, and the
>>
>> You can't? Whats this then:
>>
>> const char *ptr = "hello world";
>
>That's a string literal, not a compile-time constant. String literals are
>instantiated wherever they are used (like happens here).

Not for pointers. In this case "hello world" is stored in the text portion
of the binary and is at a fixed location from the minute the binary is loaded
into memory and is never instantiated.

>If you have a string literal in a header file, chances are that it will
>be duplicated in every compilation unit where it's used (whether the

Or more likely you'll get a duplicate symbol error unless you declare it
as extern in all but 1 of those units.

>compiler will merge all these instances into one is implementation-defined,
>but in most implementations unlikely to happen).

Thats exactly what will happen:

fenris$ cat t.h
#include <stdio.h>

#ifdef MAIN
const char *ptr = "hello world";
#else
extern const char *ptr;
#endif

fenris$ cat m.c
#define MAIN
#include "t.h"

void func();

int main()
{
printf("main %p\n",ptr);
func();
return 0;
}

fenris$ cat f.c
#include "t.h"

void func()
{
printf("func %p\n",ptr);
}
fenris$ cc m.c f.c
fenris$ ./a.out
main 0x104705f8e
func 0x104705f8e

Paavo Helde

unread,
Jun 26, 2020, 8:19:56 AM6/26/20
to
I think Juha is talking about string content, not pointer values.

If I replace t.h with:

$ cat t.h
#include <stdio.h>
const char * const ptr = "hello world";

with f.c and m.c unchanged, I get different pointers and duplicate strings:

$ g++ m.c f.c

$ ./a.out
main 0x4005f8
func 0x400620

$ strings a.out | grep hello
hello world
hello world

True, adding -O1 or better gets rid of the duplicates, at least with
this g++ (7.4):

gemma: tmp>g++ m.c f.c -O1
gemma: tmp>./a.out
main 0x4005f4
func 0x4005f4
gemma: tmp>strings a.out | grep hello
hello world

already...@yahoo.com

unread,
Jun 26, 2020, 9:30:41 AM6/26/20
to
On Friday, June 26, 2020 at 1:49:33 PM UTC+3, Juha Nieminen wrote:
> already...@yahoo.com wrote:
> > On Thursday, June 25, 2020 at 9:16:06 AM UTC+3, Juha Nieminen wrote:
> >> already...@yahoo.com wrote:
> >> > So, unless I am missing something, in 2020 C++ still has no nice portable syntax for typed constants that can be declared at class==struct scope and don't come in conflict with basic DRY principle.
> >>
> >> You don't seem to understand that you want a *pointer* to such a variable.
> >
> > You don't seem to understand that everything "you understand" about low level things I understand at least as well or better.
>
> I appreciate your humility.
>

You are welcome.

> > What I probably don't understand/know as well as yourself is a "new" C++11/14/17 things.
>
> I don't really understand why you are talking about the new C++ standards
> in this respect. I don't get your point.
>
> Class variables (ie. "static" variables inside the scope of a class) have
> always worked in this manner, all the way since the first standard, C++98
> (and probably for as long as any version of C++ has supported static
> variables inside a class scope). If you declare a class variable, you need
> to tell the compiler where it should instantiate it, because the instance
> must only be found in one compilation unit (if you instantiate it in
> several compilation units you'll get a linker error because of duplicate
> names). It's no different from function definitions.

And in specific case of static const class members (not just integer, but integers are the most obvious) from the perspective of programmer there are absolutely no advantages in enforcing such artificial rules and quite obvious disadvantages (unnecessary violation of DRY).

>
> Somehow you write as if this had changed between C++98 and C++11. It didn't.
>
> C++17 added support for the 'inline' keyword in variables (including
> class variables), which makes them work (from the perspective of the linker)
> in the same way as 'inline' functions have always worked. In other words,
> if the linker finds the same variable signature in more than one
> compilation unit, it's instructed to not give an error about duplicate
> names and instead just take one of them and discard the rest.
>
> > And I expected that it was here since C++03 and without special keyword.
>
> Why are you singling out C++03 in particular? Static variables inside a
> class have *always* worked the same way, since C++98 and prior.
>

С++03 was about fixing non-clear parts of C++98 docs in accordance to best industry practices. I hoped that the case of static const integer data members was among those that was fixed.
Obviously, I was wrong.

I remember that in several pre-standard C++ implementations initialization of any static const data members, even integers, withing class declaration was not allowed.
I don't remember if it became legal in C++98 or somewhat later.
But, from my perspective as programmer, making it legal without immediate simultaneous addition of exception to "one definition rule" is a mistake on part of standard body, the sort of mistake that I expect to not be enforced by quality implementations unless standard *requires* enforcement. Which, according to my understanding, Standard never did.

> > IMHO, the way Microsoft handling it, i.e. things just work, is The Correct Way.
>
> And how exactly does Microsoft handle this?

The general principle is "Compiler and linker cooperate to make life of programmer easier. Making life of compiler developers or especially of linker developers easier is a secondary goal."
As long as it works, I am not interested in details. If it was broken I'd may be dig in.
Looking at asm output, compiler puts static const members in segment called 'CONST'. I suppose that linker knows how to merge multiple identical entries in such segment into a single entry. I did test that it's indeed a single entry in the .exe.
I don't know what would happen when initialization values in different object files does not match each other. Hopefully in this case linker would complain with intelligible message. The situation wouldn't arise, anyway, unless programmer goes crazy with preprocessor.

already...@yahoo.com

unread,
Jun 26, 2020, 9:40:02 AM6/26/20
to
But changing value of "const' static data member variable is UB anyway. So it's not compiler's business to care too much about the outcome.
With elaborate optimization on, the situation can't be made predictable anyway, because compiler is allowed to keep a copy of const data member in register or on local stack across external function invocations. More so, compiler is allowed to use immediate value and to not refer to common storage at all.

already...@yahoo.com

unread,
Jun 26, 2020, 10:00:43 AM6/26/20
to
BTW, I feel that insistence od standard body on not allowing initialization of non-integer static const members within class declaration in this day and age looks more than a little anachronistic.
Both gcc and clang with -std=c++17 allow it to "just work" for 'double' with constexpr. But what is a reason to not allow it for good old 'const'? Is it there some sort of legacy code that I am unable to imagine that would be broken?

bol...@nowhere.co.uk

unread,
Jun 26, 2020, 10:29:42 AM6/26/20
to
On Fri, 26 Jun 2020 15:19:45 +0300
Paavo Helde <ees...@osa.pri.ee> wrote:
>I think Juha is talking about string content, not pointer values.
>
>If I replace t.h with:
>
>$ cat t.h
>#include <stdio.h>
>const char * const ptr = "hello world";
>
>with f.c and m.c unchanged, I get different pointers and duplicate strings:
>
>$ g++ m.c f.c
>
>$ ./a.out
>main 0x4005f8
>func 0x400620

That doesn't happen with Clang on MacOS:

fenris$ cat t.h
#include <stdio.h>

#ifdef MAIN
const char * const ptr = "hello world";
#else
extern const char * const ptr;
#endif

fenris$ cc *.c
fenris$ ./a.out
main 0x10d640f9f
func 0x10d640f9f
fenris$ strings a.out | grep hello
hello world
fenris$

I'm surprised gcc does it, it makes no logical sense. I'll have to try it
next time I'm on a linux box.

Paavo Helde

unread,
Jun 26, 2020, 10:57:01 AM6/26/20
to
26.06.2020 17:29 bol...@nowhere.co.uk kirjutas:
> On Fri, 26 Jun 2020 15:19:45 +0300
> Paavo Helde <ees...@osa.pri.ee> wrote:
>> I think Juha is talking about string content, not pointer values.
>>
>> If I replace t.h with:
>>
>> $ cat t.h
>> #include <stdio.h>
>> const char * const ptr = "hello world";

[...]
> That doesn't happen with Clang on MacOS:
>
> fenris$ cat t.h
> #include <stdio.h>
>
> #ifdef MAIN
> const char * const ptr = "hello world";
> #else
> extern const char * const ptr;
> #endif

I guess this is because your t.h is different than mine.

bol...@nowhere.co.uk

unread,
Jun 26, 2020, 11:14:33 AM6/26/20
to
On Fri, 26 Jun 2020 17:56:51 +0300
Paavo Helde <ees...@osa.pri.ee> wrote:
>26.06.2020 17:29 bol...@nowhere.co.uk kirjutas:
>> On Fri, 26 Jun 2020 15:19:45 +0300
>> Paavo Helde <ees...@osa.pri.ee> wrote:
>>> I think Juha is talking about string content, not pointer values.
>>>
>>> If I replace t.h with:
>>>
>>> $ cat t.h
>>> #include <stdio.h>
>>> const char * const ptr = "hello world";
>
>[...]
>> That doesn't happen with Clang on MacOS:
> >
> > fenris$ cat t.h
> > #include <stdio.h>
> >
> > #ifdef MAIN
> > const char * const ptr = "hello world";
> > #else
> > extern const char * const ptr;
> > #endif
>
>I guess this is because your t.h is different than mine.

There's a good reason for that. If I use yours:

fenris$ cc *.c
duplicate symbol '_ptr' in:
/var/folders/_3/d50cjsnj6gg_0ztqcqmhxlrc0000gn/T/f-ab8317.o
/var/folders/_3/d50cjsnj6gg_0ztqcqmhxlrc0000gn/T/m-457e92.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)



Paavo Helde

unread,
Jun 26, 2020, 11:46:05 AM6/26/20
to
That's because you are using a C compiler. This is a C++ group. Try c++
instead of cc.


bol...@nowhere.co.uk

unread,
Jun 26, 2020, 12:09:04 PM6/26/20
to
On Fri, 26 Jun 2020 18:45:56 +0300
Its the same compiler and AFAIK const <type> const <var> is not a valid C
declaration.

But if you insist:

fenris$ cat t.h
#include <stdio.h>

const char * const ptr = "hello world";
fenris$ c++ *.cc
fenris$ ./a.out
main 0x104109f9f
func 0x104109f9f

Same result. Plus its poor form not to use extern when dealing with multiple
object files since it avoids precisely these sorts of issues.

Juha Nieminen

unread,
Jun 26, 2020, 12:46:29 PM6/26/20
to
bol...@nowhere.co.uk wrote:
>>> const char *ptr = "hello world";
>>
>>That's a string literal, not a compile-time constant. String literals are
>>instantiated wherever they are used (like happens here).
>
> Not for pointers. In this case "hello world" is stored in the text portion
> of the binary and is at a fixed location from the minute the binary is loaded
> into memory and is never instantiated.

First you describe in detail how the string literal is instantiated
and then you say that it's never instantiated.

>>If you have a string literal in a header file, chances are that it will
>>be duplicated in every compilation unit where it's used (whether the
>
> Or more likely you'll get a duplicate symbol error unless you declare it
> as extern in all but 1 of those units.

Not if you declare it as const. In C++ variables at the global or
a namespace scope declared as const have internal linkage.

Paavo Helde

unread,
Jun 26, 2020, 1:30:08 PM6/26/20
to
This is not what we have; we have const <type> * const <var>, which is
legal in both languages, but with subtle differences.

>
> But if you insist:
>
> fenris$ cat t.h
> #include <stdio.h>
>
> const char * const ptr = "hello world";
> fenris$ c++ *.cc
> fenris$ ./a.out
> main 0x104109f9f
> func 0x104109f9f
>
> Same result. Plus its poor form not to use extern when dealing with multiple
> object files since it avoids precisely these sorts of issues.
>

This means your linker performs some optimizations even without -O1.

In C++ namespace-level const variables have internal linkage by default,
extern would mean the opposite. If you printed out &ptr in addition to
ptr values, you would see these are different (at least if the address
of ptr is taken), even though they will point to the same string literal
if the other has been optimized away.

So, in C++ const global variables do not cause linker errors, and any
seemingly duplicate string literals can be easily optimized away by the
linker. No need to complicate your life with 'extern' and conditional
compilation.




bol...@nowhere.co.uk

unread,
Jun 29, 2020, 6:05:38 AM6/29/20
to
On Fri, 26 Jun 2020 16:46:18 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>bol...@nowhere.co.uk wrote:
>>>> const char *ptr = "hello world";
>>>
>>>That's a string literal, not a compile-time constant. String literals are
>>>instantiated wherever they are used (like happens here).
>>
>> Not for pointers. In this case "hello world" is stored in the text portion
>> of the binary and is at a fixed location from the minute the binary is loaded
>
>> into memory and is never instantiated.
>
>First you describe in detail how the string literal is instantiated
>and then you say that it's never instantiated.

Instantiation implies an action at runtime, not binary load time which is
what happens in this case.


Juha Nieminen

unread,
Jun 30, 2020, 2:02:35 AM6/30/20
to
Says who? Instantiation means that the object physically exists at runtime.
If the object never exists, it has never been instantiated.

Ian Collins

unread,
Jun 30, 2020, 2:11:52 AM6/30/20
to
Says the troll who can't count code changes or compile code!

--
Ian.

bol...@nowhere.co.uk

unread,
Jun 30, 2020, 7:02:36 AM6/30/20
to
On Tue, 30 Jun 2020 06:02:23 +0000 (UTC)
So is the machine code in the binary instantiated as well then? Instantiation
means run time creation, not simply what the loader copied into memory before
a single CPU instruction of the program has been run.

Juha Nieminen

unread,
Jun 30, 2020, 12:17:10 PM6/30/20
to
bol...@nowhere.co.uk wrote:
> So is the machine code in the binary instantiated as well then?

In this sense, yes. As opposed to the compiler evaluating the
program at compile time and simply using the end result of the
calculations (which is quite common especially nowadays with
constexpr functions).

If a constexpr function is evaluated at compile time and only
its end result ends up being used, then you could say that the
function was never instantiated. If the function gets compiled
into the binary and thus actually exists there at runtime, then
it got instantiated.

Data or code, it works very similary.

> Instantiation
> means run time creation, not simply what the loader copied into memory before
> a single CPU instruction of the program has been run.

And where are you getting this weird definition from?

bol...@nowhere.co.uk

unread,
Jul 1, 2020, 5:42:33 AM7/1/20
to
The process is instantiated, hard coded text sections are simply part of that,
they are not instantiated in their own right. That happens to runtime created
objects. Otherwise you might as well say a class is instantiated just by dint
of it existing in the code even before an object has been created from it.

Here's an idea - how about you stick to giving vocabulary lessons in Finnish
or Estonian or whatever your native language is, and leave native English
speakers like me to define what the words in our language mean.

Juha Nieminen

unread,
Jul 1, 2020, 1:40:25 PM7/1/20
to
bol...@nowhere.co.uk wrote:
> The process is instantiated, hard coded text sections are simply part of that,
> they are not instantiated in their own right. That happens to runtime created
> objects. Otherwise you might as well say a class is instantiated just by dint
> of it existing in the code even before an object has been created from it.

"Existing in the code"? You mean the source code?

I am precisely making the distinction between compile-time constructs
and runtime constructs. Source code, such as class declarations, are
compile-time constructs. The class declaration itself doesn't exist
at runtime. The data inside of the class may be instantiated as a
data structure.

Which one of these are, in your opinion, instantiations of a given
class, and which ones aren't?

static const MyClass obj1;
static MyClass obj2;

void foo()
{
static MyClass obj3;
MyClass obj4;
MyClass* obj5 = new MyClass;
}

> Here's an idea - how about you stick to giving vocabulary lessons in Finnish
> or Estonian or whatever your native language is, and leave native English
> speakers like me to define what the words in our language mean.

Here's a better idea: Why don't you go and fuck yourself?

Öö Tiib

unread,
Jul 1, 2020, 2:31:54 PM7/1/20
to
Deliberate failure to comprehend the question noted. Language where
rubbish can't be expressed has not been invented yet. So, boltar, you
are offal regardless of what language you can or can not speak.


bol...@nowhere.co.uk

unread,
Jul 2, 2020, 5:10:56 AM7/2/20
to
On Wed, 1 Jul 2020 17:40:08 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>bol...@nowhere.co.uk wrote:
>> The process is instantiated, hard coded text sections are simply part of
>that,
>> they are not instantiated in their own right. That happens to runtime created
>
>> objects. Otherwise you might as well say a class is instantiated just by dint
>
>> of it existing in the code even before an object has been created from it.
>
>"Existing in the code"? You mean the source code?
>

I give up, I'm not sure how much clearer I can be.

>> Here's an idea - how about you stick to giving vocabulary lessons in Finnish
>> or Estonian or whatever your native language is, and leave native English
>> speakers like me to define what the words in our language mean.
>
>Here's a better idea: Why don't you go and fuck yourself?

Sama sinulle kusipää

bol...@nowhere.co.uk

unread,
Jul 2, 2020, 5:12:31 AM7/2/20
to
I can speak French quite well but I wouldn't dream of going on a French group
and arguing the toss over the definition of a french word. So go do one you
self important prick.


Öö Tiib

unread,
Jul 2, 2020, 11:15:20 AM7/2/20
to
Whatever you do in your French or English groups is irrelevant and your
accusation of me arguing over definition of word "instantiation" in
English is groundless *and* nonsense.

I only noted your failure to comprehend a question and your failure
to cite from where are you getting your definition as answer. So I
diagnosed you as a piece of offal based on that.

bol...@nowhere.co.uk

unread,
Jul 2, 2020, 11:23:12 AM7/2/20
to
*yawn* Someone wake me up when the record changes. Zzzzzz....

Vir Campestris

unread,
Jul 2, 2020, 4:55:11 PM7/2/20
to
On 01/07/2020 10:42, bol...@nowhere.co.uk wrote:
> The process is instantiated, hard coded text sections are simply part of that,
> they are not instantiated in their own right. That happens to runtime created
> objects. Otherwise you might as well say a class is instantiated just by dint
> of it existing in the code even before an object has been created from it.
>

When you instantiate a class you make an object of that class.

Sometimes this is done at compile time.

> Here's an idea - how about you stick to giving vocabulary lessons in Finnish
> or Estonian or whatever your native language is, and leave native English
> speakers like me to define what the words in our language mean.

And in this case the meaning of instantiate is the meaning defined in
the C++ language standard, not the one you'd find in an English
dictionary. I'd trust Juha on the former, not the latter.

Andy

Keith Thompson

unread,
Jul 2, 2020, 5:12:15 PM7/2/20
to
Vir Campestris <vir.cam...@invalid.invalid> writes:
[...]
> When you instantiate a class you make an object of that class.
>
> Sometimes this is done at compile time.

Are you saying that, for example given this:

class Foo { int n; };
Foo obj;

creating the object "obj" *instantiates" the class "Foo"? Where does
the C++ standard say this? (I accept that the word can be used
informally in this way.)

And do you have an example of an object being created at compile time?
I'd describe that as the compiler generating code that causes the object
to be created at run time (possibly while the program is being loaded).

[...]
>
> And in this case the meaning of instantiate is the meaning defined in
> the C++ language standard, not the one you'd find in an English
> dictionary. I'd trust Juha on the former, not the latter.

In a quick look through the C++ standard, I don't see a formal
definition of "instantiate". It does use the word, but usually in
reference to templates. Do you have a specific citation of the word
"instantiate" being used this way?

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Juha Nieminen

unread,
Jul 3, 2020, 2:53:38 AM7/3/20
to
Keith Thompson <Keith.S.T...@gmail.com> wrote:
> In a quick look through the C++ standard, I don't see a formal
> definition of "instantiate".

Which actually makes that other guy's attempt at nitpicking about the
definition of the word even mor ridiculous, given that there's no
official definition. It's especially ridiculous that he tries to
allude to the English language for this, given that no English
dictionary defines "instantiate" in terms of a particular programming
language like C++.

I would argue that pretty much universally it's agreed that when a type
is "instantiated" it means that now some concrete values corresponding to
that abstract type exist in memory somewhere (where they can be eg read,
or a pointer/reference can be created that points to them).

(Of course in the case of templates the word "instantiate" has a slightly
different meaning, as you point out is used in the standard as well.
Although, even in this case it's not *that* dissimilar: An abstract
declaration of types and/or code is made concrete, usually by instantiating
types types and/or code in the first sense above, so they become actual
data that ends up in memory somewhere.)

I don't think anybody makes the distinction of eg. "instantiating a class"
into data that ends up somewhere in the executable binary file itself,
or at runtime in a manner that ends up somewhere on the heap or stack.
In both situations "instantiating" is merely the act of creating actual
concrete values that reside somewhere, from an abstract type (or code)
declaration.

Öö Tiib

unread,
Jul 3, 2020, 4:46:12 AM7/3/20
to
Correction. Piece of drowsy offal.

Öö Tiib

unread,
Jul 3, 2020, 7:18:31 AM7/3/20
to
On Friday, 3 July 2020 00:12:15 UTC+3, Keith Thompson wrote:
>
> In a quick look through the C++ standard, I don't see a formal
> definition of "instantiate". It does use the word, but usually in
> reference to templates. Do you have a specific citation of the word
> "instantiate" being used this way?

"Instantiation" used about objects in C++ has to be informal
simplification. It perhaps originates from programming language
like Java where there is only one kind of storage (not four),
constness of objects is not language feature, compile time
processing is not language feature, end of life-time of object is
never under control of programmer, storage can never be reused,
objects have to be always initialised in same step of allocation
of storage and so on. In C++ it is cheap way for troll like boltar
to confuse all discussion into nonsense with argument that there
is some kind of special formal meaning of it.

bol...@nowhere.co.uk

unread,
Jul 3, 2020, 7:22:12 AM7/3/20
to
On Thu, 2 Jul 2020 21:55:02 +0100
Vir Campestris <vir.cam...@invalid.invalid> wrote:
>On 01/07/2020 10:42, bol...@nowhere.co.uk wrote:
>> The process is instantiated, hard coded text sections are simply part of
>that,
>> they are not instantiated in their own right. That happens to runtime created
>
>> objects. Otherwise you might as well say a class is instantiated just by dint
>
>> of it existing in the code even before an object has been created from it.
>>
>
>When you instantiate a class you make an object of that class.
>
>Sometimes this is done at compile time.

No, it isn't. Unless you think the binary comes with its own heap and stack.
Go disassemble one and have a look.

bol...@nowhere.co.uk

unread,
Jul 3, 2020, 7:22:55 AM7/3/20
to
On Fri, 3 Jul 2020 01:46:00 -0700 (PDT)
=?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>On Thursday, 2 July 2020 18:23:12 UTC+3, bol...@nowhere.co.uk wrote:
>> On Thu, 2 Jul 2020 08:14:55 -0700 (PDT)
>> =?UTF-8?B?w5bDtiBUaWli?= <oot...@hot.ee> wrote:
>> >I only noted your failure to comprehend a question and your failure
>> >to cite from where are you getting your definition as answer. So I
>> >diagnosed you as a piece of offal based on that.
>>
>> *yawn* Someone wake me up when the record changes. Zzzzzz....
>
>Correction. Piece of drowsy offal.

I've been called a lot worse by people far better at insults than you.

bol...@nowhere.co.uk

unread,
Jul 3, 2020, 7:28:48 AM7/3/20
to
Ah ok, I'm a troll for not agreeing with you and Mr Fin. So if there's no
formal meaning then you one can use any meaning one wants so therefor this
discussion is over. Right?

already...@yahoo.com

unread,
Jul 3, 2020, 7:46:22 AM7/3/20
to
As originator of the thread I do think that the faster this particular branch of discussion is over, the better for most of us.

Öö Tiib

unread,
Jul 3, 2020, 7:52:59 AM7/3/20
to
Bullshit. I did not use nor argue about any meaning of it. You claimed
it has meaning: "instantiation means run time creation" and you failed
to show from what dictionary or standard that garbage come from.

bol...@nowhere.co.uk

unread,
Jul 3, 2020, 7:55:46 AM7/3/20
to
On Fri, 3 Jul 2020 04:52:47 -0700 (PDT)
So you're not arguing over the meaning of it but my definition is apparently
"garbage". I'll let you go and have a little think about how you managed to
contradict yourself there. Well done.

Öö Tiib

unread,
Jul 3, 2020, 7:59:16 AM7/3/20
to
Everything utterly groundless is garbage. And utter groundlessness is
shown by your failure to provide any ground.

Paavo Helde

unread,
Jul 3, 2020, 11:53:06 AM7/3/20
to
I think we have figured out this many years ago. An object in C++ is a
region of memory. This means it has an address and size.

As soon as the binary image is loaded into the process address space,
any region in it which corresponds to a C++ object obtains a memory
address, so by then it's an object there. Loading the binary into memory
is a run-time activity (esp. with dynamically loaded libs), so this even
matches boltar's definition.

And no, heap and stack are not the only places where C++ objects can reside.

bol...@nowhere.co.uk

unread,
Jul 3, 2020, 11:58:39 AM7/3/20
to
On Fri, 3 Jul 2020 04:59:06 -0700 (PDT)
I can lend you a nice spade to help you dig that hole even deeper if you like.

bol...@nowhere.co.uk

unread,
Jul 3, 2020, 12:07:00 PM7/3/20
to
Sure, you could hide them away in shared memory or somewhere similar but the
point is they do NOT exist in the binary. The class definition is NOT an object
and instantiating the process does not create any objects until instantiation
code has been run whether its explicit user code or compiler generated start up.

Chris Vine

unread,
Jul 3, 2020, 2:33:05 PM7/3/20
to
I think most people already realized that.

Juha Nieminen

unread,
Jul 3, 2020, 3:23:10 PM7/3/20
to
bol...@nowhere.co.uk wrote:
>>> >Bullshit. I did not use nor argue about any meaning of it. You claimed
>>> >it has meaning: "instantiation means run time creation" and you failed
>>> >to show from what dictionary or standard that garbage come from.
>>>
>>> So you're not arguing over the meaning of it but my definition is apparently
>>> "garbage". I'll let you go and have a little think about how you managed to
>>> contradict yourself there. Well done.
>>
>>Everything utterly groundless is garbage. And utter groundlessness is
>>shown by your failure to provide any ground.
>
> I can lend you a nice spade to help you dig that hole even deeper if you like.

I just love your projection there. It's quite clear that this isn't
the first time you have got yourself into this kind of situation,
and you have learned from your previous battles the concepts and
terminology that people use against you, and now you are just
throwing those same terms against others because you think that
if they work against you, surely they will work against others
if you use them.

Words, expressions and accusations have a meaning, and if you use them
in a context that doesn't apply, it just makes you sound foolish.

Perhaps some time in the future, ten or twenty years from now, when
you have grown and wisened up a bit, you'll understand that it's
better even for your own sake to just concede when you make an error
rather than trying stubborningly and uselessly to win the argument
at any cost. Perhaps you'll understand that not only is it useless,
but in fact detrimental for your own reputation to try to win an
empty victory at any cost, over such a trivial thing as the meaning
of a word.

You know why they make a comparison between a flamewar and the special
olympics?

Juha Nieminen

unread,
Jul 3, 2020, 3:26:42 PM7/3/20
to
bol...@nowhere.co.uk wrote:
> Sure, you could hide them away in shared memory or somewhere similar but the
> point is they do NOT exist in the binary. The class definition is NOT an object
> and instantiating the process does not create any objects until instantiation
> code has been run whether its explicit user code or compiler generated start up.

How many conditions are you going to add for this personal definition
of yours?

I noticed earlier that you didn't answer my question. Is this
instantiating a class or not?

static const MyClass obj;

Chris M. Thomasson

unread,
Jul 3, 2020, 3:58:16 PM7/3/20
to
Check this out... I need a static node to use its address for the wait
state of special atomic stack experiment. This node needs to be able to
have its address taken... Here is the code. It should work, it calls a
constructor. Any thoughts?

_____________________________
#include <iostream>
#include <atomic>
#include <thread>


struct user_payload
{
int m_foo;

user_payload(int foo) : m_foo(foo) {}

user_payload(const user_payload& rhs) : m_foo(rhs.m_foo) {}

void process()
{
std::cout << this << "->user_payload::process() " << m_foo << "\n";
std::this_thread::yield();
}
};


namespace ct
{

static struct node* node_wait_next(node*);

struct node
{
std::atomic<node*> m_next;
user_payload m_payload;


node(user_payload const& payload) : m_next(nullptr),
m_payload(payload)
{
std::cout << this << "->node::node()" << "\n";
}

~node()
{
std::cout << this << "->node::~node()" << "\n";
}


static void process(node* head)
{
node* cur = head;

while (cur)
{
// user processing first!
cur->m_payload.process();

// now, we see if we need to wait...
node* next = node_wait_next(cur);

delete cur;

cur = next;
}
}
};


static node g_special_wait_node(0);


#define CT_SPECIAL (&ct::g_special_wait_node)


node* node_wait_next(node* n)
{
node* next = nullptr;
while ((next = n->m_next.load(std::memory_order_relaxed))
== CT_SPECIAL) std::this_thread::yield();
return next;
}

struct stack
{
std::atomic<node*> m_head;

stack() : m_head(nullptr) {}

void push(node* n)
{
n->m_next.store(CT_SPECIAL, std::memory_order_relaxed);
node* prev = m_head.exchange(n, std::memory_order_release);
n->m_next.store(prev, std::memory_order_relaxed);
}


node* flush()
{
return m_head.exchange(nullptr, std::memory_order_acquire);
}
};
}


int main()
{
std::cout << "\nCT_SPECIAL = " << CT_SPECIAL << "\n\n";

{
ct::stack alist;

alist.push(new ct::node(789));
alist.push(new ct::node(456));
alist.push(new ct::node(123));

ct::node* work = alist.flush();

ct::node::process(work);


alist.push(new ct::node(321));
alist.push(new ct::node(654));
alist.push(new ct::node(987));

work = alist.flush();

ct::node::process(work);
}

return 0;
}
_____________________________


Does it work for you?

Mr Flibble

unread,
Jul 3, 2020, 6:56:41 PM7/3/20
to
An object is an instantiation of a type, e.g.

int i = 42; // i is an object being instantiation (i.e. an instance) of the type int.

/Flibble

--
"Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin

“You won’t burn in hell. But be nice anyway.” – Ricky Gervais

“I see Atheists are fighting and killing each other again, over who doesn’t believe in any God the most. Oh, no..wait.. that never happens.” – Ricky Gervais

"Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say."

Ian Collins

unread,
Jul 4, 2020, 4:12:33 AM7/4/20
to
On 03/07/2020 23:59, Öö Tiib wrote:
>
> Everything utterly groundless is garbage. And utter groundlessness is
> shown by your failure to provide any ground.

Never wrestle with a pig. You just get dirty and the pig enjoys it.

--
Ian.

Chris M. Thomasson

unread,
Jul 4, 2020, 4:36:31 AM7/4/20
to
The worst is when the pig beats you at it!

bol...@nowhere.co.uk

unread,
Jul 6, 2020, 3:00:17 PM7/6/20
to
On Fri, 3 Jul 2020 19:22:59 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>bol...@nowhere.co.uk wrote:
>>>> >Bullshit. I did not use nor argue about any meaning of it. You claimed
>>>> >it has meaning: "instantiation means run time creation" and you failed
>>>> >to show from what dictionary or standard that garbage come from.
>>>>
>>>> So you're not arguing over the meaning of it but my definition is
>apparently
>>>> "garbage". I'll let you go and have a little think about how you managed to
>
>>>> contradict yourself there. Well done.
>>>
>>>Everything utterly groundless is garbage. And utter groundlessness is
>>>shown by your failure to provide any ground.
>>
>> I can lend you a nice spade to help you dig that hole even deeper if you
>like.
>
>I just love your projection there. It's quite clear that this isn't

Thank you. Welcome back, took you long enough to think up a riposte. Shame
it wasn't worth the effort.

bol...@nowhere.co.uk

unread,
Jul 6, 2020, 3:02:49 PM7/6/20
to
Yes. And obj doesn't exist until the binary is loaded and the instatiation
code is run. Whats your point? MyClass exists in the binary, obj does not.

Juha Nieminen

unread,
Jul 6, 2020, 5:27:48 PM7/6/20
to
bol...@nowhere.co.uk wrote:
>>I just love your projection there. It's quite clear that this isn't
>
> Thank you. Welcome back, took you long enough to think up a riposte. Shame
> it wasn't worth the effort.

While I'm certain you only read like first two or three lines of my
post and skipped the rest and hurried to post something just to have
the final word, I still think that you may yet grow up and learn
in the next 10 to 20 years. You may not want to believe it right now,
but it may well happen.

Meanwhile, just a word of advice: Just give up, for your own sake.
Stop digging the hole deeper. You are not going to "win" anything.
Just stop.

Juha Nieminen

unread,
Jul 6, 2020, 5:30:22 PM7/6/20
to
The compiler may well make that into a data in the text section of the
binary (because it's const), depending on how exactly that class is
implemented. Meaning it won't create the object at runtime, but it will
be data in the executable binary itself.

Or if it's implemented in another manner, it may well create code that
initializes it at runtime (and eg. does memory allocations or whatever).

So, is it instantiated in both cases or not?

Paavo Helde

unread,
Jul 6, 2020, 6:23:30 PM7/6/20
to
MyClass definitely does not exist in the binary. Classes are
compile-time concept and are not present in the generated binary, in
C++. There is no data structure in the generated binary representing the
class. At most you will have a typeid tag for RTTI, but this is just a
simple identification tag. There are proposals to add reflection to C++
which would mean a bit more presence of classes in binary, but AFAIK
these have not yet materialized.

I agree with you that the object does not exist before the binary is
loaded, as before loading it does not have an address in the program
memory space.

Juha Nieminen

unread,
Jul 7, 2020, 2:23:15 AM7/7/20
to
Paavo Helde <ees...@osa.pri.ee> wrote:
> I agree with you that the object does not exist before the binary is
> loaded, as before loading it does not have an address in the program
> memory space.

But his argument is that if the object is in the executable binary file,
put into RAM alongside the executable binary itself at load time, then
it's not "instantiated". It exists in RAM, with a physical address which
you can point to, but it was never "instantiated".

bol...@nowhere.co.uk

unread,
Jul 7, 2020, 3:59:14 AM7/7/20
to
On Mon, 6 Jul 2020 21:30:13 +0000 (UTC)
The person making the assertion is the one who has to prove it, its not up
to others to disprove it. Get back to us when you're done.

bol...@nowhere.co.uk

unread,
Jul 7, 2020, 4:01:16 AM7/7/20
to
The class memory layout has to be stored in some form somewhere in the binary
otherwise on the fly objects could never be created.

Keith Thompson

unread,
Jul 7, 2020, 4:27:27 AM7/7/20
to
Since there's no agreed definition of "instantiated", I expect the
argument will never be resolved. (Which is fine with me.)

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Juha Nieminen

unread,
Jul 7, 2020, 11:11:32 AM7/7/20
to
bol...@nowhere.co.uk wrote:
>>The compiler may well make that into a data in the text section of the
>>binary (because it's const), depending on how exactly that class is
>>implemented. Meaning it won't create the object at runtime, but it will
>>be data in the executable binary itself.
>>
>>Or if it's implemented in another manner, it may well create code that
>>initializes it at runtime (and eg. does memory allocations or whatever).
>>
>>So, is it instantiated in both cases or not?
>
> The person making the assertion is the one who has to prove it, its not up
> to others to disprove it. Get back to us when you're done.

Prove what?

I asked a *question*. If the compiler makes the object into what
essentially amounts to a literal that exists in the executable
binary, is that instantiating the class or not?

And yes, the compiler does that with certain classes. It's no
different from eg. creating a const array of ints at the global
scope.

It just sounds to me that you are now trying to dodge the question,
not having to answer it. Probably even you don't know why.

Juha Nieminen

unread,
Jul 7, 2020, 11:15:52 AM7/7/20
to
bol...@nowhere.co.uk wrote:
> The class memory layout has to be stored in some form somewhere in the binary
> otherwise on the fly objects could never be created.

Not, it doesn't necessarily.

If the class consists of eg. just integers and they are all
default-initialized or zero-initialized, the compiler could
just as well create code that allocates space for that many
integers and do effectively a memset() on that memory block
to zero it. Any code that accesses the members just use
offsets from the beginning of that memory block.

The actual layout isn't specifically stored separately anywhere.
The only place where the layout has effect is in any code that
accesses the members (and there it's in the form of offsets from
the beginning of the memory block). There may be numerous functions
that access the members in this way, so there isn't one single
unified place where this layout is "stored" in the binary.

Manfred

unread,
Jul 7, 2020, 2:38:31 PM7/7/20
to
On 7/7/2020 10:01 AM, bol...@nowhere.co.uk wrote:
> The class memory layout has to be stored in some form somewhere in the binary
> otherwise on the fly objects could never be created.

Yes, they can. It is called construction.

Paavo Helde

unread,
Jul 7, 2020, 5:16:33 PM7/7/20
to
Right, that's why it is not possible in C++ to construct classes at run
time and to create objects from them "on the fly". The compiled code
accesses object members at fixed offsets which are hardcoded in the code
and not looked up anywhere at run time.

Of course one can implement in C++ a new (scripting) language which does
exactly such things as dynamic class building, but those would then be
classes and objects of that new language, not of C++.

bol...@nowhere.co.uk

unread,
Jul 8, 2020, 5:05:47 AM7/8/20
to
On Tue, 7 Jul 2020 15:15:41 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>bol...@nowhere.co.uk wrote:
>> The class memory layout has to be stored in some form somewhere in the binary
>
>> otherwise on the fly objects could never be created.
>
>Not, it doesn't necessarily.
>
>If the class consists of eg. just integers and they are all
>default-initialized or zero-initialized, the compiler could
>just as well create code that allocates space for that many
>integers and do effectively a memset() on that memory block
>to zero it. Any code that accesses the members just use
>offsets from the beginning of that memory block.

I was using "stored" in a rather liberal sense. I didn't mean it had to be
some kind of lookup table but if you have

struct mystruct
{
int i;
char c;
short s[5];
int j;
};

then the binary needs to be aware that (assuming no padding) s is 5 bytes
away from i in the memory and j is 10 bytes away however that awareness is
stored internally.


bol...@nowhere.co.uk

unread,
Jul 8, 2020, 5:06:04 AM7/8/20
to
Whoooosh....

bol...@nowhere.co.uk

unread,
Jul 8, 2020, 5:07:27 AM7/8/20
to
On Wed, 8 Jul 2020 00:16:21 +0300
Paavo Helde <ees...@osa.pri.ee> wrote:
>07.07.2020 11:01 bol...@nowhere.co.uk kirjutas:
>> On Tue, 7 Jul 2020 01:20:45 +0300
>> Paavo Helde <ees...@osa.pri.ee> wrote:
>>> MyClass definitely does not exist in the binary. Classes are
>>> compile-time concept and are not present in the generated binary, in
>>> C++. There is no data structure in the generated binary representing the
>>
>> The class memory layout has to be stored in some form somewhere in the binary
>
>> otherwise on the fly objects could never be created.
>>
>
>Right, that's why it is not possible in C++ to construct classes at run
>time and to create objects from them "on the fly". The compiled code
>accesses object members at fixed offsets which are hardcoded in the code
>and not looked up anywhere at run time.

And the difference between memory layout being stored and hardcoded offsets
is.... what exactly?

Juha Nieminen

unread,
Jul 8, 2020, 5:25:32 AM7/8/20
to
would imply that classes can only be instantiated if their exact internal
structure is known, else it's impossible.

As mentioned, that's not necessarily the case. For example, if the class
consists only of integer variables, for instance, which are all
zero-initialized or default-initialized, it can be instantiated by
knowing the size of the class, with no knowledge of its internal
structure. (If it's completely zero-initialized, then what amounts
to a single memset() call can be used to initialize it.)

No code in the program might access every single member variable of that
class, which means that only some of the offsets will be stored in code,
not all of them. This means that even by the loosest possible definition
of "storing the memory layout of the class", it would only have been
"stored" partially, not fully, yet that doesn't make it impossible to
instantiate.

For example, maybe the class has 20 integer member variables, but this
particular program only accesses the first one of them, ignoring the
rest. This means that, effectively, the program only accesses the
very first value in the class. None of the rest of the internal
structure of the class is stored anywhere in the code, in any way.
Yet that doesn't make it impossible to instantiate the class.

Paavo Helde

unread,
Jul 8, 2020, 8:28:59 AM7/8/20
to
The difference is in how easy is to access that information. For
starters, write a function which will take a pointer to any class object
and print out its class definition. This can be done quite easily in
some other languages.

bol...@nowhere.co.uk

unread,
Jul 8, 2020, 11:01:34 AM7/8/20
to
On Wed, 8 Jul 2020 09:25:19 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>bol...@nowhere.co.uk wrote:
>> On Wed, 8 Jul 2020 00:16:21 +0300
>> Paavo Helde <ees...@osa.pri.ee> wrote:
>>>07.07.2020 11:01 bol...@nowhere.co.uk kirjutas:
>>>> On Tue, 7 Jul 2020 01:20:45 +0300
>>>> Paavo Helde <ees...@osa.pri.ee> wrote:
>>>>> MyClass definitely does not exist in the binary. Classes are
>>>>> compile-time concept and are not present in the generated binary, in
>>>>> C++. There is no data structure in the generated binary representing the
>>>>
>>>> The class memory layout has to be stored in some form somewhere in the
>binary
>>>
>>>> otherwise on the fly objects could never be created.
>>>>
>>>
>>>Right, that's why it is not possible in C++ to construct classes at run
>>>time and to create objects from them "on the fly". The compiled code
>>>accesses object members at fixed offsets which are hardcoded in the code
>>>and not looked up anywhere at run time.
>>
>> And the difference between memory layout being stored and hardcoded offsets
>> is.... what exactly?
>
>"otherwise on the fly objects could never be created"
>
>would imply that classes can only be instantiated if their exact internal
>structure is known, else it's impossible.

It doesn't imply anything of the sort. However the binary needs some
representation of the class and if not stripped it'll also contain the function
and attribute names too otherwise debuggers wouldn't work.

bol...@nowhere.co.uk

unread,
Jul 8, 2020, 11:03:15 AM7/8/20
to
On Wed, 8 Jul 2020 15:28:46 +0300
In interpreted languages like python anything is possible because their
object format isn't constrained by the OS executable format but if the
language is compiled down to a binary there are limitations on what can be
stored in the binary unless the OS supports it. Eg MacOS supports a large
amount of exe metadata.

Juha Nieminen

unread,
Jul 9, 2020, 3:26:02 AM7/9/20
to
bol...@nowhere.co.uk wrote:
>>>>> The class memory layout has to be stored in some form somewhere in the
>>binary
>>>>> otherwise on the fly objects could never be created.
>>>
>>> And the difference between memory layout being stored and hardcoded offsets
>>> is.... what exactly?
>>
>>"otherwise on the fly objects could never be created"
>>
>>would imply that classes can only be instantiated if their exact internal
>>structure is known, else it's impossible.
>
> It doesn't imply anything of the sort.

There's no way of interpreting "the class memory layout has to be stored in some
form somewhere in the binary otherwise on the fly objects could never be created"
other than that it's impossible to instantiate a class at runtime if its
exact internal structure is not known.

The exactly layout is not always needed. The only two things you need in certain
cases are 1) the size of the class, and 2) the offsets of the member variables
in whatever code is accessing those variables.

Requirement 2 does not necessarily need to encode the offsets of *all* the
member variables, if not all of them are ever accessed.

> However the binary needs some
> representation of the class and if not stripped it'll also contain the function
> and attribute names too otherwise debuggers wouldn't work.

Now you are bringing up debuggers, which have absolutely nothing to do with your
original assertion. How big will the pileup become?

Bo Persson

unread,
Jul 9, 2020, 4:30:04 AM7/9/20
to
On 2020-07-09 at 09:25, Juha Nieminen wrote:
> bol...@nowhere.co.uk wrote:

>> However the binary needs some
>> representation of the class and if not stripped it'll also contain the function
>> and attribute names too otherwise debuggers wouldn't work.
>
> Now you are bringing up debuggers, which have absolutely nothing to do with your
> original assertion. How big will the pileup become?
>

Stripping symbols is a Linux thing, nothing C++ specific. Other systems
store the debug info in a separate database, and not in the binary.


Bo Persson

bol...@nowhere.co.uk

unread,
Jul 9, 2020, 4:45:49 AM7/9/20
to
Yes, we know how primitive Windows is in a number of respects.

bol...@nowhere.co.uk

unread,
Jul 9, 2020, 4:48:21 AM7/9/20
to
If you're not able to follow a thread maybe keep out of it. I'm honestly
tired of arguing with you over trivial that should be fucking obvious.

Bo Persson

unread,
Jul 9, 2020, 5:41:38 AM7/9/20
to
Now the "primitive" way of doing this proves that the binary doesn't
have to contain all the info. Contrary to some claims.

And the code still works the same when the debug database is not present.


Bo Person

Juha Nieminen

unread,
Jul 9, 2020, 9:01:53 AM7/9/20
to
bol...@nowhere.co.uk wrote:
>>> However the binary needs some
>>> representation of the class and if not stripped it'll also contain the
>>function
>>> and attribute names too otherwise debuggers wouldn't work.
>>
>>Now you are bringing up debuggers, which have absolutely nothing to do with
>>your
>>original assertion. How big will the pileup become?
>
> If you're not able to follow a thread maybe keep out of it. I'm honestly
> tired of arguing with you over trivial that should be fucking obvious.

Ah, the ultimate concession of defeat, when you have no response.

It only lacks calling me a "beginner programmer" or something.

bol...@nowhere.co.uk

unread,
Jul 9, 2020, 1:34:13 PM7/9/20
to
On Thu, 9 Jul 2020 11:41:25 +0200
Bo Persson <b...@bo-persson.se> wrote:
>On 2020-07-09 at 10:45, bol...@nowhere.co.uk wrote:
>> On Thu, 9 Jul 2020 10:29:52 +0200
>> Bo Persson <b...@bo-persson.se> wrote:
>>> On 2020-07-09 at 09:25, Juha Nieminen wrote:
>>>> bol...@nowhere.co.uk wrote:
>>>
>>>>> However the binary needs some
>>>>> representation of the class and if not stripped it'll also contain the
>>> function
>>>>> and attribute names too otherwise debuggers wouldn't work.
>>>>
>>>> Now you are bringing up debuggers, which have absolutely nothing to do with
>
>>> your
>>>> original assertion. How big will the pileup become?
>>>>
>>>
>>> Stripping symbols is a Linux thing, nothing C++ specific. Other systems
>>> store the debug info in a separate database, and not in the binary.
>>
>> Yes, we know how primitive Windows is in a number of respects.
>>
>
>Now the "primitive" way of doing this proves that the binary doesn't
>have to contain all the info. Contrary to some claims.

No, but Visual Shitshow has to generate a seperate file which you then have
to remember to cart around if you wish to debug in situ. Just what you want
when you're deploying to N machines.

>And the code still works the same when the debug database is not present.

Wow, amazing, truly tech from the future.

bol...@nowhere.co.uk

unread,
Jul 9, 2020, 1:36:30 PM7/9/20
to
If you don't understand what debuggers and class attribute and method names
stored in binary files have to do with what I was talking about then either
you're a troll or a complete moron. Take your pick.

Mr Flibble

unread,
Jul 9, 2020, 1:48:55 PM7/9/20
to
A binary executable does NOT contain any type information whatsoever: it merely contains data in the data segment and text in the text segment. A C++ program and a C program could produce exactly the same text segment(s) after compiling and linking completely different source code.

You adding debug information to your argument is a just a case of you shifting the goalposts as you have lost the argument.

/Flibble

--
"Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin

“You won’t burn in hell. But be nice anyway.” – Ricky Gervais

“I see Atheists are fighting and killing each other again, over who doesn’t believe in any God the most. Oh, no..wait.. that never happens.” – Ricky Gervais

"Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say."

bol...@nowhere.co.uk

unread,
Jul 9, 2020, 2:00:41 PM7/9/20
to
On Thu, 9 Jul 2020 18:48:43 +0100
Mr Flibble <flibbleREM...@i42.co.uk> wrote:
>On 09/07/2020 18:36, bol...@nowhere.co.uk wrote:
>> On Thu, 9 Jul 2020 13:01:38 +0000 (UTC)
>> Juha Nieminen <nos...@thanks.invalid> wrote:
>>> bol...@nowhere.co.uk wrote:
>>>>>> However the binary needs some
>>>>>> representation of the class and if not stripped it'll also contain the
>>>>> function
>>>>>> and attribute names too otherwise debuggers wouldn't work.
>>>>>
>>>>> Now you are bringing up debuggers, which have absolutely nothing to do
>with
>>>>> your
>>>>> original assertion. How big will the pileup become?
>>>>
>>>> If you're not able to follow a thread maybe keep out of it. I'm honestly
>>>> tired of arguing with you over trivial that should be fucking obvious.
>>>
>>> Ah, the ultimate concession of defeat, when you have no response.
>>>
>>> It only lacks calling me a "beginner programmer" or something.
>>
>> If you don't understand what debuggers and class attribute and method names
>> stored in binary files have to do with what I was talking about then either
>> you're a troll or a complete moron. Take your pick.
>
>A binary executable does NOT contain any type information whatsoever: it

I didn't say type information, I said names. You might want to try learning
to read.

>You adding debug information to your argument is a just a case of you shifting
>the goalposts as you have lost the argument.

My argument is that class layouts are stored in some form in the binary. Is
that true or false? If its false then explain how objects are created on the
fly. Take your time.

Mr Flibble

unread,
Jul 9, 2020, 2:12:45 PM7/9/20
to
A class layout would be akin to meta data which would be akin to type information and as I have already indicated text segments contain no type information WHATSOEVER. Now you have to use your brain and workout what really constitutes an object in a running program. Take all the time you need.

bol...@nowhere.co.uk

unread,
Jul 9, 2020, 2:38:42 PM7/9/20
to
On Thu, 9 Jul 2020 19:12:32 +0100
I noticed you didn't explain anything. Perhaps you don't know.

Mr Flibble

unread,
Jul 9, 2020, 2:44:18 PM7/9/20
to
It is obvious to all that you certainly don't know. Here is a clue to help you in your quest: The C++ Abstract Machine and the final running executable ARE NOT THE SAME THING. Good luck.

Juha Nieminen

unread,
Jul 9, 2020, 3:14:23 PM7/9/20
to
bol...@nowhere.co.uk wrote:
> If you don't understand what debuggers and class attribute and method names
> stored in binary files have to do with what I was talking about then either
> you're a troll or a complete moron. Take your pick.

I actually know exactly what you are doing, because I have seen it
many, many times. I have frequenting usenet since the mid-90's,
and believe me I have seen a lot during that time.

What you are doing there is trying to hide your mistake by moving
goalposts and sidetracking. You realized that your original statement
about the necessity of storing information about the class structure
was incorrect, so now to try to safe face and avoid having to admit
having made an error, you invent a new goalpost and pretend that that
was what you were talking about in the first place. In other words,
you are just trying to dodge and obfuscate.

And, obviously, you just throw names and insults on top of it,
as if that made you sound smarter somehow.

I have seen this kind of behavior many, many times over the
past two and a half decades. This is nothing new.

bol...@nowhere.co.uk

unread,
Jul 10, 2020, 3:56:07 AM7/10/20
to
On Thu, 9 Jul 2020 19:44:06 +0100
Mr Flibble <flibbleREM...@i42.co.uk> wrote:
>On 09/07/2020 19:38, bol...@nowhere.co.uk wrote:
>>>> My argument is that class layouts are stored in some form in the binary. Is
>
>>>> that true or false? If its false then explain how objects are created on
>the
>>>> fly. Take your time.
>>>
>>> A class layout would be akin to meta data which would be akin to type
>>> information and as I have already indicated text segments contain no type
>>> information WHATSOEVER. Now you have to use your brain and workout what
>really
>>> constitutes an object in a running program. Take all the time you need.
>>
>> I noticed you didn't explain anything. Perhaps you don't know.
>
>It is obvious to all that you certainly don't know. Here is a clue to help you
>in your quest: The C++ Abstract Machine and the final running executable ARE
>NOT THE SAME THING. Good luck.

Thanks for that heads up there Captain State The Obvious. Still no explanation
then? Whenever you're ready.


It is loading more messages.
0 new messages