Monday, June 8, 2020

Digest for comp.lang.c++@googlegroups.com - 25 updates in 2 topics

David Brown <david.brown@hesbynett.no>: Jun 08 07:52PM +0200

On 08/06/2020 19:36, Manfred wrote:
 
> Actually, an interrupt handler is exactly the purpose that volatile is
> designed for: it tells the compiler that a variable may change its value
> outside the flow of operation as seen by the compiler.
 
Exactly. "Atomic" would be slightly inappropriate (though it would
probably work fine here).
 
 
> However, I am not totally with David Brown on preferring a conditional
> to a function pointer - of course it depends on the specific case, and
> it may be a matter of taste.
 
Of course it can vary by detail of the case, and personal preference.
As a general rule, I usually choose a conditional or switch rather than
a function pointer because it gives the compiler far more information
for optimisation purposes, and it makes it much easier to follow the
flow of the code when reading it, generating call graphs, etc. If your
code has no function pointers (or none of a particular type), then it's
easy to find every part of your code that calls the function "foo" - you
just search for all calls to "foo". If "foo" might have been assigned
to a function pointer, such searches are a lot more complicated.
 
It does come at the cost that it can lead to more inter-dependencies
between modules that could be avoided by function pointers and
call-backs, so there are pros and cons.
 
But since the OP is talking about interrupts, I'm assuming it will be a
low-level program and probably fairly small, so I'd start with a
variable and conditionals until convinced function pointers are better.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 08 11:03AM -0700

>> DO NOT DO THIS -- IT IS UNDEFINED BEHAVIOUR *AT BEST*.
 
> All C++-compilers handle vtables in a similar way.
> If you stick to one implementation that's quite manageable.
 
The OP wants to alter which function is called with a given name.
 
Isn't that exactly what function pointers are for?
 
Even if the language guaranteed the behavior of vtables (or mentioned
them at all!), what would be the advantage of modifying a vtable
rather than using a function pointer?
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Scott Newman <scott69@gmail.com>: Jun 08 08:07PM +0200

> Even if the language guaranteed the behavior of vtables (or mentioned
> them at all!), what would be the advantage of modifying a vtable
> rather than using a function pointer?
 
You won't have to deal with implementing your own vtable structure.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 02:26PM -0400

On 6/8/20 12:43 PM, Scott Newman wrote:
> Of course you can customize the vtable this way.
 
The kind of type-punning needed to do anything like this has undefined
behavior. This means, for instance, that an implementation is free to
cache vtable pointer somewhere and continue using the cached version,
even after you've changed the one in memory. However, the opportunities
for something to go wrong are much worse than that.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 02:27PM -0400

On 6/8/20 1:20 PM, Scott Newman wrote:
>> DO NOT DO THIS -- IT IS UNDEFINED BEHAVIOUR *AT BEST*.
 
> All C++-compilers handle vtables in a similar way.
> If you stick to one implementation that's quite manageable.
 
They're not required to do so, and I'd be surprised (or more accurately,
astounded) if they all did it in exactly the same way.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 02:28PM -0400

On 6/8/20 2:07 PM, Scott Newman wrote:
>> them at all!), what would be the advantage of modifying a vtable
>> rather than using a function pointer?
 
> You won't have to deal with implementing your own vtable structure.
 
At the cost of having to determine what the implementation's vtable
structure is, and at the cost of rendering the behavior of your program
undefined. An ordinary function pointer is a far better way of
implementing this.
Scott Newman <scott69@gmail.com>: Jun 08 08:32PM +0200

> structure is, and at the cost of rendering the behavior of your program
> undefined. An ordinary function pointer is a far better way of
> implementing this.
 
No, you will get an integration of your own functions in the vtable
and not a single function-pointer for each function in the object.
That's a lot less space.
And usually you stay with one implementation where this is reliable.
Scott Newman <scott69@gmail.com>: Jun 08 08:32PM +0200

> They're not required to do so, and I'd be surprised (or more
> accurately, astounded) if they all did it in exactly the same way.
 
The way is still the same since cfront for all C++-compilers.
Scott Newman <scott69@gmail.com>: Jun 08 08:34PM +0200

> The kind of type-punning needed to do anything like this has undefined
> behavior.
 
Doesn't matter if you stay with one impementation. The OP is talking
about interrupt-handlers, so it's very unlikely that he needs code
that is portable across all compilers.
Paavo Helde <eesnimi@osa.pri.ee>: Jun 08 09:47PM +0300

08.06.2020 21:03 Keith Thompson kirjutas:
>> If you stick to one implementation that's quite manageable.
 
> The OP wants to alter which function is called with a given name.
 
> Isn't that exactly what function pointers are for?
 
In C, yes. C++ provides better means to achieve the same, namely virtual
functions, functors and lambdas.
 
In this scenario virtual functions are not applicable, so one could use
a functor (a std::function variable), which can be easily assigned by
using a lambda.
 
However, if the repertoire of functions involved is small and fixed (as
I suspect is the case in this scenario), a simple state variable might
appear more readable and maintainable. But this depends on the usage
details.
 
> Even if the language guaranteed the behavior of vtables (or mentioned
> them at all!), what would be the advantage of modifying a vtable
> rather than using a function pointer?
 
I have come to a conclusion there is almost no usage case for plain
function pointers in C++. Nearly always one also wants to pass extra
data which can be done very conveniently with a lambda.
Paavo Helde <eesnimi@osa.pri.ee>: Jun 08 09:53PM +0300

08.06.2020 21:32 Scott Newman kirjutas:
> and not a single function-pointer for each function in the object.
> That's a lot less space.
 
> And usually you stay with one implementation where this is reliable.
 
Until the next compiler version or an innocent compilation flag will
optimize away or otherwise break your undefined behavior.
 
C++ does not have a shortage of ways how to shoot yourself in foot
inadvertently. There is no reason to do the same intentionally.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 08 07:55PM +0100

On 08/06/2020 19:34, Scott Newman wrote:
 
> Doesn't matter if you stay with one impementation. The OP is talking
> about interrupt-handlers, so it's very unlikely that he needs code
> that is portable across all compilers.
 
You are manifesting a combination of the two greatest evils: obtuseness and wrongness. How many times have you been fired from your job out of interest?
 
/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."
Scott Newman <scott69@gmail.com>: Jun 08 08:58PM +0200

>> And usually you stay with one implementation where this is reliable.
 
> Until the next compiler version or an innocent compilation flag will
> optimize away or otherwise break your undefined behavior.
 
That'S very unlikely with such a basic feature.
Scott Newman <scott69@gmail.com>: Jun 08 09:01PM +0200


> You are manifesting a combination of the two greatest evils: obtuseness
> and wrongness. How many times have you been fired from your job out of
> interest?
 
I have been working as a developer for a long time. And my bosses
were always happy with my job. There have never been any problems
with my programming style.
But you are a theoretician who has nothing to do with practice.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 03:01PM -0400

On 6/8/20 2:32 PM, Scott Newman wrote:
>> They're not required to do so, and I'd be surprised (or more
>> accurately, astounded) if they all did it in exactly the same way.
 
> The way is still the same since cfront for all C++-compilers.
 
How many different implementation of C++ have you actually verified that
assumption for? Please list them.
Scott Newman <scott69@gmail.com>: Jun 08 09:04PM +0200

>> The way is still the same since cfront for all C++-compilers.
 
> How many different implementation of C++ have you actually verified that
> assumption for? Please list them.
 
It's just the most obvious way to do it like Cfront.
And there is no reason to do it differently.
And with all compilers for Windows it is even more important
to do it that way because COM is based on this vtable layout;
other component-object-models handle it similary.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 03:07PM -0400

On 6/8/20 2:34 PM, Scott Newman wrote:
 
> Doesn't matter if you stay with one impementation. The OP is talking
> about interrupt-handlers, so it's very unlikely that he needs code
> that is portable across all compilers.
 
