Friday, June 14, 2019

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

Nikki Locke <nikki@trumphurst.com>: Jun 14 10:23PM

Available C++ Libraries FAQ
 
URL: http://www.trumphurst.com/cpplibs/
 
This is a searchable list of libraries and utilities (both free
and commercial) available to C++ programmers.
 
If you know of a library which is not in the list, why not fill
in the form at http://www.trumphurst.com/cpplibs/cppsub.php
 
Maintainer: Nikki Locke - if you wish to contact me, please use the form on the website.
Juha Nieminen <nospam@thanks.invalid>: Jun 14 12:44PM

One thing I have always felt as being astonishingly under-defined
both in C and C++ is the concept of the stack, how much of it a
program has available, and especially, what happens if you run
out of it.
 
With dynamic memory allocation there's always a mechanism to deal
with the case that it fails: Either a null pointer is returned, or
an exception is thrown (depending on how exactly you are doing the
allocation). In either case, you can deal with the problem.
 
But what exactly happens if eg. your recursion level is too big and
you run out of stack space?
 
To be honest, I actually don't know what the standard says about this
(and in fact, this is a question I'm presenting here.) I would imagine
it's UB or implementation-defined behavior. And I'm guessing there's
simply no way of knowing *when* you are going to run out of stack
space, or to gracefully recover from it.
 
How exactly should programs be designed, if one wanted to be extra
paranoid about the possibility of running out of stack space? Or is
it something that there's simply no recourse against?
Paavo Helde <myfirstname@osa.pri.ee>: Jun 14 04:47PM +0300

On 14.06.2019 15:44, Juha Nieminen wrote:
 
> How exactly should programs be designed, if one wanted to be extra
> paranoid about the possibility of running out of stack space? Or is
> it something that there's simply no recourse against?
 
With MSVC++ one can make stack overflow a recoverable error, though it's
tricky to get it right and there is a danger to make the whole program
slower. A good starting point is the _resetstkoflw() documentation.
 
Another more portable solution is to measure the used stack space and
fail the operation if it is becoming too large. Measuring is actually
easy, you just compare the addresses of local variables in the current
function and in main() (or another thread start function).
 
In practice this measuring has to be done only in recursive functions
(direct or indirect), as long as one abstains from using evil things
like VLA-s and alloca().
 
What's more tricky is to figure out what the max stack size is and how
much of it would be used by non-recursive functions called from the
function doing the check. A cheap and dirty way is to just test it: run
the program so that it gets into infinite recursion. Find out the number
of recursions it was able to do before crashing, then insert a check,
leaving some safety margin.
 
As always, unit tests are invaluable for detecting regressions caused by
unrelated code changes.
David Brown <david.brown@hesbynett.no>: Jun 14 03:49PM +0200

On 14/06/2019 14:44, Juha Nieminen wrote:
> it's UB or implementation-defined behavior. And I'm guessing there's
> simply no way of knowing *when* you are going to run out of stack
> space, or to gracefully recover from it.
 
That's about right, yes. It is certainly possible for some
compiler/OS/cpu combinations to give you something extra here, but there
is no standard way to detect, predict, or handle out of stack failures.
 
This is intentional - run-time checking of stack problems would be very
difficult to specify at a language level, and could quickly be quite
costly (in terms of run-time and code space) to implement. Most
languages, I think, leave stack overflow as undefined and rely on the OS
to crash the program in a controlled manner via memory access faults.
 
 
> How exactly should programs be designed, if one wanted to be extra
> paranoid about the possibility of running out of stack space? Or is
> it something that there's simply no recourse against?
 
Standard techniques include:
 
1. Avoid recursion (direct or indirect).
2. If recursion is necessary (or it is the cleanest solution to a
problem), be /very/ careful that you know its depth will be limited.
3. Avoid VLAs, or make sure their size is within known limits.
4. Be careful with any large non-static local variables.
5. Use OS, compiler or target-specific features.
6. Test worst cases.
7. Use OS-specific calls or settings to reduce stack size during
testing, and increase it during production.
8. Use static stack size warnings or analysis.
9. Use dynamic stack checking and analysis.
 
 
Some possible gcc features that can help include:
 
-Wstack-usage=n
-fstack-check
-fstack-limit
-fstack-usage
 
Other compilers probably have features you can use.
Thomas David Rivers <rivers@dignus.com>: Jun 14 11:28AM -0400

Paavo Helde wrote:
 
> fail the operation if it is becoming too large. Measuring is actually
> easy, you just compare the addresses of local variables in the current
> function and in main() (or another thread start function).
 
That is not a portable solution as there is no requirement that the stack be
a contiguous "chunk" of memory. On the mainframe, for example, it is
not... so you can't tell
how much stack is "used" by comparing addresses of automatic variables.
 
- Dave Rivers -
 
--
rivers@dignus.com Work: (919) 676-0847
Get your mainframe programming tools at http://www.dignus.com
Melzzzzz <Melzzzzz@zzzzz.com>: Jun 14 05:38PM

> fail the operation if it is becoming too large. Measuring is actually
> easy, you just compare the addresses of local variables in the current
> function and in main() (or another thread start function).
 
That's undefined behavior.
 
 
--
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala
Keith Thompson <kst-u@mib.org>: Jun 14 11:58AM -0700

> a contiguous "chunk" of memory. On the mainframe, for example, it is
> not... so you can't tell
> how much stack is "used" by comparing addresses of automatic variables.
 
Even if the stack is contiguous, relational operators on pointers
to distinct objects have undefined behavior. It's likely to "work"
on most systems, but there's no guarantee. (And the stack could
grow either up or down.)
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
Thiago Adams <thiago.adams@gmail.com>: Jun 14 01:00PM -0700

On Friday, June 14, 2019 at 9:44:11 AM UTC-3, Juha Nieminen wrote:
> it's UB or implementation-defined behavior. And I'm guessing there's
> simply no way of knowing *when* you are going to run out of stack
> space, or to gracefully recover from it.
 
I believe some embedded hardware (like arduino) will not give you an
option. It doesn't make any check. The standard cannot help.

> How exactly should programs be designed, if one wanted to be extra
> paranoid about the possibility of running out of stack space? Or is
> it something that there's simply no recourse against?
 
 
if you don't allocate memory on the stack like VLAs and you don't have recursion, then you can statically determine how much stack memory each function needs.
(
See 13.13 Stack Usage Report
https://www.gimpel.com/html/manual.pdf
)
 
 
 
But some hardware have the same memory for stack and heap and the amount
of stack is variable.
The solution for extra safety is is not to use recursion and dynamic allocations.
Thiago Adams <thiago.adams@gmail.com>: Jun 14 01:04PM -0700

On Friday, June 14, 2019 at 10:50:07 AM UTC-3, David Brown wrote:
....
> testing, and increase it during production.
> 8. Use static stack size warnings or analysis.
> 9. Use dynamic stack checking and analysis.
 
What do you think about adding this one?
 
If your hardware shares the memory between heap and stack:
 
10. Don't use dynamic memory allocation
rick.c.hodgin@gmail.com: Jun 14 01:06PM -0700

On Friday, June 14, 2019 at 8:44:11 AM UTC-4, Juha Nieminen wrote:
> allocation). In either case, you can deal with the problem.
 
> But what exactly happens if eg. your recursion level is too big and
> you run out of stack space?
 
I don't see how this is a C/C++ issue at all. To my knowledge,
there is no guarantee of a stack in the C or C++ standards. They
are totally implementation-specific.
 
 
> How exactly should programs be designed, if one wanted to be extra
> paranoid about the possibility of running out of stack space? Or is
> it something that there's simply no recourse against?
 
If you are running out of stack space, re-write your algorithm.
In post-80386's expand-down segment designs where the initial
stack pointer points to a logical top-of-memory address, and
where paging is employed, it will never be an issue anyone has
to deal with again, unless your algorithm is broken.
 
The only time I've gotten stack exceptions since the 1990s is
when I've had an algorithm error.
 
--
Rick C. Hodgin
Paavo Helde <myfirstname@osa.pri.ee>: Jun 14 11:12PM +0300

On 14.06.2019 18:28, Thomas David Rivers wrote:
> a contiguous "chunk" of memory. On the mainframe, for example, it is
> not... so you can't tell
> how much stack is "used" by comparing addresses of automatic variables.
 
Right. That's why I said "more portable", not "portable".
Paavo Helde <myfirstname@osa.pri.ee>: Jun 14 11:17PM +0300

On 14.06.2019 20:38, Melzzzzz wrote:
>> easy, you just compare the addresses of local variables in the current
>> function and in main() (or another thread start function).
 
> That's undefined behavior.
 
Which behaves much better than stack overflow, on many common platforms.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 14 11:20PM +0200

On 14.06.2019 20:58, Keith Thompson wrote:
>> a contiguous "chunk" of memory. On the mainframe, for example, it is
>> not... so you can't tell
>> how much stack is "used" by comparing addresses of automatic variables.
 
I've seen this alleged fact before.
 
Then it was a misunderstanding of a machine that linked up stack frames
obtained from a single contiguous machine stack.
 
So a concrete link to the spec of "the mainframe" would be nice.
 
 
> to distinct objects have undefined behavior. It's likely to "work"
> on most systems, but there's no guarantee. (And the stack could
> grow either up or down.)
 
Pointers to distinct objects can be compared using std::greater & family.
 
On a segmented architecture one can imagine this being done by comparing
first segment selectors, and if they're equal, the segment offsets.
 
However, since that doesn't necessarily involve a translation to a
single linear address space, or the possibility of doing that, that
doesn't imply that forming the difference of two such pointers is
necessarily possible on all platforms.
 
 
Cheers!,
 
- Alf
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Jun 14 08:43AM -0400

On 6/12/2019 10:30 PM, Mr Flibble wrote:
> C# is a bag of .. BTW.
 
I find that to be an inaccurate assessment. C# is proving to be quite
a powerhouse language. It also uses keywords which make it clear in
source code what you're doing, such as "ref" and "out" to indicate which
parameters passed to a function are by reference, are output, etc.
 
It has a nice delegate syntax. You don't have to declare everything
before you use it. It's got an excellent debugger interface. Nice
built-in exception handling.
 
I wouldn't use it for high-speed apps, but for all business apps, all
GUI-based apps that aren't games, all general purpose apps... it looks
very nice. It's also VM-based, so it works across platforms without
changing a single line of C# code.
 
Not too shabby.
 
--
Rick C. Hodgin
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Jun 14 08:49AM -0400

On 6/13/2019 3:06 AM, Chris M. Thomasson wrote:
> Fwiw, Keep going on C Alive. I am willing to install, and give it a spin. :^)
> Send me an ISO.
 
 
Will do. I'm still working on developing those games I mentioned pre-
viously. It will probably be another year or so until I release CAlive
compared to my original timeline.
 
Life sometimes punches you in the face. It's one of the reasons we all
need Jesus. While this life is hard, the one He intended for us, and
the one He restores us to, is not. If you read Genesis 3:8, the Bible
refers to "the cool of the day" when Adam was in the garden.
 
The world God gave us was different from today's world. And He's return-
ing soon to restore that which was lost. All those who believe in Christ
before His return will be part of His millennial reign, and will be here
for the full 1,000 years in a body like the angels that never ages, never
tires, but is always at the top of its game. And that's just the pre-
cursor for what comes after in Heaven.
 
There's so much to learn from the Bible. I encourage you each to invest-
igate it. You've been lied to by the powers that be in this world about
what true Christianity is. It's all about Jesus, and having that daily,
personal relationship with Him. It's not religion. It's love applied
to one's life (with an exclamation point in bold face type).
 
--
Rick C. Hodgin
nobody@example.org (Scott): Jun 14 03:21PM

On Fri, 14 Jun 2019 08:43:49 -0400, "Rick C. Hodgin"
 
>You don't have to declare everything before you use it.
 
Many people, including myself, consider that to be a bad thing.
Jens Stuckelberger <Jens_Stuckelberger@nowhere.net>: Jun 14 03:28PM

In article <qdr3vq$c0e$1@dont-email.me>, Rick C. Hodgin
>All,
 
>I'll only be back here periodically.
 
You have an historic opportunity to take your religious drivel to
a different forum, and you are still intending to come back every so
often? Say it ain't so!
gazelle@shell.xmission.com (Kenny McCormack): Jun 14 03:55PM

In article <qe0eeb$3ov$1@news.albasani.net>,
 
> You have an historic opportunity to take your religious drivel to
>a different forum, and you are still intending to come back every so
>often? Say it ain't so!
 
Maybe I should start assuming the role formerly played by Rick.
 
I think I've got the drill down pretty well. Mostly just cut and paste
from various Babble sites and so on.
 
Let me think about this.
 
--
The randomly chosen signature file that would have appeared here is more than 4
lines long. As such, it violates one or more Usenet RFCs. In order to remain
in compliance with said RFCs, the actual sig can be found at the following URL:
http://user.xmission.com/~gazelle/Sigs/DanaC
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Jun 14 12:55PM -0400

On 6/14/2019 11:21 AM, Scott wrote:
> <rick.c.hodgin@gmail.com> wrote:
>> You don't have to declare everything before you use it.
> Many people, including myself, consider that to be a bad thing.
 
Many other people, including myself (and the authors of Go, including
Ken Thompson demonstrating his evolutionary view of the necessity of
forward declarations given modern CPU performance in compilation),
consider it to be a wonderful thing.
 
--
Rick C. Hodgin
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Jun 14 12:57PM -0400

On 6/14/2019 11:28 AM, Jens Stuckelberger wrote:
> You have an historic opportunity to take your religious drivel to
> a different forum, and you are still intending to come back every so
> often? Say it ain't so!
 
I have searched for a C# Usenet group but haven't found an active one.
I had not intended to be on Usenet for C# programming.
 
My interests in C/C++ have not changed, nor in CAlive. I just won't
be here reading on a regular basis.
 
--
Rick C. Hodgin
Bart <bc@freeuk.com>: Jun 14 06:07PM +0100

On 14/06/2019 16:21, Scott wrote:
> <rick.c.hodgin@gmail.com> wrote:
 
>> You don't have to declare everything before you use it.
 
> Many people, including myself, consider that to be a bad thing.
 
You mean not declaring things at all, or not declaring them before first
use?
 
I find lack of out-of-order declarations in C, to be a considerable
pain. Although I think this mainly applies to functions.
Martijn van Buul <pino@dohd.org>: Jun 14 07:22AM

* Keith Thompson:
 
> Agreed.
 
> One might argue that, for example, the fact that 4/3 yields 1 means
> the result is inaccurate.
 
But by that definition, 3/2 would also be inaccurate, while it isn't: it
can accurately be represented by a binary floating point.
 
--
Martijn van Buul - pino@dohd.org
Keith Thompson <kst-u@mib.org>: Jun 14 01:42AM -0700

>> the result is inaccurate.
 
> But by that definition, 3/2 would also be inaccurate, while it isn't: it
> can accurately be represented by a binary floating point.
 
To be clear, I wasn't making the argument that it's inaccurate; rather
the accurate result of 4/3 is 1, because it's an integer division, not a
floating-point division.
 
Similarly, the *accurate* result of 3/2 is 1 (and 3.0/2.0 is 1.5).
 
(The C standard describes integer division as "the algebraic quotient
with any fractional part discarded", but it could equivalently be
described without reference to discarding any fractional part.)
 
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 14 08:31AM -0400

On 6/14/19 3:22 AM, Martijn van Buul wrote:
>> the result is inaccurate.
 
> But by that definition, 3/2 would also be inaccurate, while it isn't: it
> can accurately be represented by a binary floating point.
 
Yes, in C 3/2 is 1, and 1.0 can be represented by binary floating point
- which is not what you meant - but it is what Keith was talking about.
The mathematical value of 3/2 is exactly representable in floating point
on any system where FLT_RADIX is a multiple of 2 (the most common values
are 2, 10, and 16 - I've never heard of a real system where it wasn't a
multiple of 2), and on such systems 3.0/2.0 == 1.5.
 
You need to clearly distinguish several things:
 
1. The mathematical value of 4/3, which is a number that when multiplied
by 3, gives 4.
 
2. The C value of 4/3, which is 1. When multiplied by 3, it gives 3.
 
3. The C value of 4.0/3.0, which is a rational number with a denominator
that is a integral power of FLT_RADIX. Unless FLT_RADIX is a multiple of
3 (I have actually heard of trinary systems, but they were highly
experimental, and I doubt that any such system hosts an implementation
of C), that value is NOT the same as the mathematical value - when
multiplied by 3 it does not give exactly 4.0, though it does come close.
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: