Saturday, June 20, 2020

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

boltar@nowhere.co.uk: Jun 16 09:04AM

On Tue, 16 Jun 2020 18:06:34 +1200
>> certain amount of imbalance occurs? When it does happen how long does it
>> take and is there a way to force it to happen?
 
>Have you learned how to count to three yet?
 
If you think a major rebalance would only involved updating 3 nodes then
you have no idea how balancing works.
Ian Collins <ian-news@hotmail.com>: Jun 16 06:06PM +1200

> itself after deletions. Does it happen after every erase or only after a
> certain amount of imbalance occurs? When it does happen how long does it
> take and is there a way to force it to happen?
 
Have you learned how to count to three yet?
 
--
Ian.
boltar@nowhere.co.uk: Jun 15 09:10AM

Morning
 
I'm finding it hard to find out if/how/when the standard map rebalances
itself after deletions. Does it happen after every erase or only after a
certain amount of imbalance occurs? When it does happen how long does it
take and is there a way to force it to happen?
 
Cheers
Juha Nieminen <nospam@thanks.invalid>: Jun 17 06:41AM


>>Have you learned how to count to three yet?
 
> If you think a major rebalance would only involved updating 3 nodes then
> you have no idea how balancing works.
 
Rebalancing a binary tree (such as a red-black tree) requires updating
O(log(n)) nodes. Most usually approximately 2*log(n) nodes (no big-O).
 
So if your tree has 100 million nodes, rebalancing it after an insertion
or deletion requires updating about 54 nodes (give or take).
Ben Bacarisse <ben.usenet@bsb.me.uk>: Jun 13 11:11AM +0100


> Chris Thomasson, I wanted to get your input.
 
You should consider using email. This is a group.
 
--
Ben.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 15 03:27PM -0700

>> Here's a challenge for you: a binary file has already been loaded into
>> memory, and P is a char* pointer, pointing into part of it that has this
>> stringtable data, very similar to your count/string pairs:
[...]
 
As a starter, take a look at DCOM:
 
https://en.wikipedia.org/wiki/Distributed_Component_Object_Model
 
Or Corba.
Scott Newman <scott69@gmail.com>: Jun 14 02:02PM +0200

If you're in a context where your authority isn't honored,
you're constantly trolling.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 14 11:50PM -0700

On 6/14/2020 11:45 PM, Chris M. Thomasson wrote:
> On 6/12/2020 8:10 PM, rick.c.hodgin@gmail.com wrote:
>> Chris Thomasson, I wanted to get your input.  Maybe there's already
>> a syntax to handle these cases in C or C++.
[...]
 
>         header_free(h);
 
>         if ((h = header_alloc(42)))
>         {
 
/// ARGH! I forgot to put in:
 
buf1 = h->get_buf();
 
 
> }
> _______________________________
 
> Help at all?
 
Sorry for the bug. Self slap here. Can you find any more? ;^)
 
Correction:
 
_______________________________
#include <iostream>
#include <cstddef>
#include <cstdlib>
#include <cstring>
 
 
struct header
{
std::size_t m_size;
 
char* get_buf()
{
return reinterpret_cast<char*>(this + sizeof(*this));
}
};
 
 
header* header_alloc(std::size_t size)
{
header* const h = reinterpret_cast<header*>(std::malloc(sizeof(*h) +
size));
 
if (h)
{
h->m_size = size;
}
 
return h;
}
 
 
void header_free(header* h)
{
std::free(h);
}
 
 
int main()
{
{
header* h = header_alloc(123);
 
if (h)
{
char* buf1 = h->get_buf();
 
std::strcpy(buf1, "Hello");
 
std::cout << "buf1 = " << buf1 << "\n";
std::cout << "h->m_size = " << h->m_size << "\n\n";
 
 
char* buf2 = h->get_buf();
 
std::strcat(buf2, " World");
 
std::cout << "buf2 = " << buf2 << "\n";
std::cout << "h->m_size = " << h->m_size << "\n\n";
 
header_free(h);
 
if ((h = header_alloc(42)))
{
buf1 = h->get_buf();
 
std::strcpy(buf1, "FortyTwo");
 
std::cout << "buf1 = " << buf1 << "\n";
std::cout << "h->m_size = " << h->m_size << "\n";
 
header_free(h);
}
}
}
 
return 0;
}
_______________________________
Paavo Helde <eesnimi@osa.pri.ee>: Jun 16 06:29PM +0300

16.06.2020 15:26 Manfred kirjutas:
 
> Cast operators are explicitly meant to tell the compiler: look, this
> pointer, irrespective of where it comes from, is a pointer to T, deal
> with it.
 
The proposal to legislate malloc and friends for object creation
"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0593r6.html"
contains explicit remark, stressing the opposite:
 
"Note that a pointer reinterpret_cast is not considered sufficient to
trigger implicit object creation."
 
I gather all this fuss is about allowing type-based alias analysis.
Reinterpret_cast works directly against this idea.
Scott Newman <scott69@gmail.com>: Jun 15 07:15PM +0200

> return reinterpret_cast<char*>(this) + sizeof(*this);
 