If the one implementation you're doing it with is one of the ones that
takes advantage of the fact that it has undefined behavior to do
something you didn't think it could do, no, you can't do that.
 
Please note that it's not sufficient to simply experiment and verify
that it works. If the implementation doesn't provide any guarantees
about what the behavior will be if you do something like this, it's
entirely possible that it will appear to work in every situation you
think of testing, but will fail in a situation that you didn't think to
test, possibly for reasons that you completely failed to imagine could
be relevant.
 
Please cite for me at least one implementation of C++ that provides
guarantees about what would happen if your code modifies the vtable, and
please tell us precisely what it guarantees about that behavior.
Scott Newman <scott69@gmail.com>: Jun 08 09:09PM +0200

> If the one implementation you're doing it with is one of the ones that
> takes advantage of the fact that it has undefined behavior to do
> something you didn't think it could do, no, you can't do that.
 
The whole thing is predictable since no compiler behaves differently
than cfront.
Paavo Helde <eesnimi@osa.pri.ee>: Jun 08 10:11PM +0300

08.06.2020 21:58 Scott Newman kirjutas:
 
>> Until the next compiler version or an innocent compilation flag will
>> optimize away or otherwise break your undefined behavior.
 
> That'S very unlikely with such a basic feature.
 
UB is a bug, not a feature.
Scott Newman <scott69@gmail.com>: Jun 08 09:12PM +0200

>> That'S very unlikely with such a basic feature.
 
> UB is a bug, not a feature.
 
UB is what the standard says, not the implementation.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 08 08:09PM +0200

Can ayone here tell me why I can't access errno
with the ::-prefix ?
guinness.tony@gmail.com: Jun 08 11:16AM -0700

On Monday, 8 June 2020 19:09:41 UTC+1, Bonita Montero wrote:
> Can ayone here tell me why I can't access errno
> with the ::-prefix ?
 
Because errno is defined as a macro.
 
22.4 Error numbers [errno]
1 The contents of the header <cerrno> are the same as the POSIX header
<errno.h>, except that errno shall be defined as a macro.
[ Note: The intent is to remain in close alignment with the POSIX standard.
— end note ]
A separate errno value shall be provided for each thread.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 08 08:21PM +0200

>> Can ayone here tell me why I can't access errno
>> with the ::-prefix ?
 
> Because errno is defined as a macro.
 
I "compiled" just with preprocessing-output and
errno is not substituted but stays as errno.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 08 02:59PM -0400

> [ Note: The intent is to remain in close alignment with the POSIX standard.
> — end note ]
> A separate errno value shall be provided for each thread.
 
What POSIX says is:
"Any conflict between the requirements described here and the ISO C
standard is unintentional."
...
"The symbol errno shall expand to a modifiable lvalue of type int. It is
unspecified whether errno is a macro or an identifier declared with
external linkage."
 
Section 17.5 paragraph 2 of the C standard lists the macros #defined in
<errno.h>, and errno is on that list. It goes on to specify that "errno
... expands to a modifiable lvalue 201) that has type int and thread
local storage duration ...".
 
Since the C standard explicitly describes errno as a macro, having it be
an "identifier declared with external linkage" would be in conflict with
the C standard's. As all such conflicts are explicitly declared to be
unintentional, that option presumably is not actually permitted.
However, the expansion of errno is allowed to be such an identifier.
 
The wording actually used, however, allows other possibilities, such as
 
# define errno (*__errno_location ())
 
which is how errno is defined in /usr/include/errno.h on my system.
Paavo Helde <eesnimi@osa.pri.ee>: Jun 08 10:08PM +0300

08.06.2020 21:21 Bonita Montero kirjutas:
 
>> Because errno is defined as a macro.
 
> I "compiled" just with preprocessing-output and
> errno is not substituted but stays as errno.
 
This does not refute the C++ standard (19.4 [errno]):
 
"The contents of the header <cerrno> are the same as the POSIX header
<errno.h>, except that errno shall be defined as a macro."
 
In my quick test errno got replaced by (*__errno()).
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: