Friday, June 11, 2021

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

Bonita Montero <Bonita.Montero@gmail.com>: Jun 11 01:16PM +0200

> Just because something isn't specified for a library class, doesn't mean
> that the implementation is prohibited from having it.
 
The containers _always_ use allocators that provide the allocatotor
-interface which is specified under the link I've shown you. And
with this there is no opportunity to get the size of the memory
actually allocated.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 11 01:17PM +0200

> The allocator API may not tell you when an allocator actually gets more
> memory than you ask for. But containers like std::vector are part of
> the standard library - they are not restricted to the public API. ...
 
They are because they're restricted to the specified behaviour of the
allocator template-parameter.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 11 02:18PM +0300

> }
> return 0;
> }
 
It definitely does not work fine with gcc:
 
> g++ test1.cpp -D_GLIBCXX_DEBUG
> ./a.exe
/usr/lib/gcc/x86_64-pc-cygwin/10/include/c++/debug/vector:427:
In function:
std::__debug::vector<_Tp, _Allocator>::reference
std::__debug::vector<_Tp,
_Allocator>::operator[](std::__debug::vector<_Tp,
_Allocator>::size_type) [with _Tp = int; _Allocator =
std::allocator<int>; std::__debug::vector<_Tp, _Allocator>::reference =
int&; std::__debug::vector<_Tp, _Allocator>::size_type = long unsigned
int]
 
Error: attempt to subscript container with out-of-bounds index 0, but
container only holds 0 elements.
 
Objects involved in the operation:
sequence "this" @ 0x0xffffcbf0 {
type = std::__debug::vector<int, std::allocator<int> >;
}
Aborted (core dumped)
 
 
Note: the -D_GLIBCXX_DEBUG flag is what you want to use to check that
your code is correct.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 11 01:19PM +0200

> that even if you request to reserve 8388492 bytes of memory, it's better
> to allocate an even 8388608 bytes. If so, it makes perfect sense to
> adjust the number of reserved values to reflect reality.
 
That's not what we're talking about. We're talking about if
any container can notice the size actually allocated by an
allocator - it can't.
Even with the malloc()-API there's no opportunity to get the
real size of the block.
Manfred <noname@add.invalid>: Jun 11 01:22PM +0200


>> You mean "seems to work", which is one possible effect of UB.
 
> Does work. There's no reason why it wouldn't unless you can think of one.
 
Memory allocated via resize() involves /construction/ of the required
objects - i.e. invocation of their constructor via e.g. placement new.
On the contrary, reserve() allocates memory but does /not/ construct the
objects. It is UB to access objects before their construction.
 
>> of reserve(10).
 
>> What is the problem?
 
> Why does it need both? What is the point of reserve() is my point.
 
See above.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 11 02:26PM +0300

> complex interactions with default or user methods that could easily cause a
> crash if you try and use any of them when uninitialised. Yes, it'll probably
> be some random value but it won't crash.
 
Yet another flat-earther who thinks his beliefs somehow prescribe the
world how to behave.
 
Just compile your program in MSVC Debug mode or with g++
-D_GLIBCXX_DEBUG and witness by your own eyes it is crashing! What else
do you want?
 
And this is not a fault of those compilers, the fault is in your code.
This is why you need to change your code and not claim that the whole
world is wrong and only your ideas are right.
Bo Persson <bo@bo-persson.se>: Jun 11 01:27PM +0200

On 2021-06-11 at 13:16, Bonita Montero wrote:
> -interface which is specified under the link I've shown you. And
> with this there is no opportunity to get the size of the memory
> actually allocated.
 
The library implementor knows how std::allocator gets its memory,
because he wrote that earlier.
 
So he can predict what the underlying memory manager will actually
return when you ask for 7, or 53, bytes. The container can make use of
that knowledge, for example by asking the allocator for 64 bytes instead
of 53. And now reserve(53) can result in capacity() == 64.
MrSpook_0nG@p900whw6_n8r7ovwuul.ac.uk: Jun 11 11:34AM

On Fri, 11 Jun 2021 13:22:37 +0200
>objects - i.e. invocation of their constructor via e.g. placement new.
>On the contrary, reserve() allocates memory but does /not/ construct the
>objects. It is UB to access objects before their construction.
 
POD types do not need to be constructed. As long as the memory is addressable
thats all that matters. Why do you think I used ints as an example?
MrSpook_35@s879vvmwpgee7rpqv.net: Jun 11 11:38AM

On Fri, 11 Jun 2021 14:26:18 +0300
 
>Just compile your program in MSVC Debug mode or with g++
>-D_GLIBCXX_DEBUG and witness by your own eyes it is crashing! What else
>do you want?
 
Thats not a crash, thats a compiler runtime warning. If it accessed OOB memory
then the OS would segfault it.
 
>And this is not a fault of those compilers, the fault is in your code.
>This is why you need to change your code and not claim that the whole
>world is wrong and only your ideas are right.
 
Absolutely none of you seem to understand the what reserve() is doing.
 
Reserve() for vector<int> v is equivalent to:
 
int v[10000];
 
Resize() would be:
 
int v[10000];
bzero(v,sizeof(v));
 
Either way you can access the memory up to the array size except in the first
case the value is undefined.
MrSpook_4421gcxq@fceufv2.ac.uk: Jun 11 11:39AM

On Fri, 11 Jun 2021 12:25:20 +0200
>Then there is, of course, ZZ Top's "Woke up with wood", which makes it
>rather explicit what it's all about.
 
>Except, I don't understand why Amii Stewart was /knocking/ on it.
 
Knocking on wood is superstitious drivel in the english speaking world.
You do it to ward off bad luck.
David Brown <david.brown@hesbynett.no>: Jun 11 01:45PM +0200

On 11/06/2021 13:17, Bonita Montero wrote:
>> the standard library - they are not restricted to the public API. ...
 
> They are because they're restricted to the specified behaviour of the
> allocator template-parameter.
 
No, they are not.
 
They need to be able to work with allocators that provide nothing beyond
the specified API. But that does not mean that they can use more
information and more methods when dealing with standard library allocators.
 
(You snipped my other points - is that because you don't understand
them, or because you know they show you are wrong but won't admit it?)
Bonita Montero <Bonita.Montero@gmail.com>: Jun 11 01:53PM +0200

> The library implementor knows how std::allocator gets its memory,
> because he wrote that earlier.
 
The allocator template-parameter is replaceable, so the code calling
it has to adhere to its interface. So there's no opportunity to get
the size actually physically allocated.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 11 01:54PM +0200

> They need to be able to work with allocators that provide nothing beyond
> the specified API. But that does not mean that they can use more
> information and more methods when dealing with standard library allocators.
 
The allocator template-parameter is replaceable, so the code has to
content itself with the API a allocator provides.
Manfred <noname@add.invalid>: Jun 11 02:14PM +0200

>> objects. It is UB to access objects before their construction.
 
> POD types do not need to be constructed. As long as the memory is addressable
> thats all that matters. Why do you think I used ints as an example?
 
You also asked why there is a need for both reserve() and resize(),
which is another formulation of the same question.
I gave the answer and the rationale for it.
 
If you want to try and find an exception for a special case of some
specifically qualified clause of some sort (and if you are willing to
bet your job on it), go ahead and have fun diving into the 1800+ pages
of legalese of the standard.
 
A word of advise: a quick look at [intro.object] shows:
 
1. An object is created by a definition (6.2), by a new-expression
(7.6.2.7), by an operation that implicitly creates objects (see below),
when implicitly changing the active member of a union (11.5), or when a
temporary object is created (7.3.4, 6.7.7)
 
Now you may want to look into "implicitly created objects":
13. "[Note: Some functions in the C++ standard library implicitly create
objects (20.10.9.2, 20.10.12, 21.5.3, 26.5.3). —end note]"
 
Then you are referenced a.o. to 20.10.9.2 [allocator.traits.members]
[[nodiscard]] static constexpr pointer allocate(Alloc& a, size_type n);
1. Returns: a.allocate(n).
 
Which redirects you to Allocator::allocate; for the default allocator
you have [allocator.members]:
 
[[nodiscard]] constexpr T* allocate(size_t n);
2 Mandates: T is not an incomplete type (6.8).
3 Returns: A pointer to the initial element of an array of n T.
4 Remarks: The storage for the array is obtained by calling
::operator new (17.6.2), but it is unspecified when or how often this
function is called. This function starts the lifetime of the array
object, but not that of any of the array elements.
 
Note the last sentence: "This function starts the lifetime of the array
object, but not that of any of the array elements"
 
Obviously it's perfectly possible that that's not the end of it.
Have fun!
Paavo Helde <myfirstname@osa.pri.ee>: Jun 11 03:14PM +0300

>> do you want?
 
> Thats not a crash, thats a compiler runtime warning. If it accessed OOB memory
> then the OS would segfault it.
 
Explain that to the customer who is complaining that your program
crashes when she compiles it with a mainstream compiler with her
favorite settings.
MrSpook_p_5Ko4g@21yhpi_n4fck_wfz.org: Jun 11 12:50PM

On Fri, 11 Jun 2021 14:14:53 +0200
 
>> POD types do not need to be constructed. As long as the memory is addressable
 
>> thats all that matters. Why do you think I used ints as an example?
 
>You also asked why there is a need for both reserve() and resize(),
 
And I haven't had a proper answer yet. I see zero reason for reserve() existing.
 
>If you want to try and find an exception for a special case of some
>specifically qualified clause of some sort (and if you are willing to
 
I was making a point about reserve() allocating memory, nothing more.
 
>bet your job on it), go ahead and have fun diving into the 1800+ pages
>of legalese of the standard.
 
I'll leave that to the aspies.
 
tl;dr
MrSpook_uQjuVe@5szcyauh_pjzi228wvwn.info: Jun 11 12:52PM

On Fri, 11 Jun 2021 15:14:57 +0300
 
>Explain that to the customer who is complaining that your program
>crashes when she compiles it with a mainstream compiler with her
>favorite settings.
 
More likely his unless you live in a parallel woke universe. I'm simply
pointing out that reserve() reserves memory that allows PODs to be used
which leads on to my point as to whats the point of it when resize() should
always be used.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 11 04:37PM +0300

>> crashes when she compiles it with a mainstream compiler with her
>> favorite settings.
 
> More likely his unless you live in a parallel woke universe.
 
Obviously you missed the point why I used "her" here :-) I conclude you
are living alone.
 
> pointing out that reserve() reserves memory that allows PODs to be used
> which leads on to my point as to whats the point of it when resize() should
> always be used.
 
Reserve() is an optimization feature which can increase the speed and
reduce the memory usage of the program when used properly. As such, it
is not necessary to use it, as these potential performance improvements
are modest and do not make big-O difference.
 
However, reserve() might also be necessary in the case when the objects
placed in the container cannot have working copy or move constructors,
or they are extremely expensive. If you have reserved enough memory in
the vector, then emplace_back() et al are guaranteed to not reallocate
the buffer, so no copy or move constructor is called.
 
Now one could argue that it would be almost always possible to provide a
cheap move constructor, and therefore there is no inherent need for
reserve(). There might be some truth in it, but the thing is that we
didn't have move constructors before 2011, and vector::reserve() was
there beforehand, as a way to partially compensate for this lack.
David Brown <david.brown@hesbynett.no>: Jun 11 03:58PM +0200

On 11/06/2021 13:54, Bonita Montero wrote:
>> allocators.
 
> The allocator template-parameter is replaceable, so the code has to
> content itself with the API a allocator provides.
 
Sometimes this is like talking to a brick wall. You are so convinced
that you know /everything/ that you won't try to read, and you certainly
won't try to /think/.
 
You asked a question in this thread. I gave you the answer. You reject
that because of your incorrect preconceptions. You can go back to being
ignorant - I'm done trying to help.
 
If you decide to read what other people post and perhaps even rub a
couple of brain cells together to understand the help you are given, let
us know.
 
Oh, and /please/ do us the courtesy of learning how to quote properly
with attributions.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 11 04:35PM +0200

You say:
 
> undocumented features that allow std::vector to see how much
> memory it has /actually/ een allocated, and let it set "capacity"
> a little higher.
 
And this can't be true since the container-implementation has
to stick with what an allocator provides. Otherwise it wouldn't
be replaceable.
MrSpook_9fpRQm@i1z834r.net: Jun 11 02:58PM

On Fri, 11 Jun 2021 16:37:36 +0300
 
>> More likely his unless you live in a parallel woke universe.
 
>Obviously you missed the point why I used "her" here :-) I conclude you
>are living alone.
 
Obviously I did. And you're wrong.
 
>However, reserve() might also be necessary in the case when the objects
>placed in the container cannot have working copy or move constructors,
 
OK, that is a good reason for it.
Manfred <noname@add.invalid>: Jun 11 05:06PM +0200

On 6/11/2021 3:37 PM, Paavo Helde wrote:
>> On Fri, 11 Jun 2021 15:14:57 +0300
>> Paavo Helde <myfirstname@osa.pri.ee> wrote:
>>> 11.06.2021 14:38 MrSpook_35@s879vvmwpgee7rpqv.net kirjutas:
[...]
> reserve(). There might be some truth in it, but the thing is that we
> didn't have move constructors before 2011, and vector::reserve() was
> there beforehand, as a way to partially compensate for this lack.
 
but emplace_back was first standardized in 2011 too, which would make it
hard to construct an object in-place before then anyway.
The argument is still valid though.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 11 02:03PM +0300

11.06.2021 04:31 Lynn McGuire kirjutas:
 
> I want multiple threads to share the massive dataset that we use.  Very
> tricky, I have tried sharing data between the threads and it was a
> disaster.
 
MFC is not thread-safe, so only the main thread can call any MFC functions.
 
For data exchange the most robust way is to use a couple of message
queues for passing events back and forth between the threads. Any data
which is not MT-safe to access should be copied by value into a new
non-shared object when putting into the queue.
 
One can easily build such a queue with a std::queue and a std::mutex.
 
For example, if a background queue wants to display a message to the
user, it can send an event to the main thread queue containing the
message. The main thread would check in a MFC OnIdle() function if there
are any events in the queue, and process them in the main thread.
Paavo Helde <myfirstname@osa.pri.ee>: Jun 11 03:19PM +0300

11.06.2021 14:03 Paavo Helde kirjutas:
> which is not MT-safe to access should be copied by value into a new
> non-shared object when putting into the queue.
 
> One can easily build such a queue with a std::queue and a std::mutex.
 
s/std::queue/std::deque/
 
Manfred <noname@add.invalid>: Jun 11 01:37PM +0200

On 6/11/2021 12:17 AM, Öö Tiib wrote:
> by local legislature. So it is symbolic for me and attempts to censor
> it are also symbolic for me and discussing it is not Real Troll's fault
> but mine.
 
As far as I am concerned, I don't think there was any fault.
 
c.l.c and c.l.c++ are about the languages, so their topicality is clear,
but they are also part of Usenet, for which freedom (with no
compromises, as the Internet was originally thought of when it was made
public) is a distinctive character.
So, up to some extent, the occasional comment about free speech and
concern for censorship (which I agree is becoming more and more a real
issue) is still appropriate.
 
Thanks for sharing.
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: