Tuesday, June 28, 2022

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

Juha Nieminen <nospam@thanks.invalid>: Jun 28 01:56PM

One of the strangest and perhaps most surprising (and even controversial)
new features of C++20 are coroutines. This post is not about bashing them,
criticizing them, questioning the motivation for adding them to the
already complex language, or anything like that. Let's put all that aside
for a moment, and just focus on what they can actually be useful for.
Practical examples.
 
I had never heard of "coroutines" before, and in fact it took me quite
a while to understand what exactly they are, and what they are used for.
They are often described as kind of emulating cooperative multitasking
(similarly to how multitasking worked in Windows 3.x and MacOS prior
to X.)
 
I would, however (and from what I understand), describe them more like a
way to more easily store the state of a function (or group of functions)
so that the function can be exited at any point that it wants, and then
execution resumed later from that point (when the rest of the code
tells it to resume execution.)
 
(Well, I suppose that's exactly what "cooperative multitasking" means,
but I think describing it as I did is much clearer than using that term.)
 
Of course doing this was already possible even before C++20, but it
required a lot more manual labor, a lot more coding. The coroutines
help automatize the process and make it much easier.
 
So where is this actually useful? I can think of two examples.
Are there more?
 
Example 1:
 
You are writing a function that decompresses some compressed input format.
The decompressed data should be written to a buffer of a given size.
Whenever the buffer gets full, this decompressor function should return
it to the calling code for it to consume it. After the calling code has
consumed it, the decompression should continue from where it left.
Since compression formats are complicated there may be literally dozens
of places in the decompression algorithm where the buffer may get full,
in very varied situations, sometimes even inside deeply nested loops,
coroutines make this process a lot easier because the code can "yield"
at any point, anywhere (even inside deeply nested loops), and then
continue from that point as if nothing has happened (other than the
buffer having been emptied).
 
Example 2:
 
A class/module that parses command-line arguments. Since the arguments may
appear in many different forms, the parser is done so that it will be
called with individual command-line parameters (which may end in the null
character, or a whitespace character, or something else). In other words
for each individual parameter the calling code calls the parser giving it
that parameter.
 
However, not all command-line parameters are singular, as in consisting
of only one "word". A parameter may be followed by one or more strings
(such as file names, etc.) The calling code doesn't know if a particular
parameter is just data for the previous parameter or not, it just feeds
them one by one to the parser.
 
Thus, when the parser encounters a parameter that expects further
parameters, it needs to remember its state between calls. (It needs to
remember which particular command-line parameter it's currently
parsing, and any additional parameters given to it already.)
(This, of course, can be done even with C++98, but with coroutines this
"storing the current state of the parser" becomes much easier.)
Bonita Montero <Bonita.Montero@gmail.com>: Jun 28 04:47PM +0200

If you don't like coroutines, don't use them.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jun 28 01:14AM +0100

>> verb), and I don't think it does in mathematics either. And in C and
>> C++, incrementing means adding one.
 
> Not really.
 
It really does. It's right there in the definition.
 
> to the same machine code. But that machine code will almost certainly
> be "add 4 to the address held in ptr". In fact what you mean is "go to
> the next value in the sequence".
 
What happens to the representation of the pointer when we add one to it
should not prevent you from believing that you are adding 1. You are
adding 1.
 
> resolution of 1mg. However the fact we are using metric units is
> merely conventional. It has no scientific significance. As is our
> choice of 1mg as the spacing between the tests. So it's "accidental".
 
Ah, scare quotes. I agree it's "accidental" but not that it's
accidental.
 
> on, up to ten men, digging a hole, and time them. Now the choice of
> one is not "accidental". It's fundamental that we can only have a
> whole number of workers.
 
But you said
 
"Adding one means "increase by a constant value which accidentally
happens to be unity".
 
I see neither an accident nor an "accident" here. Adding one means
increasing by unity. That seems to me to be fundamental.
 
>> "increment by".
 
> Exactly. ++ should mean "take the next member of an ordered set". Which it
> does in C++.
 
Eh? It means add one in C++: "The value of the operand object is
modified (3.1) by adding 1 to it". What is the next member after 1.0 of
the ordered set of double values? What is ++x when x is 1.0?
 
> In C++ "++" can't always be replaced by "+=1". In C it can.
 
Eh (again)? Both standards give that equivalence so as to delegate all
the details about types and conversion to the descriptions of addition
and assignment.
 
 
--
Ben.
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jun 27 06:42PM -0700

On Tuesday, 28 June 2022 at 00:02:50 UTC+1, Keith Thompson wrote:
> > in the sequence".
> Which you do by adding 1. In pointer arithmetic, adding 1 has a well
> defined meaning, which is not advancing to the next memory address.
 
In pointer arithmetic, adding one does not mean adding one to the address.
So it's "adding one", but only if, in this context, we accept that "adding one"
means "add four" (or however many bytes an integer occupies).
ptr++ means "go to the next integer in the sequence and take its address".
 
You can of course also say it's "adding one" because of C's rules for
pointer arithmetic. But it's not "really adding one".
Take this.
int x;
int* iptr = &x;
unsigned char* cptr = iptr;
if (iptr == cptr)
printf("pointers the same\n");
iptr++;
cptr++;
if (iptr == cptr)
printf("pointers the same\n");
 
Now iptr and cptr are equal, we add the same value to them and then they are not
equal. This isn't "wrong" because we're not working with the normal rules for
arithmetic. But we're using the word "add" in a special way. So we can say "we're
not really adding one", using the normal meaning of the word.
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jun 27 06:52PM -0700

On Tuesday, 28 June 2022 at 01:15:14 UTC+1, Ben Bacarisse wrote:
> happens to be unity".
> I see neither an accident nor an "accident" here. Adding one means
> increasing by unity. That seems to me to be fundamental.
 
If we've got two workers and add another, we have increased by unity.
If we've got two grams of sugar and we add another gram, we've done
something rather different.
The symbol "1" appears in both cases if you write it out. But it doesn't
mean the same thing. In one case it expresses an underlying, fundamental
property of the thing it represents. In the other case it doesn't. It expresses
an accidental property of the sugar.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 27 07:27PM -0700

>> Which you do by adding 1. In pointer arithmetic, adding 1 has a well
>> defined meaning, which is not advancing to the next memory address.
 
> In pointer arithmetic, adding one does not mean adding one to the address.
 
Yes, it does -- because that's how C and C++ define the operation of
adding a pointer and an integer.
 
> So it's "adding one", but only if, in this context, we accept that "adding one"
> means "add four" (or however many bytes an integer occupies).
 
No, adding an integer value N to a pointer value does not mean adding N
bytes (unless sizeof *ptr == 1).
 
> ptr++ means "go to the next integer in the sequence and take its address".
 
Given that ptr is of type int*, yes, more or less. (I'd phrase it
differently.)
 
ptr = ptr + 1 means exactly the same thing.
 
> You can of course also say it's "adding one" because of C's rules for
> pointer arithmetic. But it's not "really adding one".
 
Yes, it's really adding one.
 
> equal. This isn't "wrong" because we're not working with the normal rules for
> arithmetic. But we're using the word "add" in a special way. So we can say "we're
> not really adding one", using the normal meaning of the word.
 
We're using "add" in the way defined by the language. That is the
normal meaning.
 
Please stop trying to confuse the issue by applying other meanings to
terms that are already well defined.
 
Yes, we know that some of these terms can have different meanings in
other contexts. You're insisting that those other meanings are somehow
more "normal" than the meanings defined by the language. That's silly.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jun 27 08:37PM -0700

On Tuesday, 28 June 2022 at 03:28:10 UTC+1, Keith Thompson wrote:
 
> Yes, we know that some of these terms can have different meanings in
> other contexts. You're insisting that those other meanings are somehow
> more "normal" than the meanings defined by the language. That's silly.
 
It would have been more consistent for C to have defined
 
ptr += sizeof(*ptr);
 
as the way of moving a pointer along to the next position.
However it's such a common requirement that this wasn't done, and instead
the concept of "scaled arithmetic" was developed.
When you change the rules of arithmetic like this, inevitably you break some
of the relationships that hold in arithmetic over the set of the real numbers.
In this case
a = x;
b = x;
therefore a + c = b + c;
no longer necessarily holds.
So "a + c" means something different to what is normally understood by
these symbols. What is meant is sufficiently close to the operation of addition
over the real numbers to make it reasonable to use the same word, as
long as you make clear that you are using the word :add" in a special
way.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 27 11:07PM -0700


> It would have been more consistent for C to have defined
 
> ptr += sizeof(*ptr);
 
> as the way of moving a pointer along to the next position.
 
No, it really wouldn't. Pointers are not numbers. It's useful to
define a few limited arithmetic operators on them:
pointer + integer -> pointer
pointer - integer -> pointer
pointer - pointer -> integer
 
Defining ptr+1 to yield a useless and invalid pointer would have been
silly.
 
Do you expect pointer+pointer or integer-pointer to have some consistent
meaning?
 
> b = x;
> therefore a + c = b + c;
> no longer necessarily holds.
 
Sure it does, as long as the types are consistent. Adding 1 to an int*
pointer is a *different operation* than adding 1 to a char*.
 
> over the real numbers to make it reasonable to use the same word, as
> long as you make clear that you are using the word :add" in a special
> way.
 
It's a lot easier to understand pointer arithmitec the way it's actually
defined than to start with some inconsistent mental model and adjust it
to fit reality.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Juha Nieminen <nospam@thanks.invalid>: Jun 28 06:40AM

> pointer - pointer -> integer
 
> Defining ptr+1 to yield a useless and invalid pointer would have been
> silly.
 
One can think of "ptr+1" as being just syntactic sugar for "&ptr[1]".
(Technically it might not be "just syntactic sugar", but one can
think of it as such.)
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jun 28 02:32AM -0700

On Tuesday, 28 June 2022 at 07:41:06 UTC+1, Juha Nieminen wrote:
> One can think of "ptr+1" as being just syntactic sugar for "&ptr[1]".
> (Technically it might not be "just syntactic sugar", but one can
> think of it as such.)
 
That's another reason for scaled pointer arithmetic. So that you can convert
between ptr[2] and *(ptr + 2).
I'm not saying that the decision to use scaled pointer arithmetic was wrong.
 
I am saying that ptr += 1 is not "really" adding one to the pointer, if it is not to
a single byte type. "Really" you are adding the size of the item the pointer points
to.
You can say "a pointer is not a number", and that's true in the important exceptional
case of old x86 segment::offset pointers. But these never really worked well in
C in any case. Compilers introduced the "far" keyword to help deal with them.
 
My sister's address is 15. But in fact she lives in the thirteenth house in the street. All
rules for numbers don't necessarily apply for house address numbers. But they
are still called numbers.
"Öö Tiib" <ootiib@hot.ee>: Jun 28 03:05AM -0700

On Tuesday, 28 June 2022 at 12:32:34 UTC+3, Malcolm McLean wrote:
> > think of it as such.)
 
> That's another reason for scaled pointer arithmetic. So that you can convert
> between ptr[2] and *(ptr + 2).
 
It is other way around. The operator [] is defined in terms of pointer arithmetic
so 2[ptr] is *(2 + ptr) and so required to work. We can't have circular definitions
in specification.
 
 
> I am saying that ptr += 1 is not "really" adding one to the pointer, if it is not to
> a single byte type. "Really" you are adding the size of the item the pointer points
> to.
 
IOW you see yourself that making it in any other way would be silly. Pointer
is internally address but that is not exposed in its interface.

> You can say "a pointer is not a number", and that's true in the important exceptional
> case of old x86 segment::offset pointers. But these never really worked well in
> C in any case. Compilers introduced the "far" keyword to help deal with them.
 
You need to use reinterpret_cast to get the integer value of that address out
of pointer, or to turn it into byte address ... and then you need to know what
platform you are at and what you are doing.
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jun 28 03:15AM -0700

On Tuesday, 28 June 2022 at 11:05:51 UTC+1, Öö Tiib wrote:
> It is other way around. The operator [] is defined in terms of pointer arithmetic
> so 2[ptr] is *(2 + ptr) and so required to work. We can't have circular definitions
> in specification.
 
I don't know exactly what Denis Ritchie was thinking.
But I suspect he decided early on that [] would be the subscript operator, and that
incrementing the subscript by one would move to the next item in the array.
The last was a no-brainer.
 
Then you've got the question of how ptr[i] relates to *(ptr + i). Did he decide that
arrays would be 0-based, then decide that pointer arithmetic would be scaled?
Or did he decide that *(ptr + i) would mean ptr[i], and then accept, maybe reluctantly,
that that entailed 0-based arrays? I don't know.
David Brown <david.brown@hesbynett.no>: Jun 28 03:07PM +0200

On 28/06/2022 11:32, Malcolm McLean wrote:
> You can say "a pointer is not a number", and that's true in the important exceptional
> case of old x86 segment::offset pointers. But these never really worked well in
> C in any case. Compilers introduced the "far" keyword to help deal with them.
 
You are wrong. A pointer is /not/ a number. It is /not/ an address.
If you find that confusing, then it is no wonder you are writing such a
stream of muddled posts.
 
As a general definition, a "pointer" is a way to access data indirectly.
 
In C, it is basically "an address with type information". (I say
basically, because it can also represent information about what may or
may not be accessible as fully defined behaviour, and of course weird
implementations can have other data in a pointer.) In C++, that applies
to "raw" pointers - other kinds of pointers may have extra information.
 
If "p" is a pointer, p++ adds 1 to the /pointer/. It does not
necessarily add 1 to the address stored by the pointer - we very rarely
care what happens under the hood.
 
 
If "p" and "q" are two pointers, and "n" is an integer, then it is
always the case in C that "p + n == q + n", as you would expect. That
is because the expression makes no sense in the language if "p" and "q"
point to incompatible types, and the compiler should reject the code
with an error if they are not compatible.
 
 
It is important to understand the difference between what a high-level
concept like "pointer" represents, and how it might happen to be
implemented in a particular case - even if the implementation is obvious
and close to universal.
David Brown <david.brown@hesbynett.no>: Jun 28 03:17PM +0200

On 27/06/2022 23:32, Malcolm McLean wrote:
>> verb), and I don't think it does in mathematics either. And in C and
>> C++, incrementing means adding one.
 
> Not really.
 
As Ben and Keith have said, it is in the definition in the C standards.
(In C++, is always possible to have different effects on operators of
your own types - but the same definition applies in C++ for the built-in
integer, floating point and raw pointer types.)
 
 
To quote from C11 :
 
(6.5.2.4)
"""
The result of the postfix ++ operator is the value of the operand. As a
side effect, the value of the operand object is incremented (that is,
the value 1 of the appropriate type is added to it). See the discussions
of additive operators and compound assignment for information on
constraints, types, and conversions and the effects of operations on
pointers.
 
The postfix -- operator is analogous to the postfix ++ operator, except
that the value of the operand is decremented (that is, the value 1 of
the appropriate type is subtracted from it).
"""
 
(6.5.3.1)
"""
The value of the operand of the prefix ++ operator is incremented. The
result is the new value of the operand after incrementation. The
expression ++E is equivalent to (E+=1).
 
See the discussions of additive operators and compound assignment for
information on constraints, types, side effects, and conversions and the
effects of operations on pointers.
 
The prefix -- operator is analogous to the prefix ++ operator, except
that the value of the operand is decremented.
"""
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jun 28 02:55PM +0100


> If we've got two workers and add another, we have increased by unity.
> If we've got two grams of sugar and we add another gram, we've done
> something rather different.
 
You can't do either in C++. In C++ you manipulate numerical quantities,
and unity is 1 when talking about numerical values. In C++ I'd write
 
workers += 1;
grams_of_sugar += 1;
 
I have added 1 in both cases and there is nothing accidental about
that. It was done (presumably) because that is what the program design
needs at this point.
 
> doesn't mean the same thing. In one case it expresses an underlying,
> fundamental property of the thing it represents. In the other case it
> doesn't. It expresses an accidental property of the sugar.
 
I know what you are getting at, but in C++ adding unity means adding
one. The fact that we designed the program so that adding one was the
right thing to do at that point was not an accident though they may have
been some choice in the matter. The fact that some quantities are
dimensionless does not justify saying that in the other cases adding one
(in a program) is an accident.
 
I hope you can see I know what you are getting at. It's the words I
don't like. It gives rise to statements that appear daft to me. I
don't mind "accidental" because the scare quotes tell me you don't mean
a literal accident.
 
--
Ben.
Malcolm McLean <malcolm.arthur.mclean@gmail.com>: Jun 28 07:22AM -0700

On Tuesday, 28 June 2022 at 14:08:00 UTC+1, David Brown wrote:
> If you find that confusing, then it is no wonder you are writing such a
> stream of muddled posts.
 
