Monday, February 15, 2021

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

mickspud@potatofield.co.uk: Feb 15 09:27AM

On Sat, 13 Feb 2021 18:19:55 +0100
>> how you want padding if any.
 
>No, it is not essential. It can be convenient, but it is far from the
>only way to achieve the padding you want or to handle externally defined
 
If you're creating the memory layout then put in whatever padding you want.
 
>size. Non-aligned data can read or written using memcpy(), and good
 
Yuck, very messy! But everyone has a prefered style I suppose.
David Brown <david.brown@hesbynett.no>: Feb 15 10:47AM +0100


> If you're creating the memory layout then put in whatever padding you want.
 
>> size. Non-aligned data can read or written using memcpy(), and good
 
> Yuck, very messy! But everyone has a prefered style I suppose.
 
memcpy can work simply and easily, it's portable, and with a good
compiler it is usually optimally efficient with known fixed sizes. And
it is always correct code, unlike some things people do with packed
structs (like taking the address of non-aligned fields - something that
may not work as expected). Any messiness can easily be wrapped in a C++
class or template - that's why you use C++.
mickspud@potatofield.co.uk: Feb 15 10:03AM

On Mon, 15 Feb 2021 10:47:39 +0100
 
>> Yuck, very messy! But everyone has a prefered style I suppose.
 
>memcpy can work simply and easily, it's portable, and with a good
>compiler it is usually optimally efficient with known fixed sizes. And
 
No memcpy is going to be more efficient than a 1 line pointer cast which is
all you need to do with mapping a structure onto a block of memory. Plus for
any significant number of fields - eg for a TCP header with 9 fields - you
going to have an equivalent number of memcpys in the code which frankly
looks fugly and is much harder to visually parse.
 
eg:
tcp_hdr *thdr = (tcp_hdr *)packet;
 
vs
 
memcpy((char *)thdr.src,packet,2);
memcpy((char *)thdr.dst,packet+2,2);
memcpy((char *)thdr.seqnum,packet+4,4)
etc etc
 
Blech. No thanks.
Manfred <noname@add.invalid>: Feb 12 05:15PM +0100

On 2/12/2021 9:25 AM, David Brown wrote:
> ordering may affect the padding needed to ensure the correct alignments.
> The alignment of the struct is the maximum of the alignments of the
> members (or higher, if you use "alignas").
 
You are right that the standard does not relate alignment or padding
with members order, and in fact gcc does not do that, thanks for
pointing this out.
 
However, from the MSVC docs:
 
https://docs.microsoft.com/en-us/cpp/build/reference/zp-struct-member-alignment?view=msvc-160#remarks
 
"The compiler stores members after the first one on a boundary that's
the smaller of either the size of the member type, or an N-byte boundary."
 
https://docs.microsoft.com/en-us/cpp/preprocessor/pack?view=msvc-160#parameters
 
"The alignment of a member is on a boundary that's either a multiple of
n, or a multiple of the size of the member, whichever is smaller."
 
So, this compiler /does/ padding between members depending on their order.
David Brown <david.brown@hesbynett.no>: Feb 13 02:57PM +0100

On 12/02/2021 17:15, Manfred wrote:
 
> "The alignment of a member is on a boundary that's either a multiple of
> n, or a multiple of the size of the member, whichever is smaller."
 
> So, this compiler /does/ padding between members depending on their order.
 
As I said, the /padding/ between members in a struct does depend on
their order. Their /alignment/ does not. That applies to MSVC, gcc,
and any other compiler.
 
If you have:
 
struct S {
char a;
int b;
char c;
}
 
where "int" is size 4 and alignment 4, then S will have an alignment of
4, there will be 3 bytes of padding between "a" and "b", and three bytes
of padding after "c" - giving a total size of 12.
 
If you arrange it as:
 
struct S {
char a;
char c;
int b;
}
 
then there will be 2 bytes of padding after "c", and a total size of 8
(with the same alignment of 4).
 
 
If you arrange it as:
 
struct S {
int b;
char a;
char c;
}
 
then there will be 2 bytes of padding after "c" at the end of the
structure, and a total size of 8 (with the same alignment of 4).
 
Padding depends on the order, alignment does not.
 
 
Now, compilers are free to /increase/ alignments if they want, and
padding as needed to support that. It's not uncommon on 64-bit systems
to use 8-bit alignment on structures, and data on stacks or in
statically allocated memory can be given extra alignment - this can aid
cache friendly memory layouts. And of course compilers can offer
options or extensions to give different alignment (and thereby padding)
arrangements, even if that breaks the platform's ABI.
David Brown <david.brown@hesbynett.no>: Feb 15 12:35PM +0100

>> compiler it is usually optimally efficient with known fixed sizes. And
 
> No memcpy is going to be more efficient than a 1 line pointer cast which is
> all you need to do with mapping a structure onto a block of memory.
 
Yes, it is - because the compiler knows what memcpy does, and can
optimise appropriately. memcpy does not have to be implemented as an
external library function call!
 
 
#pragma pack(1)
typedef struct S {
int8_t a;
int32_t b;
int64_t c;
} S;
 
int getsize(void) { return sizeof(S); }
 
int32_t getb1(const S* p) {
return p->b;
}
 
int32_t getb2(const S* p) {
int32_t x;
memcpy(&x, &p->b, sizeof x);
return x;
}
 
int32_t getb3(const S* p) {
const uint8_t * q = (const uint8_t *) &p->b;
int32_t x;
uint8_t b[sizeof x];
for (size_t i = 0; i < sizeof x; i++) {
b[i] = *q++;
}
memcpy(&x, b, sizeof x);
return x;
}
 
gcc turns all of these into a single "mov" instruction. Modern
compilers (and many old ones) can do a lot of nice things in their
optimisation. Standard library functions are specified in the standard,
and the compiler can take advantage of that.
 
> memcpy((char *)thdr.seqnum,packet+4,4)
> etc etc
 
> Blech. No thanks.
 
You already have to handle accessing these with the right endianness.
You can't just read the fields and use the values. (Well, you can if
you have a compiler with extensions that cover endian specifications and
those are used in the struct definition - but that is far from standard.)
James Kuyper <jameskuyper@alumni.caltech.edu>: Feb 15 08:43AM -0500

> On Mon, 15 Feb 2021 10:47:39 +0100
> David Brown <david.brown@hesbynett.no> wrote:
...
>> compiler it is usually optimally efficient with known fixed sizes. And
 
> No memcpy is going to be more efficient than a 1 line pointer cast which is
> all you need to do with mapping a structure onto a block of memory.
 
He said "optimally efficient", not "more efficient". What he's
suggesting is that a compiler could easily optimize a call to memcpy()
into exactly the same machine code that would be generated for the code
you describe.
 
> memcpy((char *)thdr.src,packet,2);
> memcpy((char *)thdr.dst,packet+2,2);
> memcpy((char *)thdr.seqnum,packet+4,4)
 
Why the (char*) casts? memcpy() takes void*, which can be implicitly
converted to from any object pointer type, which is the only reason why
the char* cast works. A direct conversion to void* is no less safe than
an indirect one using char* as an intermediate step.
mickspud@potatofield.co.uk: Feb 15 03:31PM

On Mon, 15 Feb 2021 12:35:10 +0100
 
>Yes, it is - because the compiler knows what memcpy does, and can
>optimise appropriately. memcpy does not have to be implemented as an
>external library function call!
 
So what? 9 memcpys will be a min of 9 mov's at best. 1 cast is 1 mov
though potentially zero depending on how smart the compiler is.
 
>> Blech. No thanks.
 
>You already have to handle accessing these with the right endianness.
 
So what? You'd have to call ntoh*() or similar after the fact regardless of
what method you used. I suppose you could write your own endian aware memcpy
for numeric values but why bother plus its unlikely to be very efficient.
mickspud@potatofield.co.uk: Feb 15 03:33PM

