简体   繁体   中英

Strange segfault in unique_ptr

After a small modification in my code I encountered a segfault while running it and I can't figure out why.

Here is the code working:

std::shared_ptr<UCHAR> myClass::myMethod(const char *str)
{
    size_t strLen = strlen(str);
    ULONG paddedLen = (strLen % this->bufferLen)
        ? ((strLen / blockSize) + 1) * this->bufferLen
        : strLen;

    std::unique_ptr<UCHAR> padded = std::make_unique<UCHAR>(paddedLen);
    memset(padded.get(), 0, paddedLen);
    memcpy(padded.get(), str, strLen);

    std::unique_ptr<UCHAR> buffer = std::make_unique<UCHAR>(this->bufferLen);
    memcpy(buffer.get(), this->buffer, this->bufferLen);

...
}

Here is the code failing:

std::shared_ptr<UCHAR> myClass::myMethod(const char *str)
{
    size_t strLen = strlen(str);
    ULONG paddedLen = (strLen % this->bufferLen)
        ? ((strLen / blockSize) + 1) * this->bufferLen
        : strLen;

    std::unique_ptr<UCHAR> padded = std::make_unique<UCHAR>(paddedLen + 1); <-- Added +1 here
    memset(padded.get(), 0, paddedLen + 1);  <--Added +1 here
    memcpy(padded.get(), str, strLen);

    std::unique_ptr<UCHAR> buffer = std::make_unique<UCHAR>(this->bufferLen);  <---Crashes here
    memcpy(buffer.get(), this->buffer, this->bufferLen);

...
}

The only difference is I added a +1 when alloccating padding and memsetting it.

It crashes when making the second unique pointer.

Does anything seems wrong with my code / te way I am using the unique_ptr?

For informations: compiled on Windows using QMake with Mingw 7.3.0 32-bit

std::unique_ptr<UCHAR> padded = std::make_unique<UCHAR>(paddedLen + 1); <-- Added +1 here std::unique_ptr<UCHAR> buffer = std::make_unique<UCHAR>(this->bufferLen); <---Crashes here

You are allocating single UCHAR s each time, whose values are paddedLen + 1 and this->bufferLen , respectively. You want arrays whose lengths are paddedLen + 1 and this->bufferLen elements instead. You need to use the template specializations of std::unique_ptr and std::make_unique() for arrays, eg:

auto padded = std::make_unique<UCHAR[]>(paddedLen + 1);

std::fill_n(padded.get(), paddedLen + 1, 0);
std::copy_n(str, strLen, padded.get());

auto buffer = std::make_unique<UCHAR[]>(this->bufferLen);
std::copy_n(this->buffer, this->bufferLen, buffer.get());

...

That being said, this can be simplified using std::vector instead:

std::vector<UCHAR> padded(paddedLen + 1, 0);
std::copy_n(str, strLen, padded.begin());

std::vector<UCHAR> buffer(this->bufferLen);
std::copy_n(this->buffer, this->bufferLen, buffer.begin());

...
std::unique_ptr<UCHAR> padded = std::make_unique<UCHAR>(paddedLen + 1);
memset(padded.get(), 0, paddedLen + 1);  <--Added +1 here
memcpy(padded.get(), str, strLen);

Any chance that strLen is greater than paddedLen? If your string is 80 and your bufferLen is 40, then paddedLen is 0, but now you're going to allocate a buffer of length 1 and copy 80 characters to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM