c++g++memset

error clearing an object of non-trivial type with memset


Well, the thing is simple, im getting warning: ‘void* memset(void*, int, size_t)’ clearing an object of non-trivial type ‘struct FormatHashBuffers(CBlock*, char*, char*, char*)::<unnamed>’; use assignment or value-initialization instead [-Wclass-memaccess] memset(&tmp, 0, sizeof(tmp)); on this function and idk why, when i build with g++ 5 no warning, but when i build with 7.1 or 8.5 i get the warning, any idea why or how to solve it? Thanks in advance.

    void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata,
                       char* phash1) {
    //
    // Pre-build hash buffers
    //
    struct
    {
        struct unnamed2
        {
            int nVersion;
            uint256 hashPrevBlock;
            uint256 hashMerkleRoot;
            unsigned int nTime;
            unsigned int nBits;
            unsigned int nNonce;
        }
        block;
        unsigned char pchPadding0[64];
        uint256 hash1;
        unsigned char pchPadding1[64];
    }
    tmp;
    memset(&tmp, 0, sizeof(tmp));

    tmp.block.nVersion = pblock->nVersion;
    tmp.block.hashPrevBlock = pblock->hashPrevBlock;
    tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
    tmp.block.nTime = pblock->nTime;
    tmp.block.nBits = pblock->nBits;
    tmp.block.nNonce = pblock->nNonce;

    FormatHashBlocks(&tmp.block, sizeof(tmp.block));
    FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));

    // Byte swap all the input buffer
    for (unsigned int i = 0; i < sizeof(tmp) / 4; i++)
        ((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);

    // Precalc the first half of the first hash, which stays constant
    SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);

    memcpy(pdata, &tmp.block, 128);
    memcpy(phash1, &tmp.hash1, 64);
}

Solution

  • You could default-initialize your member variables:

    struct {
        struct unnamed2 {
            int nVersion{};
            uint256 hashPrevBlock{};
            uint256 hashMerkleRoot{};
            unsigned int nTime{};
            unsigned int nBits{};
            unsigned int nNonce{};
        } block;
    
        unsigned char pchPadding0[64]{};
        uint256 hash1{};
        unsigned char pchPadding1[64]{};
    } tmp;
    

    With that there's no need for memset(&tmp, 0, sizeof(tmp)); and the warning will go away.