> As a general definition, a "pointer" is a way to access data indirectly.
 
A pointer is a way to access data indirectly.
But so is a reference.
So is a key.
 
But references and keys are not pointers.
In C and C++, it must be possible to take the address past the pointer.
Even in the case of a pointer to a scalar.
So a pointer does have to be an "address". Usually, a machine address of
course. In exceptional implementations you might want to argue about
what constitutes an "address" and what doesn't. But you must be able to
"go to the next address", so it's got to have number-like properties. It
can't be any system of indirection.
Siri Cruise <chine.bleu@yahoo.com>: Jun 27 04:58PM -0700

In article
<756f4d86-7d99-4047-a5ee-25705ecf265en@googlegroups.com>,
 
> If I try to compile the following with the GNU compiler (g++):
 
If worse comes to worse, you can always use cpp and persnickety
placements of #defines and #includes to get around these problems.
 
#define static auto
#include "idiot's stupid variable declarations"
#undef static
#define static static
 
Not ideal, but you can make anything work. If you do have to do
this nonsense, be sure to add comments why.
 
And if even worse comes to cesspit worse. m4 is widely available
and can be coerced with pinhead's hooks and chains to do what cpp
cannot.
 
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
Discordia: not just a religion but also a parody. This post / \
I am an Andrea Chen sockpuppet. insults Islam. Mohammed
Juha Nieminen <nospam@thanks.invalid>: Jun 28 06:51AM


> Given that the language of the standard says that it is unspecified
> whether values from the c prefixed headers (like cstddef) are declared
> in the global scope I would say this is not a bug.
 
AFAIK it's a compromise by the standard because they don't want to
overburden the standard library implementations, or something.
 
But I think it's a bad compromise. It's making the life of the standard
library implementors easier at the cost of making the life of C++
programmers harder. If you #include <cstddef> you cannot assume that
the names are in the global namespace but you have to take into
account that they could be. Good luck remembering every single
name in all the <c...> header files.
 
On top of that, IIRC you can't assume <stdlib.h> exists, so no luck
in trying to make sure that those names *are* in the global namespace.
(Although I think C++23 "undeprecates" those headers, so if you wait
for it to become widely supported you can make sure.)
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Jun 28 10:19AM +0200

On 28 Jun 2022 08:51, Juha Nieminen wrote:
> account that they could be. Good luck remembering every single
> name in all the <c...> header files.
 
> On top of that, IIRC you can't assume <stdlib.h> exists,
 
Uh, where did you get that idea?
 
The ".h" headers were formally deprecated in 1998, the first standard,
because the committee unwisely, I'd say retardedly, assumed that the
intent of the clean "c..." headers would be fully supported and adopted.
 
That didn't happen, and will now never happen, since the committee
backed down a little from their high academic stance in 2011.
 
Likewise, it will never happen that the ".h" headers will disappear.
 
C++'s success is entirely founded on C compatibility, on leveraging C
libraries. That will not change. You can count on that much more than
you could count on core language features like `throw` specifications
and `export`-ed templates.
 
 
> so no luck
> in trying to make sure that those names *are* in the global namespace.
 
For C++11 names from the C library just include the relevant ".h"
header, very simple.
 
 
> (Although I think C++23 "undeprecates" those headers, so if you wait
> for it to become widely supported you can make sure.)
 
A simple remedy is to always include both of pair, "c..." and ".h".
 
That provides full guarantees about where the C++11 and earlier names
from the C library are defined, namely in both namespace `std` and the
global namespace. Guarantees that one can RELY on.
 
Unfortunately the committee didn't entirely give up their academic pipe
dream, and in C++14, C++17 and no doubt also in C++20, new names such as
`std::byte` and C11 esoteric math functions, were introduced in "c..."
headers only, with explicit exceptions that these names should not be
provided by ".h" headers. Sabotaging things just to score points for a
f...ing academic ideal. Politics everywhere, it's frustrating to have
the C++ standardization committee prioritize internal political goals to
that degree (one member even argued that Bjarne is to blame for all the
recent bad decisions, I think his words were "Bjarne is the problem").
 
 
- Alf
Paavo Helde <eesnimi@osa.pri.ee>: Jun 28 12:33PM +0300

27.06.2022 17:37 Frederick Virchanza Gotham kirjutas:
> If I try to compile the following with the GNU compiler (g++):
 
> #include <cstddef>
 
namespace MyGreatProject {
 
> class size_t {
 
> };
 
} // namespace
 
Problem solved.
"Öö Tiib" <ootiib@hot.ee>: Jun 28 02:49AM -0700

> libraries. That will not change. You can count on that much more than
> you could count on core language features like `throw` specifications
> and `export`-ed templates.
 
It wasn't retarded but carefully lobbied by likes of MicroSoft to get rid
of competitors like Watcom and Borland. Maybe some academics
were fooled but there never was hope. C++ headers are never defining
interface of module. So two modules written in C++ but compiled with
different version of compiler or different compiling options were never
designed to be possible to link together without using C headers as
mediator. Nothing to talk of other programming languages. So even if
there are some libraries written in C++ these either are open source
or pretend to be C libraries for to be useful.
Juha Nieminen <nospam@thanks.invalid>: Jun 28 01:25PM

>> On top of that, IIRC you can't assume <stdlib.h> exists,
 
> Uh, where did you get that idea?
 
I expressed it a bit poorly.
 
The <*.h> headers being deprecated means that it's not guaranteed that
they will exist in a future version of the standard.
 
So while yes, you can be sure that they exist eg. in C++11, you can't
be sure they will exist in some hypothetical future C++35 (and thus
your code may break if compiled in that mode).
 
OTOH the committee apparently relented with C++23 and will
"undeprecate" those headers, so you can use them without the fear
of them suddenly disappearing...
Juha Nieminen <nospam@thanks.invalid>: Jun 28 01:27PM


>> };
 
> } // namespace
 
> Problem solved.
 
Way to write confusing code inside that namespace...
David Brown <david.brown@hesbynett.no>: Jun 28 03:27PM +0200

On 28/06/2022 10:19, Alf P. Steinbach wrote:
> the C++ standardization committee prioritize internal political goals to
> that degree (one member even argued that Bjarne is to blame for all the
> recent bad decisions, I think his words were "Bjarne is the problem").
 
In all real compiler and library implementations of C++, the same
toolchain is both a C and a C++ compiler, and the library and headers
are shared where possible. But sometimes you just have a C compiler
without C++ - to the greatest possible extent, the C library and headers
of an implementation are a subset of the C++ library and headers. That
means the C++ committee do not mess with the contents of <math.h> or
<stdlib.h> except when it is unavoidable - it saves implementers
littering the files with "#ifdef __cplusplus ..." sections.
 
So when new maths functions were introduced, there were two options -
either the C committee also wanted them and they could go in <math.h>
(and therefore also <cmath>), or the C folks did not want them and the
C++ gang had to put them in their own header. It would, IMHO, have made
more sense to have a new C++ specific header with the new functions
rather than adding them to <cmath>, but I haven't bothered to follow the
discussions and reasoning behind the decision.
hester holt <hesterholt6@gmail.com>: Jun 27 09:37PM -0700

This is the PDF eBook version for Clinical Scenarios in Surgery - Decision Making and Operative Technique by Dimick
(Download link for cheap price) https://booksca.ca/library/ebook-clinical-scenarios-in-surgery-decision-making-and-operative-technique-by-dimick/
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.

Thursday, June 23, 2022

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

Muttley@dastardlyhq.com: Jun 23 07:11AM

On Wed, 22 Jun 2022 19:05:54 +0200
 
>No, it creates a new vector with these values. That's initialization,
>like in setting its initial value.
 
>Assignment is when there already is an objects, and it gets a new value.
 
Initialisation is the whole process, assignment is specifically setting the
values and the terminology doesn't depend on whether a value is already there.
Like I said, you're splitting hairs but call it whatever you want, I'm not
getting into another idiotic language argument with someone for whom english is
a 2nd language anyway.
Muttley@dastardlyhq.com: Jun 23 07:16AM

On Wed, 22 Jun 2022 19:16:02 +0200
>differences between initialisation and assignment, and if you want to
>understand the language you should make a point of learning about these
>differences.
 
Ah, we're in to patronising territory already which is usually an indication
that the poster is backing into a corner.
 
>incorrect terms, that's your choice - it will be good enough for simple
>coding. But it would be nice if you didn't try to confuse learners by
>using inaccurate terms.
 
I'm using the standard english terms, I'm not interested in how its described
in some dusty corner of the spec. And FWIW I doubt there are any learners on
here. How you describe something has zero effect on code unless you believe
in psychokinesis. Perhaps you do.
 
Just in case you're still confused:
 
https://www.oxfordlearnersdictionaries.com/definition/english/assign
 
"to say that something has a particular value or function, or happens at a
particular time or place"
 
Eg at vector initialisation time.
 
HTH.
Christian Gollwitzer <auriocus@gmx.de>: Jun 23 09:12AM +0100


> I'm using the standard english terms, I'm not interested in how its described
> in some dusty corner of the spec.
 
But you are talking to people who use them in their standard defined
meaning. You missed that words have multiple meanings, and especially in
science and technology these meanings sometime differ from the general
usage.
 
E.g. a "theory" in colloquial English is a vague idea for an
explanation, what scientists call a "hypothesis", while a "theory" in
science is a model backed up by and generalising all available evidence.
 
Likewise, "assignment" and "initialisation" are technical terms for C++
programmers, and when you call them "wurzlbrmpft" and "kohlrabi" you
would just induce confusion among the people who use them in their
defined meaning, and even more when you mix them up.
 
 
Christian
David Brown <david.brown@hesbynett.no>: Jun 23 11:33AM +0200


>> Assignment is when there already is an objects, and it gets a new value.
 
> Initialisation is the whole process, assignment is specifically setting the
> values and the terminology doesn't depend on whether a value is already there.
 
Bo is correct. Words like "initialisation" and "assignment" have
specific meanings in the language, and it is useful to get in the habit
of using them accurately. You are right that assignment can happen
without a value being in the object ("int x; x = 1;"). But the object
has to exist and have completed its initialisation, if any, before an
assignment can happen.
 
> Like I said, you're splitting hairs but call it whatever you want,
 
It is what the standards call it, not necessarily what any C++ user
wants. (Most C++ users would want the whole thing simplified a bit.)
 
> I'm not
> getting into another idiotic language argument with someone for whom english is
> a 2nd language anyway.
 
Bo's English is at least as good as yours.
David Brown <david.brown@hesbynett.no>: Jun 23 11:37AM +0200

>> using inaccurate terms.
 
> I'm using the standard english terms, I'm not interested in how its described
> in some dusty corner of the spec.
 
This is not a "dusty corner" of the language specification - it's an
important concept in C++. The distinction between initialisation and
assignment is not an easy matter, and you can reasonably argue that it
is more complicated that it really should be. But you have to learn it,
and you should try to use the terms accurately. It makes no practical
difference for simple object types, such as "int" here, but it /does/
make a difference with more complicated code.
 
 
> "to say that something has a particular value or function, or happens at a
> particular time or place"
 
> Eg at vector initialisation time.
 
Why would you think a dictionary entry is of relevance to technical
terms with specific meanings in a programming language standard?
Juha Nieminen <nospam@thanks.invalid>: Jun 23 11:07AM

>>differences.
 
> Ah, we're in to patronising territory already which is usually an indication
> that the poster is backing into a corner.
 
There's nothing patronizing about that response. It's simply stating an
important fact about C++.
 
>>using inaccurate terms.
 
> I'm using the standard english terms, I'm not interested in how its described
> in some dusty corner of the spec.
 
You should not be using "standard english terms" when it comes to such things
in C++ because if you do so you'll be causing confusion and even
misunderstandings. "Initialization" and "assignment" have very specific
meanings in C++ and can't be used interchangeably.
 
One quite prominent way of seeing the difference is that for custom
types assignment can be disabled (you'll get a compiler error if you try)
while initialization is enabled. (The other way around is possible too.)
 
There are, in fact, some utility classes in the standard library where
that's exactly the case, most prominently std::unique_ptr. You can
initialize it but you can't (copy) assign one. (You can move assign, but
that's a bit different.)
Juha Nieminen <nospam@thanks.invalid>: Jun 23 11:13AM

>> demarcation (though IMO [] would have made more sense) but is silly for a
>> simple assignment.
 
> The point is exactly that it isn't an assignment. It is an initialization.
 
And, in fact, they are two rather different types of initialization: The first
one is calling a constructor taking an int, while the second one is calling
a copy constructor (although the compiler is optimize that construction-the-
temporary-and-calling-the-copy-constructor away and just call the regular
constructor with the given value).
 
I have seen some people even use this idiom, with no understanding of that
difference:
 
auto vec = std::vector { 1, 2, 3, 4 };
 
While normally the compiler is allowed to optimize the temporary and the
copy constructor call away, I'm actually not sure it can do that in this
case. I find this idiom abhorrent.
Muttley@dastardlyhq.com: Jun 23 01:16PM

On Thu, 23 Jun 2022 09:12:45 +0100
 
>> I'm using the standard english terms, I'm not interested in how its described
 
>> in some dusty corner of the spec.
 
>But you are talking to people who use them in their standard defined
 
Yes I know the autism level is high on here.
Muttley@dastardlyhq.com: Jun 23 01:20PM

On Thu, 23 Jun 2022 11:33:22 +0200
>without a value being in the object ("int x; x = 1;"). But the object
>has to exist and have completed its initialisation, if any, before an
>assignment can happen.
 
Exactly. Initialisation consists of allocating the memory. Then you ASSIGN
the values to that memory.
 
>is
>> a 2nd language anyway.
 
>Bo's English is at least as good as yours.
 
Highly unlikely.
Muttley@dastardlyhq.com: Jun 23 01:22PM

On Thu, 23 Jun 2022 11:37:57 +0200
 
>> Eg at vector initialisation time.
 
>Why would you think a dictionary entry is of relevance to technical
>terms with specific meanings in a programming language standard?
 
Because spoken languages are defined in dictionaries, not in computer
progamming manuals. Memory gets assigned a value.
Muttley@dastardlyhq.com: Jun 23 01:23PM

On Thu, 23 Jun 2022 11:07:49 -0000 (UTC)
>that's exactly the case, most prominently std::unique_ptr. You can
>initialize it but you can't (copy) assign one. (You can move assign, but
>that's a bit different.)
 
I don't see your point. You're still assigning a value to it, the fact that
you can only do it the once is neither here nor there.
David Brown <david.brown@hesbynett.no>: Jun 23 04:10PM +0200

>> assignment can happen.
 
> Exactly. Initialisation consists of allocating the memory. Then you ASSIGN
> the values to that memory.
 
That is not correct usage of the technical terms (and it is the
technical terms that matter). Initialisation does not consist solely of
allocating memory, nor is allocation of memory necessary for many
initialisations.
 
>>> a 2nd language anyway.
 
>> Bo's English is at least as good as yours.
 
> Highly unlikely.
 
I've noticed a fair number of grammatical errors in your writing, but
none in Bo's posts. Of course I have not examined all his posts. My
experience with well-educated Scandinavians (and I am confident I have
more experience with them than you) is that their written English is
frequently more accurate than native English speakers. They sometimes
have tell-tail habits in their spoken English, and they won't use the
same range of idioms.
 
Certainly any argument on the basis of Bo's mastery of English as a
second language is unjustified.
Juha Nieminen <nospam@thanks.invalid>: Jun 23 02:56PM

>>that's a bit different.)
 
> I don't see your point. You're still assigning a value to it, the fact that
> you can only do it the once is neither here nor there.
 
Seriously, how hard it is to just say "ah, sorry, my bad, I stand corrected.
I learned something new today", instead of just going into this endless and
futile quest of trying to "win" and to "be right" in such a petty little
thing?
 
Admitting not having known something, or having made a small mistake, is not
a bad thing, nor is it shameful. You don't have to always "win". You don't
have to always "be right". You can perfectly well be mistaken, admit it,
learn from the mistake, and nobody will ridicule you.
 
The longer you continue this silly quest of yours of trying to defend your
mistake as not being a mistake, the deeper you will be digging that hole
where you wouldn't even have to be. In other words, and rather ironically,
you are shaming yourself by trying so desperately to be right, rather
than admitting that you didn't know (or were mistaken).
 
This is really not a hill to die on. Just say "I stand corrected" and
move on. Nobody will blame you for that.
 
(Now expecting your "I didn't read any of that" with an assortment of
insults response...)
Muttley@dastardlyhq.com: Jun 23 03:14PM

On Thu, 23 Jun 2022 16:10:27 +0200
>technical terms that matter). Initialisation does not consist solely of
>allocating memory, nor is allocation of memory necessary for many
>initialisations.
 
So the value doesn't get assigned to the memory. It just magically appears
there?
 
>> Highly unlikely.
 
>I've noticed a fair number of grammatical errors in your writing, but
>none in Bo's posts. Of course I have not examined all his posts. My
 
I write my posts in vi without any spell checking plugins and given I'm working
I have better things to do that double check spellings to keep pedants like you
happy.
Muttley@dastardlyhq.com: Jun 23 03:19PM

On Thu, 23 Jun 2022 14:56:27 -0000 (UTC)
>I learned something new today", instead of just going into this endless and
>futile quest of trying to "win" and to "be right" in such a petty little
>thing?
 
Its not me arguing the toss or making a big deal out of it. Computer memory has
values assigned to it whereas initialisation is what happens at power on. End.
Just because C++ uses a different definition doesn't change that fact nor does
it make my original post wrong.
 
>a bad thing, nor is it shameful. You don't have to always "win". You don't
>have to always "be right". You can perfectly well be mistaken, admit it,
>learn from the mistake, and nobody will ridicule you.
 
Oh bless, you're so kind.
Christian Gollwitzer <auriocus@gmx.de>: Jun 23 05:29PM +0200

>> initialisations.
 
> So the value doesn't get assigned to the memory. It just magically appears
> there?
 
Believe it or not, in some cases that is exactly what's happening. For
example, if you have a static file scope variable
 
static int x = 42;
 
int somefunc() {
}
 
then this might be translated into a section of the executable which
contains the static variables. Therefore, upon starting the program, the
values 42 will just "magically" be there (it comes with the code). There
is no explicut "MOV"-instructino or the like.
 
Of course, these things go beyond the C++ standard, and you should not
worry about them. The compiler will do the right thing for you.
 
Christian
Muttley@dastardlyhq.com: Jun 23 03:37PM

On Thu, 23 Jun 2022 17:29:18 +0200
 
>then this might be translated into a section of the executable which
>contains the static variables. Therefore, upon starting the program, the
>values 42 will just "magically" be there (it comes with the code). There
 
Yes, thats right, its all magic.
 
>is no explicut "MOV"-instructino or the like.
 
Nooooooo! Really?? Incredible!
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 04:46AM -0700

A week ago here in comp.lang.c++ I started a thread entitled "Can any tool catch this invalid memory access?".
 
One or two people said I should use valgrind, but valgrind is useless at detecting invalid access to static data or stack data. Valgrind is only effective at detecting invalid access to the heap.
 
Then I tried using g++ with the command line option "-fsanitize", and it works very well, it successfully flagged invalid access to an array on the stack.
 
Just today I tried "-D_GLIBCXX_DEBUG", and I'm actually a little mesmerized at how effective it is. It catches *everything*, especially invalid access to STL containers and also classes such as string_view.
 
So right now here's how I'm building my program:
 
g++ -o precompiler precompiler.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all
 
This is working very well for me, but if anyone has any more suggestions for even more extreme debugging, I'm all ears.
David Brown <david.brown@hesbynett.no>: Jun 23 02:18PM +0200

On 23/06/2022 13:46, Frederick Virchanza Gotham wrote:
 
> So right now here's how I'm building my program:
 
> g++ -o precompiler precompiler.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all
 
> This is working very well for me, but if anyone has any more suggestions for even more extreme debugging, I'm all ears.
 
Some problems can only be caught at run time, and you've got a good
selection of flags and tools for that.
 
But it is even better to catch problems at compile time. Make good use
of the compiler's static warning facilities. At a minimum, enable
"-Wall" and optimisation of at least "-O1". (With no optimisation, less
code analysis is done and fewer errors are spotted.) You should also
try "-Wextra", though some of the flags enabled there are controversial.
 
<https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html>
 
 
The new gcc "static analyzer" may also be helpful, depending on your code :
 
<https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html>
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 06:44AM -0700

On Thursday, June 23, 2022 at 12:46:34 PM UTC+1, I wrote:
 
> This is working very well for me, but if anyone has any more suggestions for even more extreme debugging, I'm all ears.
 
 
I'm still trying to find a debugger that will flag the error in the following code. I've written a function called "Increment_First_And_Print_Without_First" which takes an input such as the word "brush", and it prints out:
 
rush
crush
 
Inside the body of "Increment_First_And_Print_Without_First", I dereference an iterator to one-past-the-last, which is undefined behaviour. Here's how I build the following program:
 
g++ -o iterator_deref iterator_deref.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all
 
When I run the program, no error is flagged. No error is flagged in 'gdb' either. I haven't found any debugging tool that can find this error.
 
Here's the code:
 
#include <iostream>
#include <string>
#include <string_view>
#include <type_traits>
 
using namespace std;
 
void Increment_First_And_Print_Without_First(string &s)
{
if ( s.size() < 2u ) throw -1;
 
++( s[0u] );
 
// The next line has an invalid dereferencing of an iterator
cout << "The next line dereferences an end() pointer" << endl;
cout << string_view( &*(s.cbegin() + 1u), &*(s.cend()) ) << endl;
}
 
int main(void)
{
cout << "string::const_iterator is "
<< (is_same_v< string::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl;
 
cout << "string_view::const_iterator is "
<< (is_same_v< string_view::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl;
 
string str("brush");
 
Increment_First_And_Print_Without_First(str);
 
cout << str << endl;
}
 
On my x86_64 Ubuntu PC here, the output I get is:
 
string::const_iterator is NOT a simple pointer
string_view::const_iterator is just a raw pointer
The next line dereferences an end() pointer
rush
crush
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 07:01AM -0700

On Thursday, June 23, 2022 at 2:44:44 PM UTC+1, Frederick Virchanza Gotham wrote:
 
> When I run the program, no error is flagged. No error is flagged in 'gdb' either. I haven't found any debugging tool that can find this error.
 
 
Actually here's a smaller simpler program:
 
#include <iostream>
#include <string>
#include <string_view>
#include <type_traits>
 
using namespace std;
 
int main(void)
{
cout << "string::const_iterator is "
<< (is_same_v< string::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl;
 
cout << "string_view::const_iterator is "
<< (is_same_v< string_view::const_iterator, char const * > ? "just a raw pointer" : "NOT a simple pointer") << endl;
 
string s("brush");
 
cout << string_view( &*(s.cbegin() + 1u), &*(s.cend() + 876u) ) << endl;
}
 
 
On my x86_64 Ubuntu Linux PC, this prints garbage but doesn't crash. I was hoping "-fsanitize" would catch the "+876" on the last line.
David Brown <david.brown@hesbynett.no>: Jun 23 04:03PM +0200

On 23/06/2022 15:44, Frederick Virchanza Gotham wrote:
 
> Inside the body of "Increment_First_And_Print_Without_First", I dereference an iterator to one-past-the-last, which is undefined behaviour. Here's how I build the following program:
 
> g++ -o iterator_deref iterator_deref.cpp -std=c++20 -ggdb3 -D_GLIBCXX_DEBUG -fsanitize=address,leak,undefined -fsanitize=pointer-compare -fsanitize=pointer-subtract -fstack-protector-all
 
> When I run the program, no error is flagged. No error is flagged in 'gdb' either. I haven't found any debugging tool that can find this error.
 
You are dereferencing the iterator, then taking its address. In C,
"&*x" is treated exactly as "x" except for constraint checking and
making the result an lvalue. So it is defined behaviour, even if "x"
were a null pointer. I don't see anything matching that (section
6.5.3.2p3) in the C++ standards. But it is possible that the "&*" pair
gets removed early in the compilation process, and is not seen by any of
the sanitizers or checkers. After all, you are not really dereferencing
the iterator - you are taking the address of the dereference.
 
 
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Jun 23 07:47AM -0700

On Thursday, June 23, 2022 at 3:03:31 PM UTC+1, David Brown wrote:
 
> You are dereferencing the iterator, then taking its address.
 
 
The expression, "s.cend()", is of type string::const_iterator, which is not a simple pointer (or at least it's not a simple pointer on my g++ compiler).
 
 
> In C, "&*x" is treated exactly as "x" except for constraint checking and
> making the result an lvalue.
 
 
I think you mean R-value.
 
I'm only concerned with C++ right now. Is there anything in the C++ standard that says you can dereference an invalid pointer so long as you immediately take the address of the pointed-to thing? Is the following program valid in C++20?
 
int main(void)
{
char *p = nullptr;
 
&*p;
}
 
By the way "&*" has an observable effect when used on an array, for example:
 
Define an array: char buf[64];
 
The expression "buf" is an L-value of type "char[64]"
 
The expression "&*buf" is an R-value of type "char*"
 
 
> gets removed early in the compilation process, and is not seen by any of
> the sanitizers or checkers. After all, you are not really dereferencing
> the iterator
 
 
Yes I am dereferencing the iterator. No doubt about it -- the iterator is getting dereferenced.
 
 
> you are taking the address of the dereference.
 
 
This also happens.
Juha Nieminen <nospam@thanks.invalid>: Jun 23 03:04PM

> One or two people said I should use valgrind, but valgrind is useless at detecting invalid access to static data or stack data. Valgrind is only effective at detecting invalid access to the heap.
 
While calling valgrind "useless" is technically correct in this context,
to catch this kind of mistake, I think it's quite a strong word with quite
a negative connotation, which I feel is a bit unfair towards the program.
The program itself is great for debugging the things that it does support.
It can't catch (most) out-of-bounds accesses on the stack because that's
quite literally impossible (without the help of the compiler), but you
merely need to be aware of that.
 
I think it would be nicer to just say that "valgrind can't detect these
types of error", and not dismiss its usefulness in the things it has
actually been designed to test (ie. heap allocations and accesses).
 
> Just today I tried "-D_GLIBCXX_DEBUG", and I'm actually a little mesmerized at how effective it is. It catches *everything*, especially invalid access to STL containers and also classes such as string_view.
 
To be more precise, it catches (most) wrong uses of the standard library.
(That's what the "GLIBCXX" is referring to. It's a macro used in the standard
library implementation used by gcc.)
 
It won't catch errors that are not related to the standard library
utilities.
Juha Nieminen <nospam@thanks.invalid>: Jun 23 03:07PM


> cout << string_view( &*(s.cbegin() + 1u), &*(s.cend() + 876u) ) << endl;
> }
 
> On my x86_64 Ubuntu Linux PC, this prints garbage but doesn't crash. I was hoping "-fsanitize" would catch the "+876" on the last line.
 
Have you tried to run the program through valgrind? Because it has been
designed precisely for that (you are accessing dynamically allocated
memory out of bounds).
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.

Monday, June 20, 2022

Fwd: The Swan Project



Sent from my iPad

Begin forwarded message:

From: Shu Gong <edg1996@yahoo.com>
Date: June 20, 2022 at 9:42:37 AM CDT
To: TINA SOONG <tsoongtotherim@aol.com>
Subject: The Swan Project

https://youtu.be/hE1enPDh3nM


Sent from my iPad

Tuesday, June 14, 2022

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

olcott <NoOne@NoWhere.com>: Jun 13 10:41PM -0500

On 6/13/2022 3:46 PM, Juha Nieminen wrote:
 
> When it comes to theoretical computer science, you might want to ask
> computer scientists rather than software engineers. *Sometimes* those
> two coincide but not nearly always.
 
The very weird problem in this case is that software engineering has
caught a very subtle mistake that computer science textbooks have been
making regarding the halting problem. My paper details this mistake in
Appendix I.
 
Without getting into the details that are outside of the scope of this
forum all that I really need here is a step-by-step confirmation that
H(P,P) correctly determines that the correct x86 emulation of its input
would never reach the "ret" instruction of this input.
*I know that it is already as obvious as Hell*
 
#include <stdint.h>
#define u32 uint32_t
 
void P(u32 x)
{
if (H(x, x))
HERE: goto HERE;
return;
}
 
int main()
{
Output("Input_Halts = ", H((u32)P, (u32)P));
}
 
_P()
[00001352](01) 55 push ebp
[00001353](02) 8bec mov ebp,esp
[00001355](03) 8b4508 mov eax,[ebp+08]
[00001358](01) 50 push eax // push P
[00001359](03) 8b4d08 mov ecx,[ebp+08]
[0000135c](01) 51 push ecx // push P
[0000135d](05) e840feffff call 000011a2 // call H
[00001362](03) 83c408 add esp,+08
[00001365](02) 85c0 test eax,eax
[00001367](02) 7402 jz 0000136b
[00001369](02) ebfe jmp 00001369
[0000136b](01) 5d pop ebp
[0000136c](01) c3 ret
Size in bytes:(0027) [0000136c]
 
_main()
[00001372](01) 55 push ebp
[00001373](02) 8bec mov ebp,esp
[00001375](05) 6852130000 push 00001352 // push P
[0000137a](05) 6852130000 push 00001352 // push P
[0000137f](05) e81efeffff call 000011a2 // call H
[00001384](03) 83c408 add esp,+08
[00001387](01) 50 push eax
[00001388](05) 6823040000 push 00000423 // "Input_Halts = "
[0000138d](05) e8e0f0ffff call 00000472 // call Output
[00001392](03) 83c408 add esp,+08
[00001395](02) 33c0 xor eax,eax
[00001397](01) 5d pop ebp
[00001398](01) c3 ret
Size in bytes:(0039) [00001398]
 
machine stack stack machine assembly
address address data code language
======== ======== ======== ========= =============
...[00001372][0010229e][00000000] 55 push ebp
...[00001373][0010229e][00000000] 8bec mov ebp,esp
...[00001375][0010229a][00001352] 6852130000 push 00001352 // push P
...[0000137a][00102296][00001352] 6852130000 push 00001352 // push P
...[0000137f][00102292][00001384] e81efeffff call 000011a2 // call H
 
Begin Local Halt Decider Simulation Execution Trace Stored at:212352
 
// H emulates the first seven instructions of P
...[00001352][0021233e][00212342] 55 push ebp // enter P
...[00001353][0021233e][00212342] 8bec mov ebp,esp
...[00001355][0021233e][00212342] 8b4508 mov eax,[ebp+08]
...[00001358][0021233a][00001352] 50 push eax // push P
...[00001359][0021233a][00001352] 8b4d08 mov ecx,[ebp+08]
...[0000135c][00212336][00001352] 51 push ecx // push P
...[0000135d][00212332][00001362] e840feffff call 000011a2 // call H
 
// The emulated H emulates the first seven instructions of P
...[00001352][0025cd66][0025cd6a] 55 push ebp // enter P
...[00001353][0025cd66][0025cd6a] 8bec mov ebp,esp
...[00001355][0025cd66][0025cd6a] 8b4508 mov eax,[ebp+08]
...[00001358][0025cd62][00001352] 50 push eax // push P
...[00001359][0025cd62][00001352] 8b4d08 mov ecx,[ebp+08]
...[0000135c][0025cd5e][00001352] 51 push ecx // push P
...[0000135d][0025cd5a][00001362] e840feffff call 000011a2 // call H
Local Halt Decider: Infinite Recursion Detected Simulation Stopped
 
It is completely obvious that when H(P,P) correctly emulates its input
that it must emulate the first seven instructions of P. Because the
seventh instruction of P repeats this process we know with complete
certainty that the correct and complete emulation of P by H would never
reach the final "ret" instruction of P, thus never halts.
 
...[00001384][0010229e][00000000] 83c408 add esp,+08
...[00001387][0010229a][00000000] 50 push eax
...[00001388][00102296][00000423] 6823040000 push 00000423 //
"Input_Halts = "
---[0000138d][00102296][00000423] e8e0f0ffff call 00000472 // call Output
Input_Halts = 0
...[00001392][0010229e][00000000] 83c408 add esp,+08
...[00001395][0010229e][00000000] 33c0 xor eax,eax
...[00001397][001022a2][00100000] 5d pop ebp
...[00001398][001022a6][00000004] c3 ret
Number of Instructions Executed(15892) = 237 pages
 
 
 
 
Halting problem undecidability and infinitely nested simulation (V5)
 
https://www.researchgate.net/publication/359984584_Halting_problem_undecidability_and_infinitely_nested_simulation_V5
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Muttley@dastardlyhq.com: Jun 14 08:45AM

On Mon, 13 Jun 2022 20:46:45 -0000 (UTC)
 
>When it comes to theoretical computer science, you might want to ask
>computer scientists rather than software engineers. *Sometimes* those
>two coincide but not nearly always.
 
Software engineer usually implies some form of CS knowledge/training whereas
programmer or worse coder usually means someone self taught or moved over
from another area with no formal training. Though as with most definitions
its various shades of grey.
 
These days though with every 3rd idiot trying to "code" (ie write some mickey
most HTML/javascript) because they keep getting told it by vested interests
wanting to sell their latest low/no-code software or clueless government types
trying to push unsuitable people into IT we're going to find ever more of
them in the industry with ever lower software standards.
olcott <NoOne@NoWhere.com>: Jun 14 09:23AM -0500

> wanting to sell their latest low/no-code software or clueless government types
> trying to push unsuitable people into IT we're going to find ever more of
> them in the industry with ever lower software standards.
 
Here are the detailed required credentials:
To fully understand this paper a software engineer must be an expert in:
the C programming language, the x86 programming language, exactly how C
translates into x86 and the ability to recognize infinite recursion at
the x86 assembly language level. No knowledge of the halting problem is
required.
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Muttley@dastardlyhq.com: Jun 14 03:26PM

On Tue, 14 Jun 2022 09:23:15 -0500
>the x86 programming language
 
Most people call it assembler. But I guess you have to be different.
olcott <NoOne@NoWhere.com>: Jun 14 10:53AM -0500

> olcott <NoOne@NoWhere.com> wrote:
>> the x86 programming language
 
> Most people call it assembler. But I guess you have to be different.
 
Most specifically is the the x86 assembly language contained in the COFF
object files that are generated by the Microsoft C compiler when
executed in 32-bit mode. The x86utm operating system that I wrote takes
a 32-bit mode COFF object file as input.
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Muttley@dastardlyhq.com: Jun 14 04:00PM

On Tue, 14 Jun 2022 10:53:51 -0500
>object files that are generated by the Microsoft C compiler when
>executed in 32-bit mode. The x86utm operating system that I wrote takes
>a 32-bit mode COFF object file as input.
 
Thats not a language, thats machine code.
olcott <NoOne@NoWhere.com>: Jun 14 11:41AM -0500

>> executed in 32-bit mode. The x86utm operating system that I wrote takes
>> a 32-bit mode COFF object file as input.
 
> Thats not a language, thats machine code.
 
I adapted the x86 emulator to dis-assemble the machine language so that
all the x86 source in the whole COFF file can be seen. The x86 execution
trace also shows the x86 source-code of every line that is emulated.
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Juha Nieminen <nospam@thanks.invalid>: Jun 14 04:57PM

> programmer or worse coder usually means someone self taught or moved over
> from another area with no formal training. Though as with most definitions
> its various shades of grey.
 
I think "software engineer" usually refers to a job title, not an acadmic
title (those would be MSc, PhD, etc.)
 
It's perfectly possible to be a really competent software engineer and have
absolutely no idea what "computational complexity" means.
"daniel...@gmail.com" <danielaparker@gmail.com>: Jun 14 10:09AM -0700

On Tuesday, June 14, 2022 at 12:57:54 PM UTC-4, Juha Nieminen wrote:
 
> It's perfectly possible to be a really competent software engineer and have
> absolutely no idea what "computational complexity" means.
 
The word "engineer" has unfortunately been much debased in the computer
industry, particularly with that absurd title "Microsoft Solution Engineer".
Real engineers were actually personally responsible for their work.
 
Daniel
olcott <NoOne@NoWhere.com>: Jun 14 12:09PM -0500

On 6/14/2022 11:57 AM, Juha Nieminen wrote:
> title (those would be MSc, PhD, etc.)
 
> It's perfectly possible to be a really competent software engineer and have
> absolutely no idea what "computational complexity" means.
 
To fully understand this paper a software engineer must be an expert in:
the C programming language, the x86 programming language, exactly how C
translates into x86 and the ability to recognize infinite recursion at
the x86 assembly language level. No knowledge of the halting problem is
required.
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
red floyd <no.spam.here@its.invalid>: Jun 14 10:44AM -0700

On 6/13/2022 1:46 PM, Juha Nieminen wrote:
 
> When it comes to theoretical computer science, you might want to ask
> computer scientists rather than software engineers. *Sometimes* those
> two coincide but not nearly always.
 
Please remove comp.lang.c++ from this thread. It is off topic and
clogging up c.l.c++. Thank you.
Mr Flibble <flibble@reddwarf.jmc>: Jun 14 06:44PM +0100

On Tue, 14 Jun 2022 11:41:22 -0500
> that all the x86 source in the whole COFF file can be seen. The x86
> execution trace also shows the x86 source-code of every line that is
> emulated.

Disassembly isn't source code. Also, it is quite telling when you say
"no knowledge of the halting problem is required": this is correct as
what you have has nothing to do with the halting problem as your H
isn't a halting decider: it is an olcott simulation detector, a fairly
useless widget.
 
/Flibble
Richard Damon <Richard@Damon-Family.org>: Jun 13 08:40PM -0400

On 6/13/22 2:45 PM, olcott wrote:
> complete emulation of the input would never stop running, or reach its
> "ret" instruction then the SHD aborts its emulation and correctly
> returns 0.
 
You keep on missing that no such pattern exists in the emulation of
P(P), as if H has a pattern that is seees in P(P) and aborts its
simulation because of that, then when P(P) calls H(P,P) that H will
emulate for a while, abort its emulation, and then return 0 to P which
will Halt.
 
Thus the P(P) when built with an H with that pattern shows that the
pattern is not a correct non-halting behavior pattern, as a program with
that pattern halts.
 
So, a SHD based on that rule will just emulate for ever, doing a correct
and complete emulatin, but not giving the 0 answers, because if at any
finite point in time it aborts, it changes P to be Halting.
 
FAIL.
 
olcott <NoOne@NoWhere.com>: Jun 13 07:47PM -0500

On 6/13/2022 7:40 PM, Richard Damon wrote:
>> returns 0.
 
> You keep on missing that no such pattern exists in the emulation of
> P(P),
 
Even Flibble see the pattern.
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Richard Damon <Richard@Damon-Family.org>: Jun 13 09:15PM -0400

On 6/13/22 8:47 PM, olcott wrote:
>>> returns 0.
 
>> You keep on missing that no such pattern exists in the emulation of P(P),
 
> Even Flibble see the pattern.
 
Can you point to the message where he actually says that? (since he
realized that halt decider doesn't actually need to simulate its input,
only does it by choise in your case)
Paul N <gw7rib@aol.com>: Jun 14 04:47AM -0700

OK, I'll bite. Apologies to all those who would rather this conversation was not here.
 
Firstly, I think it needs to be said that the Halting Problem only applies to an infinite machine. If a computer has only a finite number of states (as so many of them do) and moves between them at a constant rate, then a suitable emulator could work out whether a program terminates simply by looking for a repeated state. Either the program terminates, or after N states you must be back to a state you have already had, where N is the number of possible states. This may be where Mr Olcott is going wrong.
 
 
On Monday, June 13, 2022 at 7:46:22 PM UTC+1, olcott wrote:
> [00001362](03) 83c408 add esp,+08
> [00001365](02) 85c0 test eax,eax
> [00001367](02) 7402 jz 0000136b
 
This is a conditional jump past the next instruction
 
> [00001369](02) ebfe jmp 00001369
 
Yes, if the program gets to this line, it will go into an infinite loop. We can't tell just from this code whether or not this will happen, as it is dependent on the jump above which is dependent on H, which you haven't shown us (at least not in this post), so the code itself does not answer the question.
 
> seventh instruction of P repeats this process we can know with complete
> certainty that the emulated P never reaches its final "ret" instruction,
> thus never halts.
 
Yes, it is clear to us humans watching it that the program is repeating itself. Thus we can appreciate that it will never reach the final "ret" - indeed, it won't even get to the infinite loop identified above. But does the computer itself know this? If the emulator simply emulates the instructions given, it will not realise that it is doing the same thing over and over again. If it does look out for this, spotting a repeated state, then it can tell that the program under consideration will not halt. The answer to whether it spots this lies in the emulator, which you haven't shown the code for.
 
However, an emulator which does this is not accurately emulating the program in question. The emulator is stopping and saying it has found an infinite loop, whereas the program itself would do no such thing and would run forever. Thus their behaviours are different.
 
You say that you have come to comp.lang.c and comp.lang.c++ is to check the points which relate to the language. I think what I have written above is probably about as much as you will be able to get from these groups. Your understanding of the language points appears to be correct.
olcott <NoOne@NoWhere.com>: Jun 14 09:30AM -0500

On 6/14/2022 6:47 AM, Paul N wrote:
>> certainty that the emulated P never reaches its final "ret" instruction,
>> thus never halts.
 
> Yes, it is clear to us humans watching it that the program is repeating itself. Thus we can appreciate that it will never reach the final "ret" - indeed, it won't even get to the infinite loop identified above. But does the computer itself know this?
 
H knows this and returns 0 on the basis.
 
> If the emulator simply emulates the instructions given, it will not realise that it is doing the same thing over and over again.
 
H has code that recognizes infinite behavior patterns.
 
> If it does look out for this, spotting a repeated state, then it can tell that the program under consideration will not halt. The answer to whether it spots this lies in the emulator, which you haven't shown the code for.
 
I have re-engineered the code to make it a pure function of its inputs.
Not knowing how to do this prevented me from publishing the code.
 
I have updated the algorithm so that it is a pure function of its
inputs. As soon as P calls H for the first time, H (knowing its own
machine address) is able to look though the prior execution trace and
see that P is calling H with the same arguments that it was called
with and there are no instructions in P that would break this cycle.
 
> However, an emulator which does this is not accurately emulating the program in question. The emulator is stopping and saying it has found an infinite loop, whereas the program itself would do no such thing and would run forever. Thus their behaviours are different.
 
The criterion measure for a simulating halt decider (SHD)
When the correct partial x86 emulation of the input matches a
non-halting behavior pattern such that it correctly determines that a
complete emulation of the input would never stop running, or reach its
"ret" instruction then the SHD aborts its emulation and correctly
returns 0.
 
> You say that you have come to comp.lang.c and comp.lang.c++ is to check the points which relate to the language. I think what I have written above is probably about as much as you will be able to get from these groups. Your understanding of the language points appears to be correct.
 
Yes you did a very excellent job thanks.
Thus you agree that H(P,P)==0 is correct.
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Muttley@dastardlyhq.com: Jun 14 03:25PM

On Tue, 14 Jun 2022 04:47:35 -0700 (PDT)
>table emulator could work out whether a program terminates simply by lookin=
>g for a repeated state. Either the program terminates, or after N states yo=
>u must be back to a state you have already had, where N is the number of po=
 
That only holds if there's no external input which cannot be known in advance
that can affect its state.
olcott <NoOne@NoWhere.com>: Jun 14 10:36AM -0500

>> u must be back to a state you have already had, where N is the number of po=
 
> That only holds if there's no external input which cannot be known in advance
> that can affect its state.
 
P is the input to H and P is the input to P.
H uses a very powerful open source x86 emulator top emulate its input.
 
The criterion measure for a simulating halt decider (SHD)
When the correct partial x86 emulation of the input matches a
non-halting behavior pattern such that it correctly determines that a
complete emulation of the input would never stop running, or reach its
"ret" instruction then the SHD aborts its emulation and correctly
returns 0.
 
void P(u32 x)
{
if (H(x, x))
HERE: goto HERE;
return;
}
 
int main()
{
Output("Input_Halts = ", H((u32)P, (u32)P));
}
 
_P()
[00001352](01) 55 push ebp
[00001353](02) 8bec mov ebp,esp
[00001355](03) 8b4508 mov eax,[ebp+08]
[00001358](01) 50 push eax // push P
[00001359](03) 8b4d08 mov ecx,[ebp+08]
[0000135c](01) 51 push ecx // push P
[0000135d](05) e840feffff call 000011a2 // call H
[00001362](03) 83c408 add esp,+08
[00001365](02) 85c0 test eax,eax
[00001367](02) 7402 jz 0000136b
[00001369](02) ebfe jmp 00001369
[0000136b](01) 5d pop ebp
[0000136c](01) c3 ret
Size in bytes:(0027) [0000136c]
 
 
Halting problem undecidability and infinitely nested simulation (V5)
 
https://www.researchgate.net/publication/359984584_Halting_problem_undecidability_and_infinitely_nested_simulation_V5
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Juha Nieminen <nospam@thanks.invalid>: Jun 14 04:54PM

> the program terminates, or after N states you must be back to a
> state you have already had, where N is the number of possible
> states. This may be where Mr Olcott is going wrong.
 
It is my understanding that whenever a question is posed about an algorithm
or program in theoretical computer science, failure states caused by the
running environment (eg. running out of RAM) are not part of the scenario,
because that's irrelevant to the question at hand. In other words, we can
always assume there's no external factor interfering with the program.
 
For example, if the question is what's the computational complexity of a
particular sorting algorithm, the question always assumes that the running
environment doesn't pose any physical limits (eg. on memory amount). The
question becomes a bit meaningless if we had to assume some upper limit
in the running environment.
 
Rather obviously the famous Halting Problem isn't asking if a program will
halt or run forever in an x86-64 PC with 32 GB of RAM. That would make the
question meaningless.
 
Likewise if we are asking "does a program testing the Collatz conjecture
eventually end when it finds a counter-example?" we are not asking
"does the program eventually end with an 'out of memory' error because
it's being run in a computer with limited RAM?"
 
Incidentally, if the halting problem were answerable, that would
automatically solve some of the biggest mathematical conjectures
out there (like the Collatz conjecture).
olcott <NoOne@NoWhere.com>: Jun 14 12:08PM -0500

On 6/14/2022 11:54 AM, Juha Nieminen wrote:
 
> Incidentally, if the halting problem were answerable, that would
> automatically solve some of the biggest mathematical conjectures
> out there (like the Collatz conjecture).
 
There is a difference between undecidable:
Neither Boolean value is correct because the decision problem is
self-contradictory
 
and undecided: The decision problem requires information that is
currently unavailable.
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Jun 14 10:12AM -0700

> OK, I'll bite. Apologies to all those who would rather this conversation was not here.
 
olcott dominates comp.theory. You can interact with him there. You can
also see multiple years of his posting history.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
olcott <NoOne@NoWhere.com>: Jun 14 12:21PM -0500

On 6/14/2022 12:12 PM, Keith Thompson wrote:
>> OK, I'll bite. Apologies to all those who would rather this conversation was not here.
 
> olcott dominates comp.theory. You can interact with him there. You can
> also see multiple years of his posting history.
 
The people on comp.theory are unable to critique my work an the basis of
software engineering:
 
To fully understand this paper a software engineer must be an expert in:
the C programming language, the x86 programming language, exactly how C
translates into x86 and the ability to recognize infinite recursion at
the x86 assembly language level. No knowledge of the halting problem is
required.
 
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
Albert Arkwright <Albert.Arkwright@gmail.com>: Jun 14 06:28PM +0100

On 14/06/2022 18:21, olcott wrote:
 
> The people on comp.theory are unable to critique my work an the basis
> of software engineering:
 
They are too smart for you. They have known you for years and you are on
their kill-file for too long. It is a matter of time that C and C++
programmers will come to understand you more here and kill-file you
after they have reported you to "abuse@giganews.com". Enough is enough
and there is a limit how much they can take your crap.
olcott <NoOne@NoWhere.com>: Jun 14 12:40PM -0500

On 6/14/2022 12:28 PM, Albert Arkwright wrote:
> programmers will come to understand you more here and kill-file you
> after they have reported you to "abuse@giganews.com". Enough is enough
> and there is a limit how much they can take your crap.
 
Only people that baselessly reject what I say out-of-hand without review
come to that conclusion. Anyone that correctly reviews my claim
validates that it is correct.
 
On 6/14/2022 6:47 AM, Paul N wrote:
> Thus we can appreciate that it will never
> reach the final "ret" - indeed, it won't
> even get to the infinite loop identified above.
 
#include <stdint.h>
typedef void (*ptr)();
 
void P(ptr x)
{
if (H(x, x))
HERE: goto HERE;
return;
}
 
int main()
{
Output("Input_Halts = ", H(P, P));
}
 
_P()
[00001352](01) 55 push ebp
[00001353](02) 8bec mov ebp,esp
[00001355](03) 8b4508 mov eax,[ebp+08]
[00001358](01) 50 push eax // push P
[00001359](03) 8b4d08 mov ecx,[ebp+08]
[0000135c](01) 51 push ecx // push P
[0000135d](05) e840feffff call 000011a2 // call H
[00001362](03) 83c408 add esp,+08
[00001365](02) 85c0 test eax,eax
[00001367](02) 7402 jz 0000136b
[00001369](02) ebfe jmp 00001369
[0000136b](01) 5d pop ebp
[0000136c](01) c3 ret
Size in bytes:(0027) [0000136c]
 
It is completely obvious that when H(P,P) correctly emulates its input
that it must emulate the first seven instructions of P. Because the
seventh instruction of P repeats this process we know with complete
certainty that the correct and complete emulation of P by H would never
reach the final "ret" instruction of P, thus never halts.
 
 
 
 
--
Copyright 2022 Pete Olcott
 
"Talent hits a target no one else can hit;
Genius hits a target no one else can see."
Arthur Schopenhauer
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.