LOL, only esoteric idiots around here.
If that would make any difference than the code shown before ...
On which machine ? Never !
Juha Nieminen <nospam@thanks.invalid>: Jun 17 06:37AM

> Don't care for the spec. It works with any compiler and
> it will work with any compiler that will ever exist.
 
The problem is that if you trigger UB, the compiler is allowed to do
whatever it wants with it. Including not doing what you want.
Juha Nieminen <nospam@thanks.invalid>: Jun 17 06:47AM


>> The problem is that if you trigger UB, the compiler is allowed to
>> do whatever it wants with it. Including not doing what you want.
 
> Not in this case.
 
What do you mean? The compiler is *always* allowed to do whatever it wants
if something is UB.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 15 12:03AM -0700

I am worried about the header::get_buf member function:
 
struct header
{
std::size_t m_size;
 
char* get_buf()
{
return reinterpret_cast<char*>(this + 1);
}
};
 
 
Here is the full code:
__________________
#include <iostream>
#include <cstddef>
#include <cstdlib>
#include <cstring>
 
 
struct header
{
std::size_t m_size;
 
char* get_buf()
{
return reinterpret_cast<char*>(this + 1);
}
};
 
 
header* header_alloc(std::size_t size)
{
header* const h = reinterpret_cast<header*>(std::malloc(sizeof(*h) +
size));
 
if (h)
{
h->m_size = size;
}
 
return h;
}
 
 
void header_free(header* h)
{
std::free(h);
}
 
 
int main()
{
{
header* h = header_alloc(123);
 
if (h)
{
char* buf1 = h->get_buf();
 
std::strcpy(buf1, "Hello");
 
std::cout << "buf1 = " << buf1 << "\n";
std::cout << "h->m_size = " << h->m_size << "\n\n";
 
 
char* buf2 = h->get_buf();
 
std::strcat(buf2, " World");
 
std::cout << "buf2 = " << buf2 << "\n";
std::cout << "h->m_size = " << h->m_size << "\n\n";
 
header_free(h);
 
if ((h = header_alloc(42)))
{
buf1 = h->get_buf();
 
std::strcpy(buf1, "FortyTwo");
 
std::cout << "buf1 = " << buf1 << "\n";
std::cout << "h->m_size = " << h->m_size << "\n";
 
header_free(h);
}
}
}
 
return 0;
}
______________________
 
How infested with UB is this? Any bugs?
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 15 03:52PM -0700

On 6/15/2020 9:44 AM, Juha Nieminen wrote:
> pointers, requiring you to manually free the allocated memory
> (although it may well be that you deliberately extracted this code
> from its RAII context to simplify it for the sake of example).
 
I need at least one raii object that can wrap the existing code, to call
header_alloc on ctor, and header_free on dtor. The power of RAII is that
it can most likely be adapted to existing explicit apis, create/destroy.
Automate it. One of my favorite examples is good ol' ScopeGuard. :^)
 
 
> functions to be exited from pretty much anywhere).
 
> For very small programs it may be completely fine, though. No need
> to over-engineer it if you never intend to use it in a larger program.
 
raii would not hurt here, imagine that the code is as it is. Well, we
can wrap it up. Imvho, its a nice convenient feature of C++.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Jun 16 03:33PM -0700

On 6/16/2020 8:29 AM, Paavo Helde wrote:
> trigger implicit object creation."
 
> I gather all this fuss is about allowing type-based alias analysis.
> Reinterpret_cast works directly against this idea.
 
Wrt the paper, a natural C program example:
 
struct X { int a, b; };
X *make_x() {
X *p = (X*)malloc(sizeof(struct X));
p->a = 1;
p->b = 2;
return p;
}
 
Would would one need to cast the return value of malloc to (X*)?
Paavo Helde <eesnimi@osa.pri.ee>: Jun 15 08:10PM +0300

15.06.2020 10:03 Chris M. Thomasson kirjutas:
>     return reinterpret_cast<char*>(this + 1);
>   }
> };
 
Interpreting a malloc'ed piece of memory as an array of objects is a
very old practice and standards have been carefully worded to allow that.
 
One slight problem might appear if size<sizeof(header). In that case
there is no room in the buffer for an header object at address this+1,
meaning that dereferencing the this+1 pointer would be UB. I'm not quite
sure if converting it to a char* pointer (plus later dereferencing it)
would be formally UB or not, the standard seems to speak only about
conversions of pointers pointing to some object.
 
To be on the safe side you could write instead:
 
return reinterpret_cast<char*>(this) + sizeof(*this);
 
I think there is no UB here.
 
> {
>   header* const h = reinterpret_cast<header*>(std::malloc(sizeof(*h) +
> size));
 
static_cast suffices here, no need to use reinterpret_cast.
 
For more complicated classes one would need to construct the object in
the buffer with placement new and take care to use the return value of
placement new for referring to the object (or use std::launder() on the
original buffer):
 
header* header_alloc(std::size_t size)
{
void* p = std::malloc(sizeof(header) + size);
if (p)
{
return new (p) header {size};
} else {
return nullptr;
}
}
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 17 10:49AM +0100

On Wed, 17 Jun 2020 06:36:24 +0000 (UTC)
> now the exact reason, but might have had something to do with deliberately
> dererencing a null pointer, which is UB, and which the compiler was
> "optimizing" away because the standard allowed it to.)
 
Yes I agree that is the problem with undefined behaviour. Which I
suppose is one reason why the standard committee should be careful
before spraying it over the standard and undermining programmers' well
established past practices.
James Kuyper <jameskuyper@alumni.caltech.edu>: Jun 16 10:02AM -0400

On 6/16/20 5:15 AM, Paavo Helde wrote:
> 16.06.2020 02:26 Chris Vine kirjutas:
...
>> However practical implementations will allow it for reasonable uses.
 
> Huh, good to know 99% of C programs formally contain UB when compiled as
> C++.
 
They don't have to be compiled as C++ for that to come up. Pointer
arithmetic in C is defined solely in terms of positions in arrays. Until
dynamically allocated memory acquires an effective type that is an array
type, technically the only position in that memory that you can create a
pointer to is the first one.
 
C doesn't have new[], but in C there are four other ways to give
dynamically allocated memory an effective type that is an array type.
One is to write the entire array in one assignment expression using a
lvalue of a struct or union type that contains an array as a member. If
you only wrote individual members of that array, those members would
acquire the effective type of the array element, but that would not give
the entire block of memory an array type. You could also use memmove(),
memcpy(), or explicitly copying something as an array of char, despite
the fact that in all three of those cases the behavior is defined in
terms of pointer arithmetic accessing the elements of an array. That's
because those three methods are explicitly described as giving an object
with no declared type an effective type that matches the effective type
of the object being copied (C2011 6.5p6).
 
In practice, it's generally understood that dynamically allocated memory
can, for the purposes of pointer arithmetic, be treated as if it were an
array of the pointed-at type - but there's nothing in either standard
that actually says so.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 17 12:05AM +0100

On Tue, 16 Jun 2020 15:39:25 -0700
 
> > Would would one need to cast the return value of malloc to (X*)?
 
> Why would one need to cast the return value? void* can do it as is,
> right? In pure C...
 
It is C-style code which will compile in C++ but has undefined
behaviour in C++ - the latter (undefined behaviour) being the point of
the example. As it happens it won't compile in C because it is missing
the struct tag before the various references to X* and there is no
typedef. The cast of the return value of malloc is not needed in C.
 
I don't think the example is intended as a guide to writing good C.
Paavo Helde <eesnimi@osa.pri.ee>: Jun 16 07:34PM +0300

16.06.2020 18:53 Manfred kirjutas:
> been part of the standard since day one, and since you can't do type
> analysis on a buffer returned by malloc anyway, what's the problem with
> that?
 
With malloc there is no conceptual problem because it produces "fresh"
memory where there are no existing objects which might alias something
else. But this is a property of malloc, not a property of any cast. The
proposal attempts to get this bit correct.
Lew Pitcher <lew.pitcher@digitalfreehold.ca>: Jun 15 06:02PM -0400

On June 15, 2020 17:58, Stefan Ram wrote:
 
> int main2() { if( cond3 )main3(); }
> int main1() { if( cond2 )main2(); }
> int main( ) { if( cond1 )main1(); }
 
if ((cond1) && (cond2) && (cond3) && (cond4)) DoSomething();
 
--
Lew Pitcher
"In Skills, We Trust"
Christian Gollwitzer <auriocus@gmx.de>: Jun 16 07:28AM +0200

Am 15.06.20 um 23:44 schrieb Frederick Gotham:
 
> if ( !cond3 ) return;
 
> if ( !cond4 ) return;
 
> Do Something();
 
This is how I'd do it. If the conditions do error checking, i.e.
checking that the input parameters are valid, instead of "return" it
could also be "throw."
 
 
 
> Do Something();
 
> Label_At_End:
> ;
 
This is how I do it in C due to lack of exceptions. After the label I
release the resources. But why should it not be possible to do
return/throw here in C++? Because there is more unrelated code after the
label? Usually it makes sense to put the whole thing into a function on
its own, and then you can return.
 
 
 
> if ( !cond4 ) break;
 
> Do Something();
> }
 
Feels hackish.
 
Christian
gazelle@shell.xmission.com (Kenny McCormack): Jun 12 11:44PM

In article <35a24fe2-8ddc-458d-a331-68e3cd84100fo@googlegroups.com>,
<rick.c.hodgin@gmail.com> wrote:
...
>> Did you manage to create an installation system for CAlive? A boot image?
 
>Nope. I had something happen in my life about 18 months ago that has
>radically reshaped my goals in the near term.
 
That's one of the tricks of this sort of scam (one I have a lot of personal
experience with - not, of course, as a perpetrator, but as an observer):
 
The trick is to constantly expand the scope of the project, so that you
never get anywhere on it.
 
--
"We should always be disposed to believe that which appears to us to be
white is really black, if the hierarchy of the church so decides."
 
- Saint Ignatius Loyola (1491-1556) Founder of the Jesuit Order -
Bonita Montero <Bonita.Montero@gmail.com>: Jun 17 07:11AM +0200

The cmpxchg has a membar itself.
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.
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: