最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Unwanted implicit object creation in an array of std::byte VS char - Stack Overflow

programmeradmin1浏览0评论

It seems that std::byte is generally meant to replace the use of char in buffers for allocating blocks of raw memory.

But I'm worried about the fact that std::byte can implicitly create objects in an array while char cannot:

"Objects of implicit-lifetime types can also be implicitly created by: except during constant evaluation, operations that begin lifetime of an array of type unsigned char or std::byte, in which case such objects are created in the array".

Consider this example of manually controlling memory allocation and lifetime of an int object:

#include <stdlib.h>
#include <memory>

int main() {
    
    //OPTION 1: allocate storage with an array of char
    //(no objects are created; char cannot implicitly create objects in an array)
    char* buffer = (char*)malloc(sizeof(int));
    
    //OPTION 2: allocate storage with an array of std::byte
    //(does std::byte implicitly create objects in the array here? it's capable of doing so)
    //std::byte* buffer = (std::byte*)malloc(sizeof(int));
    
    //explicitly create an int object, starting its lifetime:
    int* ptr = ::new(buffer) int(11);

    //explicitly destroy the int object, ending its lifetime:
    std::destroy_at(ptr);                       
    
    //deallocate storage (if this is an std::byte array, should you call their destructors first?):
    free(buffer);                          
}

If you want to allocate raw memory so you can create objects in it (for example by using placement new), why would you want std::byte to potentially fill the buffer with implicitly created objects beforehand?

Wouldn't it be better to use char so you can avoid potential undefined behavior related to the lifetime of any implicitly created std::byte objects (accessing them outside of their lifetimes by accident, forgetting to destroy them before de-allocating the memory, etc)?

I just want a block of raw memory where I can manually create & destroy objects, not a block of memory plus a bunch of implicit objects I never asked for that could silently introduce undefined behavior while I'm trying to use the block.

Thanks.

It seems that std::byte is generally meant to replace the use of char in buffers for allocating blocks of raw memory.

But I'm worried about the fact that std::byte can implicitly create objects in an array while char cannot:

"Objects of implicit-lifetime types can also be implicitly created by: except during constant evaluation, operations that begin lifetime of an array of type unsigned char or std::byte, in which case such objects are created in the array".

Consider this example of manually controlling memory allocation and lifetime of an int object:

#include <stdlib.h>
#include <memory>

int main() {
    
    //OPTION 1: allocate storage with an array of char
    //(no objects are created; char cannot implicitly create objects in an array)
    char* buffer = (char*)malloc(sizeof(int));
    
    //OPTION 2: allocate storage with an array of std::byte
    //(does std::byte implicitly create objects in the array here? it's capable of doing so)
    //std::byte* buffer = (std::byte*)malloc(sizeof(int));
    
    //explicitly create an int object, starting its lifetime:
    int* ptr = ::new(buffer) int(11);

    //explicitly destroy the int object, ending its lifetime:
    std::destroy_at(ptr);                       
    
    //deallocate storage (if this is an std::byte array, should you call their destructors first?):
    free(buffer);                          
}

If you want to allocate raw memory so you can create objects in it (for example by using placement new), why would you want std::byte to potentially fill the buffer with implicitly created objects beforehand?

Wouldn't it be better to use char so you can avoid potential undefined behavior related to the lifetime of any implicitly created std::byte objects (accessing them outside of their lifetimes by accident, forgetting to destroy them before de-allocating the memory, etc)?

I just want a block of raw memory where I can manually create & destroy objects, not a block of memory plus a bunch of implicit objects I never asked for that could silently introduce undefined behavior while I'm trying to use the block.

Thanks.

Share Improve this question edited Jan 20 at 20:27 greenlagoon asked Jan 20 at 17:44 greenlagoongreenlagoon 1111 silver badge6 bronze badges 8
  • 1 "But I'm worried about the fact that std::byte can implicitly create objects while char cannot." This needs an example code – 463035818_is_not_an_ai Commented Jan 20 at 18:02
  • pretty sure that the runtime behaviour of std::byte will be identical to unsigned char as that's basically what it is – Alan Birtles Commented Jan 20 at 18:08
  • 2 std::byte can implicitly create objects while char cannot. Can you explain what you mean? – 3CxEZiVlQ Commented Jan 20 at 18:29
  • std:: byte is a primitive, it doesn't have a lifetime – catnip Commented Jan 20 at 19:00
  • 2 And anyway, if you didn't get the pointer from malloc (or its cousins), you cannot free that pointer. – BoP Commented Jan 20 at 20:04
 |  Show 3 more comments

1 Answer 1

Reset to default 3

Wouldn't it be better to use char so you can avoid potential undefined behavior related to the lifetime of any implicitly created std::byte objects

No. See [intro.object]/11

Some operations are described as implicitly creating objects within a specified region of storage. For each operation that is specified as implicitly creating objects, that operation implicitly creates and starts the lifetime of zero or more objects of implicit-lifetime types ([basic.types.general]) in its specified region of storage if doing so would result in the program having defined behavior. If no such set of objects would give the program defined behavior, the behavior of the program is undefined. If multiple such sets of objects would give the program defined behavior, it is unspecified which such set of objects is created.
[Note: ... ]

The abstract machine implicitly creates objects only if doing so would give the program defined behavior. So, if you choose to use a std::byte array instead of a char array, it makes it more likely, not less, that your program has defined behavior.

If you only ever attempt to access or refer to objects that you explicitly constructed into a std::byte buffer, and never attempt to access or refer to any implicitly created objects, then it is not possible to get UB related to the lifetimes of those implicitly created objects, and they don't have any effect on the program's observable behavior.

However, your question is not actually about creating a char array versus creating a std::byte array; it's about calling malloc. The standard specifies that malloc implicitly creates objects in the buffer that it returns to you; whether you cast the void* result to char*, unsigned char*, or std::byte* doesn't take away malloc's implicit object creation ability.

发布评论

评论列表(0)

  1. 暂无评论