Saturday, August 10, 2019

Digest for comp.lang.c++@googlegroups.com - 9 updates in 3 topics

David Brown <david.brown@hesbynett.no>: Aug 10 11:32PM +0200

On 10/08/2019 17:25, Bonita Montero wrote:
>> struct  solution.
 
> Yes, they generate the correct code and let the rest depend on the CPU
> or the OS (trapping).
 
You've given no evidence to suggest that any OS emulates unaligned
access. It might well be that some OS's do, for compatibility with
binaries for related processors - but your "proof by repeated assertion"
is getting tedious.
 
No compiler would /ever/ rely on trapping and emulation for handling
unaligned accesses to packed objects - that would be absurdly inefficient.
 
>> that is not properly aligned is undefined behaviour.
 
> This is done only on embedded-platforms with fixed adresses of hardware
> -registers.
 
You have no idea what you are talking about.
 
> So you're in the context of a certain compiler and hardware.
> There you don't have to worry about what the standard says.
 
The standard says that you can't do unaligned accesses. It is only if a
compiler documents that it allows such accesses that you can use it safely.
David Brown <david.brown@hesbynett.no>: Aug 10 11:46PM +0200

On 10/08/2019 17:21, Bonita Montero wrote:
>> More importantly here, it also does not mean you can take pointers
>> to  the unaligned members and use them as normal pointers, ...
 
> Quote the part of the standard that says that.
 
I already did.
 
These are from N1570, draft of C11 standard - C++ inherits this from C
and the C standards are simpler.
 
6.3.2.3p7:
"""
A pointer to an object type may be converted to a pointer to a different
object type. If the resulting pointer is not correctly aligned 68) for
the referenced type, the behavior is undefined.
"""
 
6.5.3.2p4:
"""
If an invalid value has been assigned to the pointer, the behavior of
the unary * operator is
undefined. 102)
"""
 
Footnote 102:
 
"""
Among the invalid values for dereferencing a pointer by the unary *
operator are a null pointer, an address inappropriately aligned for the
type of object pointed to, and the address of an object after the end of
its lifetime.
"""
 
 
 
>> ..., nor does it mean that the compiler supports unaligned access
>> in other cases - /even/ if  the hardware supports it.
 
> Which compiler does specify this? Show me a link to the documentation.
 
Compilers don't document things they /don't/ do - the document things
that they /do/.
David Brown <david.brown@hesbynett.no>: Aug 10 11:47PM +0200

On 10/08/2019 17:31, Bonita Montero wrote:
> isn't legal to take the address of an unaligned member.
> So show me some compilers documentations that say that it isn't
> legal to take the address of an unaligned member!
 
No, it would take compiler-specific documentation to say that it /is/
legal to take the address of an unaligned packed member - because the
standard already says that this is undefined behaviour. Thus if a
compiler wants to say it is allowed, it must document it.
Bart <bc@freeuk.com>: Aug 10 11:22PM +0100

On 10/08/2019 22:46, David Brown wrote:
> object type. If the resulting pointer is not correctly aligned 68) for
> the referenced type, the behavior is undefined.
> """
 
 
What does 'correctly aligned' mean?
 
Does C not allow the address of a 32-bit int to be at anything other
than a multiple of 4, when the machine has byte-addressed memory, even
when the hardware allows it?
Ian Collins <ian-news@hotmail.com>: Aug 11 10:59AM +1200

On 11/08/2019 09:32, David Brown wrote:
> is getting tedious.
 
> No compiler would /ever/ rely on trapping and emulation for handling
> unaligned accesses to packed objects - that would be absurdly inefficient.
 
Solaris SPARC?
 
https://blogs.oracle.com/d/on-misaligned-memory-accesses
 
--
Ian.
James Kuyper <jameskuyper@alumni.caltech.edu>: Aug 10 04:11PM -0700

On Saturday, August 10, 2019 at 6:23:16 PM UTC-4, Bart wrote:
> On 10/08/2019 22:46, David Brown wrote:
...
> > the referenced type, the behavior is undefined.
> > """
 
> What does 'correctly aligned' mean?
 
That's implementation-defined (6.2.8p1). In C2011 you can determine the
alignment of a given type under a given implementation by using
_Alignof(typename).
 
> Does C not allow the address of a 32-bit int to be at anything other
> than a multiple of 4, when the machine has byte-addressed memory, even
> when the hardware allows it?
 
The C standard merely allows each implementation to impose alignment
requirements for each type; each implementation is free to choose what
those requirements are. Many implementations do choose alignment
requirements greater than 1, to simplify code generation and to speed up
code execution for particular platforms.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 10 02:19PM -0700

>> }
 
> Yes, that's mainly the basic technique I had in mind: an extra level
> of indirection, the solution to every computer science problem.
 
Not a level of indirection, a layer of abstraction. Those aren't
the same thing. The abstraction here is a five-minute exercise
to write, ignorable in most of the defining class (that's one
value of using an abstraction), completely invisible to client
code, and incurs no run-time cost. So I think it meets the
criteria you gave.
 
> Nit-picks: (1) a State instance doesn't actually hold state, yet the
> member functions are not `static`, and (2) there's a needless dynamic
> allocation and memory leak.
 
In cases like this where I am sketching out a solution to someone
else's question, I assume without really thinking about it that
people who read my comments are tracking enough to focus on those
aspects that are relevant to the original problem, and not be
distracted by incidental matters. Apparently that was a bad
assumption here. Taking up your points in reverse order:
 
(1) Yes the code above does a 'new' but not a 'delete'. That has
no important bearing on the mechanism I was trying to explain.
 
(2) We don't know that the dynamic allocation is needless,
because we don't know what or how much member data the 'State'
class might have in the context of the OP's question.
 
(3) The member functions are regular member functions, because
that's what the OP was asking about, and because, based on what
question was asked, it seems obvious that the object in question
is expected to have internal state (aka member data) that is
manipulated by the various 'Nexter' member functions called
within the object.
 
 
> }
> }
 
> Here the reinterpret_cast is [...]
 
I skipped over any questions about whether the cast would have
problems since they aren't important to what you're explaining.
 
The OP included a code fragment that clearly showed calling
member functions through pointer-to-member-function return
values. (This code fragment appears in a quoted portion above.)
Is there some reason you're giving an example that doesn't
conform to that interface?
 
 
>> with a fairly short (five-ish lines) elaboration for the "...".
 
> Not sure what you're thinking of there?
 
Much like yours but using pointer-to-member-function rather than
pointer-to-function, to wit:
 
using Nexter = struct Hidden {
using PMF = Hidden (State::*)();
Hidden( PMF p0 ) : p( p0 ) {}
operator PMF(){ return p; }
PMF p;
};
 
 
 
>> which provides an even nicer source text.
 
> Well, to my mind the indirection adds complexity so that even though
> the code is short it's not IMO /clear/,
 
I don't think of what I suggested as an indirection, but as an
abstraction. A principal value of abstraction is to hide complexity
by tucking it away somewhere so it can be ignored afterwards. Here
I think that virtue is achieved rather nicely.
 
If someone were to think of a scheme along these lines not as an
abstraction but as an indirection, and one which is not meant to
hide inner workings, that could very well be confusing. I don't
know why someone would want to think of this approach that way.
 
> and for debugging it's not so
> clear which state one is in, just by looking at a function address.
 
I think how you are conceptualizing the problem is not the same
as how the OP is conceptualizing the problem. From how the
question was asked I inferred that 'State' is not just the
integer state of a finite state machine, but something more
elaborate (and perhaps much more elaborate) that knows what to do
to accomplish state transitions as well as which state should be
"gone to". And there may not be a one-to-one mapping between
'Nexter' member functions and states of the FSM that the 'State'
object is in; that information may not even be available from
just knowing what the pointer value is. If we want to know
something about what state the object is in, presumably we should
ask the object using some other (not yet stated) member function.
 
> But, subjective opinion. ;-)
 
I suspect your opinion here is shaped largely by how you are framing
the question. I took the OP at face value that what was being asked
for is in fact what is wanted. It's interesting that in this thread
three different people have suggested solutions to problems other
than what OP was asking about.
Tim Rentsch <tr.17687@z991.linuxsc.com>: Aug 10 02:45PM -0700


>> Did you not understand the question? Your "solution"
>> doesn't do anything like what he is asking for.
 
> Yes, I tried to express that doubt. Can't you read?
 
I read fine. My question was just a question, not an accusation.
I asked because I was curious to know if your confusion about not
understanding the question had progressed beyond merely being
uncertain.
 
> Your habit to answer in useless manner starts to feel
> strange.
 
I'm sure other people feel the same way about your answers.
 
> Additionally ... I suspect that Bonita is she.
 
I don't remember seeing any postings where OP makes an explicit
statement about his or her gender. If and when I do, I expect
what phrasings I use in the future will change to reflect the new
information.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Aug 10 09:05PM +0200

On 10.08.2019 20:18, Tim Rentsch wrote:
> }
 
> As far as the Standard is concerned these two functions are
> semantically equivalent.
 
If resource limits are not exceeded.
 
 
> They are equally well-defined.
 
Yes.
 
 
> They have exactly the same implications for observable behavior.
 
No.
 
 
> If one has undefined behavior then so does the other.
 
No.
 
 
> If one has a risk of undefined behavior then so does the other.
 
Repeating that claim doesn't make it less incorrect.
 
I'm pretty sure that you inadvertently repeated it because it was
orbiting in your mind, the key thing to communicate.
 
But it's trivially false: for a just some orders of magnitude larger
array size I can arrange to consistently crash the recursive function,
while the iterative one will be fine.
 
 
> A conforming
> implementation may choose to compile an iterative definition into
> recursive object code
 
No, absolutely not.
 
 
>, as well as vice versa.
 
Yes, it /can/ transform a recursive one to an iterative one that uses
less resources.
 
 
> recursive function might result in undefined behavior, you should
> also say the C++ standard gives you no guarantee about whether the
> iterative function might result in undefined behavior.
 
That would follow if your premises were true, but they aren't.
 
However, it's not black and white only. /Any/ function runs the risk of
UB if it's called in a context where stack space is exhausted. It's just
that with an iterative function the stack space requirements are usually
fixed at compile time, i.e. constant, and generally reasonably small, so
that in practice it's like the difference between swimming from Norway
to the US, or taking a plane: both ways can get you there, but the
chance of succumbing or incurring severe health costs when one chooses
to swim, is very much higher. Saying that both ways can get you there
and that both ways run a risk, that swimming and flying are somehow on
equal terms, ignores the important real world aspects and focus on a
wholly unreasonable, dangerous academic simplification. As I see it.
 
And the C++ standard is a practical document. Or it was, until C++14.
Now it seems that reality-divorced academics unduly influence the
direction and details of the standard, in effect like saboteurs. That's
not a jab at you, but if you were on the committee and tried to
introduce language that permitted a compiler to rewrite an iterative
function as recursive, then that /would/ have been that kind of
in-effect-sabotage, and then I /would/ have used derogatory words. ;-)
 
 
 
> That depends what you mean by "debug build". In fact g++ will
> compile recursive definitions into iterative object code even
> when a -g or -ggdb option is given.
 
What I mean by a "debug build" supports debugging.
 
Unless the debugging is about optimizations, a build with optimizations
is not a debug build, because it doesn't support general debugging.
 
 
Cheers!,
 
- Alf
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: