0

From what I get, it should normally be correct to use a placement-new for reconstructing a type like this:

A a;
auto aptr = new(&a) A();

So I decided to try it with a class member like this:

struct PackedTest {
    char a = 0;
    int b = 0;
    void setb() {
        new(&b) int(5);
    }
};

int main() {
    PackedTest p;
    std::cout << sizeof(p) << "\n";
    std::cout << p.b << "\n";
    p.setb();
    std::cout << p.b << "\n";
}

and everything seems fine. But then I thought if we can always do the same with struct members? Let's assume that we have following packed struct:

struct __attribute__((packed)) PackedTest {
    char a = 0;
    int b = 0;
    void setb() {
        new(&b) int(5);
    }
};

Is this code still valid or it is undefined behavior? Because in previous case, alignment of b was equal to alignment of int, so placement-new should be fine. But in this new struct, alignment of b is 1 which is less than alignment requirement int.

Should I always add alignas(T) like:

struct __attribute__((packed)) PackedTest {
    char a = 0;
    alignas(int) int b = 0;
    void setb() {
        new(&b) int(5);
    }
};

as a rule of thumb for any variable that will be used as buffer for placement-new (though it seem this alignas is somehow affects whole structure, not just b)?

Afshin
  • 8,839
  • 1
  • 18
  • 53
  • Placement new should only be used on memory that doesn't already contain an object. I'm not sure what the spec says about it, but I strongly suspect what you're doing is undefined behavior. – Mark Ransom Dec 25 '21 at 07:12
  • @MarkRansom I really didn't see this requirement that you mention anywhere. I just know that memory should have correct alignment for our required type. – Afshin Dec 25 '21 at 07:14
  • For the delete there's [c++ - Placement new overriding existing objects - Stack Overflow](https://stackoverflow.com/questions/39287330/placement-new-overriding-existing-objects) (but it doesn't say it's undefined behavior?) – user202729 Dec 25 '21 at 07:15
  • @MarkRansom I just remembered that I have seen placement new on memory containign object in cppref at least. in this example:https://en.cppreference.com/w/cpp/utility/launder – Afshin Dec 25 '21 at 07:17
  • There's [c++ - Do I really have to worry about alignment when using placement new operator? - Stack Overflow](https://stackoverflow.com/questions/11781724/do-i-really-have-to-worry-about-alignment-when-using-placement-new-operator) which seems to apply to the case here... – user202729 Dec 25 '21 at 07:23
  • It results in undefined behaviour. `std::vector<100> a; auto* aptr = new(&a) std::vector(100);`. The least trouble is memory leak. – 273K Dec 25 '21 at 07:54
  • @S.M. you need to call destructor in your case manually. so it will be something like this:`std::vector a(5); a.~vector(); auto* aptr = new(&a) std::vector(5);` (though not sure if it is still valid). But my question is more regarding alignment requirement. should I always add `alignas` to storage to make sure everything will be valid? – Afshin Dec 25 '21 at 08:16
  • The C++ standard doesn't say anything about the meaning or effects of `__attribute__((packed))`. You are in the land of implementation-defined behavior. Consult the documentation for the particular implementation you are using. – Igor Tandetnik Dec 25 '21 at 15:08
  • @Afshin The examples in your question do not call destructors. – 273K Dec 25 '21 at 16:27
  • As already mentioned above it is more about `packed` attribute than placement new. [Here](https://stackoverflow.com/a/8568441) it is discussed even `*(&b) = 5` cause segmentation fault on some system. Also in the linked answer they say gcc 9 and above should have `-Waddress-of-packed-member` warning enabled by default. – dewaffled Dec 25 '21 at 19:54

0 Answers0