1

While the title might not be very specific, it refers to the general understanding on how much we can play with reinterpret_cast<>() while dealing with memory buffers. Considering the following code:

struct foo { };

int main() {
    auto buffer = reinterpret_cast<foo*>(new char[3 * sizeof(foo)]);

    new (buffer) foo;
    new (buffer + 1) foo;

    std::destroy(buffer, buffer + 2);

    delete[] reinterpret_cast<char*>(buffer);
}

I asked myself a question - is this safe and correct?

When searching various sources of information, I encountered a lot of examples that used alignas. As it can be seen in this question, (at to least my understanding), the problem of not aligning was caused by a specific offset of the memory buffer pointer. If my understading is incorrect, please correct me.

The question itself is - Does this code safely mimicks the memory buffer of, let's say, std::vector<foo>? What does it lack? Is the alignas required here? Where would I apply it? How to minimally construct an example of what vector does in this case?

Fureeish
  • 12,533
  • 4
  • 32
  • 62
  • `new` should give you a pointer which has the alignment which can hold any fundamental type, so there's no need of `alignas` anywhere in your example. But your example will have problems, when you index `buffer`, because there's no array of `foo`s there, just `foo`'s placed next to each other. C++ differentiates between these cases. With current C++, it's impossible to rewrite `std::vector`, which is kind of funny... – geza Nov 06 '18 at 13:20
  • I'm positive the answer is "no", because although they're contiguous, they don't form an array such that iterating from `buffer` to `buffer + 2` works. Can't dive into the standard right now though, but you'll find that coming up in the discussions about how to implement `std::vector` without UB. – Quentin Nov 06 '18 at 13:20
  • @geza can you elaborate on the unimplementability of `std::vector`? I've seen a discussion somewhere, but can't manage to find it. **@downvoter**, care to explain? How can I improve my question? – Fureeish Nov 06 '18 at 13:25
  • @geza `new` is going to give the OP memory alligned for a `char`. If `foo` doesn't have the same alignment then that can be an issue. – NathanOliver Nov 06 '18 at 13:25
  • @NathanOliver could you please provide some source of examples where can I learn how to determinate whether the alignments check out? – Fureeish Nov 06 '18 at 13:27
  • @NathanOliver: maybe, I'm not sure. OP should call operator new (instead of new expression), and then it surely won't be a problem. – geza Nov 06 '18 at 13:31
  • @NathanOliver that question and answer completely satisfy me. Thank you for finding the duplicate. I would still love to wait for the mentioned discussion about the unimplementability of `std::vector` though – Fureeish Nov 06 '18 at 13:35
  • 1
    @Fureeish It was a comment on the top answer. It links to [here](https://stackoverflow.com/questions/48062346/is-a-pointer-with-the-right-address-and-type-still-always-a-valid-pointer-since/48065437#comment83125977_48065437) – NathanOliver Nov 06 '18 at 13:36
  • @Fureeish: I don't remember any specific question about this. But surely this has been discussed here. Maybe just tangentially (it came up because of something else, and discussed in comments). Do a search, and if you don't find a question about it, please put a question :) Because I think it worth a separate question, and not just some comments. – geza Nov 06 '18 at 13:38
  • 1
    @Fureeish: https://stackoverflow.com/questions/52996590/implementing-a-stdvector-like-container-without-undefined-behavior – geza Nov 06 '18 at 13:40
  • 1
    @Fureeish: btw., maybe it's the case that `std::vector` can be implemented without UB. But the solution would depend on implementation-defined behavior, for sure. I know two problematic things: array placement new (which could have implementation-defined overhead), and pointer arithmetic (can be circumvented by reinterpret_casting to integer, do the artithmetic there, and reinterpret_cast back - this is implementation defined) – geza Nov 06 '18 at 13:43
  • @Fureeish: ah, forget it, I think it has definitely UB. Objects need to be created one-by-one (I mean, to support `push_back`). So the array cannot be created by array placement new. Each element need to created separately, so strictly speaking, it won't be a proper array. – geza Nov 06 '18 at 13:50

0 Answers0