1

I've got a QByteArray of a given size. Accessing the raw data of the array returns char*, basically a character array.

I want to fill the QByteArray's whole size with a uint32_t value.

What is the safest and most efficient way to do this? I know I could use the Qt functions for appending data into an empty QByteArray, but then it would reallocate memory a lot of time.

I've got the following implementation in my mind, but I'm not sure if it is the best solution:

    auto data = QByteArray(fillSize, '0');
    auto dataPtr = data.data();
    auto fillValue = _byteswap_ulong(getFillValue());
    for (char* it = dataPtr; it != dataPtr + fillSize; it += 4)
    {
        auto help = reinterpret_cast<uint32_t*>(it);
        *help = fillValue;
    }
Attis
  • 573
  • 1
  • 7
  • 19
  • 1
    What you are doing is a violation of the [strict aliasing rule](https://stackoverflow.com/q/98650/10147399). It is formally undefined behavior. It does usually work though. You can use `std::fill_n` for that as well: `std::fill_n(reinterpret_cast(arr), fillSize / sizeof(int), fillValue);` – Aykhan Hagverdili Jun 02 '21 at 12:21
  • Thanks, that helped a lot! Is there any kind of source that lists the rules which must not be violated to avoid UB? – Attis Jun 02 '21 at 13:15
  • 1
    I would say you should know [the most common ones](https://stackoverflow.com/q/367633/10147399), like accessing to memory you don't own, etc. Then just read documentation of the functions you use as you go. – Aykhan Hagverdili Jun 02 '21 at 13:34

2 Answers2

1

You can just use QByteArray::reserve(int size) to avoid reallocations.

mugiseyebrows
  • 4,138
  • 1
  • 14
  • 15
1

Accessing a char array as if it were an int array is a violation of the strict aliasing rule.

Aside from that, it is possible that your array is misaligned for int. Misaligned access is a major problem as some processors can't do it at all, while others can do it but very slowly. It is also undefined behavior.

Here's a version that doesn't have any alignment issues or strict aliasing issues:

#include <stddef.h>  // for size_t
#include <stdint.h>  // for int32_t
#include <string.h>  // for memcpy

void Fill(char* const arr, size_t const size, int32_t const value) noexcept {
  for (size_t i = 0; i + sizeof(value) <= size; i += sizeof(value))
    memcpy(arr + i, &value, sizeof(value));
}

Also note that endianness of the CPU will matter if you plan to store this data or to send it though network.

Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
  • Okay so just for the sake of completeness, what extra safety measures have to be followed considering endianness? Because it was an issue with one of my previous implementations. (I had to change the byte order to receive a correct output. FYI: I'm working with sparse images. ) I'm guessing you have to consider the endianness of the solution you use vs. the default endianness of the platform you're working on. – Attis Jun 02 '21 at 14:17
  • 1
    @Attis if you are doing serialization, the best you can do is to use a serialization library. Otherwise, just make sure you don't serialize as one endianness and desterilize as the other. It's a big deal if you send files across platforms with different endianness. – Aykhan Hagverdili Jun 02 '21 at 14:24