www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.development - Second Draft: Placement New Expression

reply Walter Bright <newshound2 digitalmars.com> writes:
https://github.com/WalterBright/documents/blob/37206e8aad453aa115329f4465fc5b83bca4ff66/placementnew.md

as the first draft did not survive the implementation:

https://github.com/dlang/dmd/pull/17057
Nov 18
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
This still includes typed expressions, which I have some concerns about.

We should not be condoning uninitialized memory as having a type. It can 
only cause problems for people. If we stick to ``void[]`` as the input, 
we can limit the source to `` system`` code only.

No double-init bugs please.

The side benefit of this, is the the length is known. If not big enough, 
return null.

At the very least we should think about how to make a memory safety DFA 
with one layer of indirection support, so not just the variable being 
known to be initialized, but what the pointer points to also being 
initialized. That would make this a whole lot safer.

 If one desires to use classes without the GC, such as in BetterC, 
it's just awkward to use emplace. Not true, emplace is the easiest part of it as it becomes library code. No reference counting on classes, lack of ability to mix -betterC with full D. https://github.com/ldc-developers/ldc/issues/4779 These are the problems that need solving. This is how I solved RC classes in -betterC, note that everything is templated (sigh), and that I have down casting working. https://github.com/Project-Sidero/basic_memory/blob/main/source/sidero/base/allocators/classes.d#L183
 The use of placement new is not allowed in  safe code.
Excellant! Although I would prefer us to disallow casting to ``void*`` and ``void[]`` also in `` safe``. Still too easy to introduce memory unsafe behaviors.
 To allocate storage with an allocator function such as malloc(), a 
simple template can be used: Why not support calling the allocator with the size needed? ```d struct Allocator { void[] allocate(size_t); } Allocator a; new (allocator) S; new (malloc) S; ``` DONE.
Nov 18
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 19/11/2024 6:05 PM, Richard (Rikki) Andrew Cattermole wrote:
  > To allocate storage with an allocator function such as malloc(), a 
 simple template can be used:
 
 Why not support calling the allocator with the size needed?
 
 ```d
 struct Allocator {
      void[] allocate(size_t);
 }
 
 Allocator a;
 
 new (allocator) S;
 new (malloc) S;
 ```
 
 DONE.
There are three reasons that motivate me for allocator support: 1. It would be safe. 2. There is no trait like ``__traits(allocateSize, T)``/``__traits(allocateSize, T, arrayCount)``. Handle overflow correctly and "just work" regardless of type, i.e. class vs struct vs array has a very different way of getting allocation size. 3. Needing wrapper functions for this is genuinely silly. As a result I don't understand why it hasn't been adopted already.
Nov 18
parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 19 November 2024 at 05:17:20 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 19/11/2024 6:05 PM, Richard (Rikki) Andrew Cattermole wrote:
 Why not support calling the allocator with the size needed?
 
 ```d
 struct Allocator {
      void[] allocate(size_t);
 }
 
 Allocator a;
 
 new (allocator) S;
 new (malloc) S;
 ```
 
 DONE.
There are three reasons that motivate me for allocator support: 1. It would be safe.
It would not be safe, because there is no way the compiler can be sure that the void[] returned from allocate will not be aliased by other pointers/references/slices. The programmer would have to verify that for each individual allocator implementation, and use trusted once they had done so.
Nov 19
parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 20/11/2024 8:08 AM, Paul Backus wrote:
 On Tuesday, 19 November 2024 at 05:17:20 UTC, Richard (Rikki) Andrew 
 Cattermole wrote:
 On 19/11/2024 6:05 PM, Richard (Rikki) Andrew Cattermole wrote:
 Why not support calling the allocator with the size needed?

 ```d
 struct Allocator {
      void[] allocate(size_t);
 }

 Allocator a;

 new (allocator) S;
 new (malloc) S;
 ```

 DONE.
There are three reasons that motivate me for allocator support: 1. It would be safe.
It would not be safe, because there is no way the compiler can be sure that the void[] returned from allocate will not be aliased by other pointers/references/slices. The programmer would have to verify that for each individual allocator implementation, and use trusted once they had done so.
If there is anything like that is occurring outside of an allocator, or a misbehaving allocator, what expression you used to call an allocator is irrelevant, you have significantly bigger problems to attend to. At the very least you will have program corruption, at best a crash. I've experienced and debugged this plenty, without the need for placement new.
Nov 19
parent Paul Backus <snarwin gmail.com> writes:
On Tuesday, 19 November 2024 at 21:18:53 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 On 20/11/2024 8:08 AM, Paul Backus wrote:
 It would not be  safe, because there is no way the compiler 
 can be sure that the void[] returned from allocate will not be 
 aliased by other pointers/references/slices. The programmer 
 would have to verify that for each individual allocator 
 implementation, and use  trusted once they had done so.
If there is anything like that is occurring outside of an allocator, or a misbehaving allocator, what expression you used to call an allocator is irrelevant, you have significantly bigger problems to attend to. At the very least you will have program corruption, at best a crash.
I agree. If someone makes a mistake here, it could lead to program corruption. That's exactly why it can't be safe.
Nov 19
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 19 November 2024 at 05:05:57 UTC, Richard (Rikki) 
Andrew Cattermole wrote:
 This still includes typed expressions, which I have some 
 concerns about.

 We should not be condoning uninitialized memory as having a 
 type. It can only cause problems for people. If we stick to 
 ``void[]`` as the input, we can limit the source to `` system`` 
 code only.

 No double-init bugs please.
+1 Using a typed lvalue instead of void[] is just asking to shoot yourself in the foot, especially when it comes to const/immutable: struct S { int i; char c; } void main() { S dest; immutable(S)* p = new immutable(S)(dest)(123, 'A'); assert(p.i == 123 && p.c == 'A'); dest.i = 0; // oops, undefined behavior! }
Nov 19
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 11/19/2024 11:02 AM, Paul Backus wrote:
 Using a typed lvalue instead of void[] is just asking to shoot yourself in the 
 foot, especially when it comes to const/immutable:
This (and some other reasons) is why placement new will not be allowed in safe code. The compiler will never be able to properly vet the provenance of the memory being overwritten by placement new.
Nov 19
parent Paul Backus <snarwin gmail.com> writes:
On Wednesday, 20 November 2024 at 01:49:23 UTC, Walter Bright 
wrote:
 On 11/19/2024 11:02 AM, Paul Backus wrote:
 Using a typed lvalue instead of void[] is just asking to shoot 
 yourself in the foot, especially when it comes to 
 const/immutable:
This (and some other reasons) is why placement new will not be allowed in safe code. The compiler will never be able to properly vet the provenance of the memory being overwritten by placement new.
I agree that it can't be safe, void[] or not. But my impression is that even in system code, D generally tries to guide the programmer away from error-prone constructs (for example, requiring an explicit `= void` to leave a variable uninitialized). Using a void[] instead of a typed lvalue would be consistent with that approach.
Nov 19
prev sibling parent jmh530 <john.michael.hall gmail.com> writes:
On Tuesday, 19 November 2024 at 03:47:09 UTC, Walter Bright wrote:
 https://github.com/WalterBright/documents/blob/37206e8aad453aa115329f4465fc5b83bca4ff66/placementnew.md

 as the first draft did not survive the implementation:

 https://github.com/dlang/dmd/pull/17057
Not directly related to this DIP, but Adam had some interesting ideas about supporting allocators in functions in the fork.
Nov 25