On Mon, 15 Feb 2021 08:43:31 -0500
>suggesting is that a compiler could easily optimize a call to memcpy()
>into exactly the same machine code that would be generated for the code
>you describe.
 
No it wouldn't. Maybe for 1 but not for 9.
 
>> memcpy((char *)thdr.dst,packet+2,2);
>> memcpy((char *)thdr.seqnum,packet+4,4)
 
>Why the (char*) casts? memcpy() takes void*, which can be implicitly
 
Habit. Plus I forgot &.
David Brown <david.brown@hesbynett.no>: Feb 15 05:55PM +0100

>> external library function call!
 
> So what? 9 memcpys will be a min of 9 mov's at best. 1 cast is 1 mov
> though potentially zero depending on how smart the compiler is.
 
Casts frequently don't need any instructions - pointer casts on most
systems are free at run time. /Accessing/ the data takes instructions.
The point is that with a good enough compiler (and sensible flags),
memcpy is going to give you the same code.
 
The key difference is that casting pointer types then using them to
access data is often lying to the compiler - for all but a handful of
exceptions, it is behaviour undefined by the standard. This means you
can easily get something that works fine in your simple tests, but fails
in more complex situations when code is inlined, link-time optimised, or
otherwise used in more advanced code. Memcpy, on the other hand, is
well specified and safe.
 
 
> So what? You'd have to call ntoh*() or similar after the fact regardless of
> what method you used. I suppose you could write your own endian aware memcpy
> for numeric values but why bother plus its unlikely to be very efficient.
 
The point is that you have to have code for accessing the fields, you
can't just use them directly. And when you have a an accessor function
anyway, you might as well write it correctly, safely and portably - it
will be just as efficient.
 
I am not at all suggesting that memcpy is always the best way to write
code - merely that it is not an expensive way to do it either in terms
of run-time costs or in source code clarity, and it is often safer and
more portable. People have been writing code to access network-defined
or file format defined structures since C has been in existence, and
#pragma pack is neither necessary nor sufficient for the task.
David Brown <david.brown@hesbynett.no>: Feb 15 05:57PM +0100

>> into exactly the same machine code that would be generated for the code
>> you describe.
 
> No it wouldn't. Maybe for 1 but not for 9.
 
I think you are misunderstanding something here.
 
If you read three items view a pointer, you will (in general) have a
minimum of three read instructions. If you do it with three optimised
memcpy() calls, you also have three read instructions. The code is the
same.
 
mickspud@potatofield.co.uk: Feb 15 05:16PM

On Mon, 15 Feb 2021 17:55:58 +0100
>memcpy is going to give you the same code.
 
>The key difference is that casting pointer types then using them to
>access data is often lying to the compiler - for all but a handful of
 
Sorry? Its standard C. Perhaps its frowned on in C++ but I've been doing
network programming for a couple of decades and this method is used all over
the place. No one does 50 memcpys if there's a memory structure with 50
fields in it just for the sake of ivory tower correctness, you'd have to
be insane. A structure only has to be correct once in the header, memcpys have
to be correct everywhere you use them.
 
If you don't believe me have a look in any of the /usr/include/linux network
header files and then go through this and check out the casting to structs:
 
https://github.com/torvalds/linux/blob/master/net/ipv4/tcp.c
 
>exceptions, it is behaviour undefined by the standard. This means you
>can easily get something that works fine in your simple tests, but fails
>in more complex situations when code is inlined, link-time optimised, or
 
Rubbish. Maybe in Windows but that doesn't concern me.
 
>> for numeric values but why bother plus its unlikely to be very efficient.
 
>The point is that you have to have code for accessing the fields, you
>can't just use them directly. And when you have a an accessor function
 
Wtf are you taking about? You just access them as structure fields. There
may be a small cost in deferencing but there's a large gain in code
readability and correctness.
 
>more portable. People have been writing code to access network-defined
>or file format defined structures since C has been in existence, and
>#pragma pack is neither necessary nor sufficient for the task.
 
Whether its pragma pack or attribute packed, its used a lot in Linux.
 
$ pwd
/usr/include/linux
$ grep __attribute__ *.h | grep packed | wc -l
239
 
But what do they know?
David Brown <david.brown@hesbynett.no>: Feb 15 01:15AM +0100

On 14/02/2021 23:56, Brian Wood wrote:
>> checked by no one is merely part of the daily grind for a coder.
 
> Perhaps we can at least agree that services are the most important
> form of software today
 
Absolutely not, no. I don't really think it makes sense to talk about
"the impost important form of software" - our way of life depends on a
wide variety of software types. But if I had to pick one, it would be
embedded software - the kind that most people never see, and never think
about, but makes things work.
 
Online code generators would rank down at the bottom of the list - they
are not necessary in any way. They might sometimes be convenient, but
they are not important.
 
> and that C++ is the most important language
> for services.
 
Again, no. Most online services are written in other languages. C++ is
not the worst choice (it's far better than C) for that kind of thing,
but it is not a great choice either.
 
>> harder sell for most potential code reviewers.
 
> A lot of code review is done for free:
> https://www.reddit.com/r/codereview
 
Sure - for free projects. No one does code reviews for free for
commercial products. Why do you think people should review /your/ code
for free?
 
> for articles of silver and gold, and for clothing. And the L-RD gave the
> people such favor in the sight of the Egyptians that they granted their
> request. In this way they plundered the Egyptians." Exodus 12:36,37
 
I'm sorry, I can't see what relevance there is in quoting an old story book.
 
> The Israelites didn't pay for the items of gold and silver. G-d was
> saving them from their oppressors. Unfortunately, some of the
> regulars here are oppressors.
 
No one here is oppressing /people/ - certainly not oppressing
Christians, Jews, Israelites, Egyptians, or any other particular
religion or nationality. People /do/ oppress preaching or pointless,
off-topic and repetitive religious posts. Stick to the topic at hand.
Brian Wood <woodbrian77@gmail.com>: Feb 14 06:16PM -0800

On Sunday, February 14, 2021 at 6:15:57 PM UTC-6, David Brown wrote:
> Again, no. Most online services are written in other languages. C++ is
> not the worst choice (it's far better than C) for that kind of thing,
> but it is not a great choice either.
 
At least you didn't say Scala or Ada or some other nonsense.
 
 
> Sure - for free projects. No one does code reviews for free for
> commercial products. Why do you think people should review /your/ code
> for free?
 
My software is free -- like duckduckgo.com.
 
 
> Christians, Jews, Israelites, Egyptians, or any other particular
> religion or nationality. People /do/ oppress preaching or pointless,
> off-topic and repetitive religious posts. Stick to the topic at hand.
 
This reminds me of Don Cheadle's comment that cancel
culture is "not really real."
https://www.dailywire.com/news/don-cheadle-cancel-culture-is-not-really-real
 
 
The topic is about how to improve my repo:
https://github.com/Ebenezer-group/onwards
 
and website:
https://webEbenezer.net
.
 
Brian
David Brown <david.brown@hesbynett.no>: Feb 15 09:02AM +0100

On 15/02/2021 03:16, Brian Wood wrote:
>> not the worst choice (it's far better than C) for that kind of thing,
>> but it is not a great choice either.
 
> At least you didn't say Scala or Ada or some other nonsense.
 
Are you just picking random programming languages that you personally
don't like?
 
Different languages are suitable for different purposes - Ada and Scala
have their place. C++ covers an unusually broad range of tasks,
probably broader than any other language. But that doesn't mean it is
the appropriate choice for all tasks. When I write online services
(these are not public services), I don't use C++ - I use Python. Others
use other languages, including some using C++.
 
(A very quick and rough way to gauge the choice of language for online
services would be to look at the Wikipedia page for "Comparison of web
frameworks". Look at how many of these are written in the various
languages - that will give you an idea of what people think is the right
language for a task like that.)
 
>> commercial products. Why do you think people should review /your/ code
>> for free?
 
> My software is free -- like duckduckgo.com.
 
Your software is commercial, as far as I can see. Some of it is open
source, but parts of it are closed source and your intention is to get
paid for that software - it's part of your company business plan.
(There's nothing wrong with that - people are free to choose what they
give away and what they don't, and if you spend your time creating a
worthwhile product or service, then it's natural to get paid for the
effort.)
 
However, there /is/ something wrong with asking others to work for you
for free so that you stand a better chance of earning money with the
software.
 
 
> This reminds me of Don Cheadle's comment that cancel
> culture is "not really real."
> https://www.dailywire.com/news/don-cheadle-cancel-culture-is-not-really-real
 
I don't know or care who that person might be, and we were not
discussing "cancel culture" - real, imaginary, under-estimated or
over-blown as it may be. It is this kind of rambling that makes it less
likely for anyone to want to be connected with you.
 
 
> The topic is about how to improve my repo:
> https://github.com/Ebenezer-group/onwards
 
First you have to give people a reason to help.
 
> and website:
> https://webEbenezer.net
 
I can give you good advice here, but you are not going to like it. It
is, however, a genuine recommendation of what would help your company.
 
Find someone who is able to run a company, and pay them to fix yours.
Pay someone to make you a website that looks like it is the site of a
company. Get someone to put relevant information on the website, and
remove the begging and pleading, and the irrelevant links (especially
the antisocial ones).
 
In general, you have to decide if you are a programmer, or a failed
project manager and company owner. If you want your "CMW" to succeed as
a project, find someone who can manage the project. If you want your
company to succeed, find someone to run it. I'm sure you can do the
programming fine, but that's not the main ability if you want to make a
living from your software. Damn few people can manage to handle both
roles well, and it's not easy (ask Jacob Navia how much free time he gets).
"Öö Tiib" <ootiib@hot.ee>: Feb 15 03:45AM -0800

On Monday, 15 February 2021 at 10:02:34 UTC+2, David Brown wrote:
> I can give you good advice here, but you are not going to like it. It
> is, however, a genuine recommendation of what would help your company.
 
By "Parable of the Sower" <https://en.wikipedia.org/wiki/Parable_of_the_Sower>
you are knowingly sowing into thorns.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Feb 13 01:36PM -0800

On 2/13/2021 4:51 AM, Bonita Montero wrote:
>> - Raw spin locks make no sense on /any/ single core.
 
> Raw spinlocks almost never make sense in userland.
 
True.
mickspud@potatofield.co.uk: Feb 15 09:34AM

On Sat, 13 Feb 2021 12:52:50 -0800
>> process couldn't accomplish. If you know otherwise then feel free to explain.
 
>IOCP is basically windows version of POSIX aio. Just make sure to never
>create a process and/or thread per connection. That really, really bad.
 
I guess that depends on how long many connections you're expecting per unit
time, how long they stay up and how important the server is. I wrote a
middleware system that forked every time a new connection came but but we only
expected a few connections a minute and they'd stay up for 2-3 mins at a time.
Plus it was a critical system and if the main process went down the company
backend would grind to a halt so multiplexing and threading were off the table.
mickspud@potatofield.co.uk: Feb 12 03:26PM

On Fri, 12 Feb 2021 14:52:01 +0000
>> execution structures as procedural languages. If you knew anything about
>> parsing you'd know that.
 
>Why do you assume that I have no knowledge regarding declarative languages? Do
 
Because you pretend you have a lot of knowledge about a lot of things but
when pressed you tend to come up short and resort to...
 
>you often make such assumptions when interacting with people you know fuck all
>about and their projects that you know fuck all about?
 
..answering questions with a question just like a 2nd rate politician.
 
So lets see an example of your wonder compiler compiling some SQL, Prolog or
other declarative language. I mean since its a universal compiler you'd have
done that, right?
 
>> can't?
 
>I am not in the habit of teaching ignorant, presumptive, arrogant cockwombles
>the fundamentals, dear.
 
Another of your standard responses when you can't answer. But thanks for
playing son.
Mr Flibble <flibble@i42.REMOVETHISBIT.co.uk>: Feb 12 04:04PM


>> Why do you assume that I have no knowledge regarding declarative languages? Do
 
> Because you pretend you have a lot of knowledge about a lot of things but
> when pressed you tend to come up short and resort to...
 
Assertions made without evidence can be dismissed with evidence.
 
 
> So lets see an example of your wonder compiler compiling some SQL, Prolog or
> other declarative language. I mean since its a universal compiler you'd have
> done that, right?
 
Since when is SQL ever "compiled"?
 
>> the fundamentals, dear.
 
> Another of your standard responses when you can't answer. But thanks for
> playing son.
 
I don't believe I have ever responded with those exact words before, dear, ergo it cannot be one of my "standard" responses.
 
If you want to learn about threads then I suggest you go back to school, dear.
 
/Flibble
 
--
😎
mickspud@potatofield.co.uk: Feb 12 05:12PM

On Fri, 12 Feb 2021 16:33:09 +0000
>On 12/02/2021 16:20, mickspud@potatofield.co.uk wrote:
 
Still waiting for your proof. Take your time.
 
 
>It is "UNIX" not "unix", dear. And as far as UNIX-like is concerned: Linux's
>overcommit/OOM-killer to support fork()ing is a fucking omnishambles; but you
>wouldn't know this of course as you are fucking clueless anachronism.
 
Oh dear, someone tell the child about copy-on-write.
 
If you're going to google stuff and pretend its your own knowledge you might
want to have a clue first. FWIW overcommit is pretty standard amongst OS's of
all colours and has been for decades.
 
>If you knew anything useful about threads you would know what advantages they
>have over processes; I repeat: go back to school, dear.
 
Thanks for proving my point. Have a good w/e with your boyfriend cupcake.
mickspud@potatofield.co.uk: Feb 12 04:20PM

On Fri, 12 Feb 2021 16:04:05 +0000
 
>> Because you pretend you have a lot of knowledge about a lot of things but
>> when pressed you tend to come up short and resort to...
 
>Assertions made without evidence can be dismissed with evidence.
 
So prove me wrong.
 
>> other declarative language. I mean since its a universal compiler you'd have
>> done that, right?
 
>Since when is SQL ever "compiled"?
 
Oh I dunno, probably since the 1980s. Or do you think RDBMs store procedures
as plain text then parse them each time?
 
 
>I don't believe I have ever responded with those exact words before, dear,
>ergo it cannot be one of my "standard" responses.
 
>If you want to learn about threads then I suggest you go back to school, dear.
 
I've been fully versed in threads for 2 decades buttercup and I've yet to
see anything they can do that multiprocess can't though mileage may vary for
each depending on the use case. However I'm speaking from a unix POV. I guess
if you've only programmed on a toy OS like Windows that can even do something
as fundamental as multiplexing network sockets without threading then I guess
you may well be screwed without them.
Mr Flibble <flibble@i42.REMOVETHISBIT.co.uk>: Feb 12 04:33PM

> if you've only programmed on a toy OS like Windows that can even do something
> as fundamental as multiplexing network sockets without threading then I guess
> you may well be screwed without them.
 
It is "UNIX" not "unix", dear. And as far as UNIX-like is concerned: Linux's overcommit/OOM-killer to support fork()ing is a fucking omnishambles; but you wouldn't know this of course as you are fucking clueless anachronism.
 
If you knew anything useful about threads you would know what advantages they have over processes; I repeat: go back to school, dear.
 
/Flibble
 
--
😎
"Öö Tiib" <ootiib@hot.ee>: Feb 14 03:36PM -0800

On Monday, 15 February 2021 at 00:05:41 UTC+2, Chris M. Thomasson wrote:
> extended until the temporary std::shared_ptr is destroyed as well.
> ___________________
 
> Does shared_ptr have a "separate" reference count to weak_ptr's?
 
Yes.
Nikki Locke <nikki@trumphurst.com>: Feb 14 11: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: