Sunday, July 26, 2020

Digest for comp.lang.c++@googlegroups.com - 12 updates in 1 topic

Melzzzzz <Melzzzzz@zzzzz.com>: Jul 26 04:29AM

> a system with a contiguous stack or not, as long as the system
> correctly supports automatic storage allocation and deallocation
> in some manner.
 
One way or another as long as it does not have deep recursion...
 
--
current job title: senior software engineer
skills: c++,c,rust,go,nim,haskell...
 
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi
bili naoruzani. -- Mladen Gogala
Scott Newman <scott69@gmail.com>: Jul 26 08:05AM +0200

>> You're apparently not kowning the difference between stack storage and
>> heap storage !!!
 
> It is called automatic storage and free store. Now, troll, fuck off.
 
It can be called whatever, hopefully the one using the words knows
what it means; but you don't.
"Öö Tiib" <ootiib@hot.ee>: Jul 25 11:23PM -0700

On Saturday, 25 July 2020 04:10:36 UTC+3, Keith Thompson wrote:
 
> Code that assumes that there's such a thing as "the stack" is likely
> to be (a) non-portable to exotic platforms and (b) unnecessarily
> low-level.
 
The tool behaves like its "automatic storage" is endless and does
outright anything when it overflows.
So it is somehow programmer's responsibility to ensure that
there is sufficient automatic storage. How can programmer honor
those obligations without going unnecessarily low-level?
aotto1968 <aotto1968@t-online.de>: Jul 26 09:45AM +0200

ok - it seems that "c" and "cP" using the SAME constructor…
 
"c" is using the STACK memory and cP is using the HEAP memory…
 
Question can I overload "new"
-> https://www.geeksforgeeks.org/overloading-new-delete-operator-c/
to set a flag that cP was created with new?
 
 
int MQ_CDECL main(int argc, MQ_CST argv[]) {
MqC c;
auto cP = new MqC();
cP->ObjLog();
try {
MqBufferLC args = {argc, argv};
 
c.ConfigSetName("MyClient");
c.LinkCreate(&args);
c.SendSTART();
c.SendEND_AND_WAIT("HLWO");
std::cout << c.ReadC() << std::endl;
 
} catch (const std::exception& e) {
 
c.ErrorCatch(e);
}
c.Exit();
}
David Brown <david.brown@hesbynett.no>: Jul 26 01:02PM +0200

On 26/07/2020 00:31, Keith Thompson wrote:
>> somewhat valid.
 
> You're using "standard" here to mean "conventional". Of course the
> language standard says nothing about this.
 
Yes. I hope that didn't cause any confusion.
 
> call a function, space for its local variables is allocated
> by the equivalent of malloc or new, and returning from a
> function deallocates space by the equivalent of free or delete.
 
That's my first group. Such mainframes are ancient systems. They are
still some in use - there are perhaps even a few that are still
produced. But they are used in critical systems - systems that must
work correctly without pause over years or decades. Little completely
/new/ software is made for these old systems - primarily code for them
would be maintaining or expanding existing code. And the people
programming or administrating these machines don't use some code they
found off github - the people writing code that runs on these systems
/know/ they are doing that.
 
More modern mainframes, based on modern ISAs like Power, x86-64, SPARC,
etc., are a different matter. But on these systems you have will
typically have conventional stacks. In fact, many new mainframe
installations are primarily as hosts for Linux virtual machines, and
thus the coding is normal Linux programming with conventional stacks.
 
(Mainframes are not something I work with, so any corrections to what I
write would be valued.)
 
> I wouldn't bet against such a mechanism becoming popular again in
> the future. C++ code that doesn't go out of its way to depend on
> implementation-specific details shouldn't even notice the difference.
 
(I agree that C++ code should not see the details of any differences
here, unless it is very specialised for some purpose.)
 
I'd be surprised to see it become popular again. There are potential
security and reliability benefits from having function stack frames
allocated as separate blocks, as well as the possibility of more
efficient use of memory (especially in multi-threaded or coroutine
environments). But the costs in efficiency of the code are far from
insignificant unless you have dedicated hardware support - and "normal"
processors do not have that. You can get most of the benefits of
growable stacks on most systems by just using the OS's virtual memory
system, which already exist. And if you need something more
sophisticated, split stacks offer a better solution than heap-allocated
function stack frames.
 
Still, predictions are hard, especially about the future. The computing
world has gone from early days of trying out a wide variety of hardware
systems, to consolidating on "C friendly" architectures. But as such a
high proportion of software these days is written in higher level
languages, the details of the underlying architectures have become less
and less relevant. So maybe new architectures will change this.
 
> Sometimes you might need to work with a subset implementation and
> work around missing features. (I suspect that C subsets are more
> common than C++ subsets for such systems.)
 
On some small microcontrollers, automatic storage is implemented
primarily as static addresses in ram. To do this, the toolchain has to
understand the reentrancy of functions to know that the function (or at
least the automatic variables) cannot be "live" more than once at a
time. This is done with a combination of compiler extensions to mark
functions as reentrant or not (often the default is "not") and
whole-program optimisation. Smart optimisation and lifetime analysis
lets the compiler/linker overlap these static areas to reduce ram usage.
 
Yes, C is usually used on such systems, rather than C++. But sometimes
C++ is used too. And yes, you usually have a variety of limitations and
non-conformity. (For C++, for example, you can be confident that
exceptions and RTTI are not supported.)
 
Again, the point is that you know you are working on such systems.
Conversely, if you don't know that you are writing code for something
like this, you are not - and can therefore assume you have a more
"normal" target.
 
> duration than for objects allocated via new/malloc. If your code
> runs on a system where that isn't true, but the system is still
> conforming, your program won't break.
 
Yes. (It's better to be potentially a little less efficient than a
little less correct!)
 
> activation frames on a heap. But even if you're certain that your
> code will only run on conventional systems, I can't think of any
> good reason to make your code rely on those assumptions.
 
It's surely going to be undefined behaviour on all systems? Of course,
that doesn't mean it won't work "as expected" on most systems, and you
can usually convert the addresses to uintptr_t and do the comparisons.
 
I agree entirely that your code shouldn't be using code like that - it's
unlikely to make sense, and isn't necessarily going to be stable. The
relationship between source code functions and local variables, and
their actual implementation, is very far from obvious with modern
optimising compilers.
 
(Implementations of functions like memcpy and memmove can be interested
in this sort of thing, but as standard library functions, these
implementations get to know more about the system details and can
"cheat" as necessary.)
 
 
> On the other hand, if you're examining object addresses in a
> debugger, it's perfectly reasonable to make use of whatever you
> know about the system.
 
Yes.
 
> a system with a contiguous stack or not, as long as the system
> correctly supports automatic storage allocation and deallocation
> in some manner.
 
Agreed.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jul 26 01:17PM

On Sat, 2020-07-25, Paavo Helde wrote:
> should have a special method, e.g. static A::Create() which calls 'new
> A' and sets a bit marking that a 'delete' call is needed to destroy it.
> A more general approach would use a customizable deleter.
 
My hunch is the OP has a fundamental design error, and if that one is
fixed he doesn't need is_on_heap(), a flag in the object, or a custom
deleter.
 
Finding out what that error is would be hard, though.
 
But as a rule, if you look at a pointer or reference to an object, you
should (as the author) be able to tell, statically, who owns the
object. And the owner is responsible for deleting it.
 
This rules out e.g. functions like foo(Bar*), where foo sometimes
takes over ownership of the Bar, and sometimes not.
 
Exceptions to that rule are rare IME, and most of those exceptions can
be handled with std::shared_ptr.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Bo Persson <bo@bo-persson.se>: Jul 26 04:59PM +0200

On 2020-07-26 at 13:02, David Brown wrote:
 
> That's my first group. Such mainframes are ancient systems. They are
> still some in use - there are perhaps even a few that are still
> produced.
 
The lastest of these ancient systems were introduced at the end of 2019:
 
https://en.wikipedia.org/wiki/IBM_z15_(microprocessor)
 
> work correctly without pause over years or decades. Little completely
> /new/ software is made for these old systems - primarily code for them
> would be maintaining or expanding existing code.
 
"Expanding" existing code includes adding server support for phone apps
and webb services. That's totally new code. And lots of it.
 
I recently worked for a bank, where we were about 500 people doing that.
 
 
> programming or administrating these machines don't use some code they
> found off github - the people writing code that runs on these systems
> /know/ they are doing that.
 
True, that. :-)
Paavo Helde <eesnimi@osa.pri.ee>: Jul 26 06:43PM +0300

26.07.2020 16:17 Jorgen Grahn kirjutas:
 
> But as a rule, if you look at a pointer or reference to an object, you
> should (as the author) be able to tell, statically, who owns the
> object. And the owner is responsible for deleting it.
 
I suspect he has shared reference counted objects which are accessed via
smart pointers. I suspect what he now wants is to have some objects on
stack, but he still wants to access them via shared pointers, presumably
because all interfaces are using smart pointers.
 
An easy way to solve this would abandon objects on stack. Allocate them
on heap always and use smart pointers always. Problem solved. Deal with
the lost microseconds on dynamic allocation only when the profiler shows
it's a bottleneck there.
David Brown <david.brown@hesbynett.no>: Jul 26 06:25PM +0200

On 26/07/2020 16:59, Bo Persson wrote:
>> produced.
 
> The lastest of these ancient systems were introduced at the end of 2019:
 
> https://en.wikipedia.org/wiki/IBM_z15_(microprocessor)
 
Yes, sure - but are these systems using function stack frames that are
allocated in lumps from the heap for each function call, or are they
using conventional stacks?
 
 
> "Expanding" existing code includes adding server support for phone apps
> and webb services. That's totally new code. And lots of it.
 
> I recently worked for a bank, where we were about 500 people doing that.
 
Also, are these running on mainframe OS's directly, or are they on Linux
virtual machines (or are they on something else) ?
 
Bo Persson <bo@bo-persson.se>: Jul 26 10:14PM +0200

On 2020-07-26 at 18:25, David Brown wrote:
 
> Yes, sure - but are these systems using function stack frames that are
> allocated in lumps from the heap for each function call, or are they
> using conventional stacks?
 
The architecture doesn't have doesn't have a dedicated hardware stack
pointer, or push, pop, and call instructions (unlike the x86). Software
convention uses a register pointing to the current activation record
(more like a bp register). The compiler can set aside an area for these
records, but it is not really a stack.
 
 
>> I recently worked for a bank, where we were about 500 people doing that.
 
> Also, are these running on mainframe OS's directly, or are they on Linux
> virtual machines (or are they on something else) ?
 
The webserver runs on a Linux partition, but it is not emulated or
anything, but compiled for the z hardware. The advantage of running the
webserver on the mainframe is that it can communicate with the back
office systems and databases extremely fast. No network delays.
 
Technically, everything is virtualized as you first boot z/VM and then
start any number of z/OS, Linux, and other subsystems from there.
 
 
Bo Persson
David Brown <david.brown@hesbynett.no>: Jul 26 10:42PM +0200

On 26/07/2020 22:14, Bo Persson wrote:
> convention uses a register pointing to the current activation record
> (more like a bp register). The compiler can set aside an area for these
> records, but it is not really a stack.
 
I've worked with PowerPC microcontrollers - while not exactly the same
as Power, they share a lot of common ancestry and features. You can say
that is no dedicated stack pointer register - or you can say that /any/
GPR register (except 0) is a stack pointer. "Push" and "pop" are just
loads and stores with pre- or post- increment and decrement, using
whichever "stack pointer" register you want, and with the stack growing
upwards or downwards as you choose. "Call" is "branch and link", with
non-leaf functions starting with a "push link register" sequence. Local
data on the stack can be accessed from the "stack pointer" as just
register + index addressing. Any register can be used as an equivalent
to the BP on x86.
 
So you can choose to use a stack or not, and can easily have multiple
stacks (that would be nice for Forth). The details are left up to the
ABI, which is effectively an agreement between the OS, libraries, and
compilers. Since I have only used the microcontroller cores, I am only
familiar with the 32-bit EABI. There you have r1 dedicated as the
"stack pointer" with a conventional downward-growing stack. (There are
actually, I think, different variants of the EABI with slightly
different details matching different variants of the PPC cores, but
AFAIK they all use r1 as a stack pointer.)
 
However, I don't know if this also applies to programming on the Power
on zSeries machines.
 
>> virtual machines (or are they on something else) ?
 
> The webserver runs on a Linux partition, but it is not emulated or
> anything, but compiled for the z hardware.
 
That is what I thought. (No need to emulate it when it is a supported
processor type!)
 
> The advantage of running the
> webserver on the mainframe is that it can communicate with the back
> office systems and databases extremely fast. No network delays.
 
There will be many other advantages too, as compared to running Linux on
bog-standard x86 boxes (or even a Talos II Power-based server). You get
hot-plug and hot-replacement of everything, including cpus and ram, and
huge scalability. I have also read of records for the speed at which
new Linux partitions can be installed on these things.
 
> Technically, everything is virtualized as you first boot z/VM and then
> start any number of z/OS, Linux, and other subsystems from there.
 
OK, so z/OS is a guest OS, just like Linux? And the virtualisation is
of the level of, say, VMWare, VirtualBox or KVM, rather than emulation
like QEMU or "super chroot jail" like Linux Containers, Docker, or
Solaris Zones ? That is to say, each partition (if that is the correct
term) has its own kernel, with hardware interaction being handled by the
hypervisor (z/VM)?
 
(I'm sorry, this is getting a bit off-topic for this group, but it's
nice to learn a little from someone who has used these things.)
Manfred <invalid@add.invalid>: Jul 27 12:33AM +0200

On 7/26/20 9:45 AM, aotto1968 wrote:
 
> Question can I overload "new"
> -> https://www.geeksforgeeks.org/overloading-new-delete-operator-c/
> to set a flag that cP was created with new?
 
AFAIK you can't.
Overloading operator new is obviously possible, but in the overload you
only have access to the raw memory of the object, /before/ the
constructor is run, and you cannot pass arguments to the constructor
from there - it is an allocation function, the constructor is called by
the language.
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: