HDFGroup / hdf5

Official HDF5® Library Repository
Other
577 stars 237 forks source link

CPP wrapper segfaults when variable length string to compound data type #4479

Open N-Jay-Dee opened 3 months ago

N-Jay-Dee commented 3 months ago

Trying to write a dataset to file, dataset is of compound type which includes a variable length string.

Sample Code

#include <H5Cpp.h>
#include <vector>
#include <string>

// NOTE: THIS CODE SEGFAULTS SO LONG AS THIS IS TRUE
bool recreateIssue = true;

constexpr uint32_t dataspaceRank = 1;
constexpr uint32_t datapointCount = 10;
constexpr hsize_t dataspaceDims[] = { 10 };

std::vector<std::string> stringData = 
{
    "1",
    "22",
    "333",
    "4444",
    "55555",
    "666666",
    "7777777",
    "88888888",
    "999999999",
    "0000000000"
};

std::string empty = "";

std::vector<uint32_t> uintData = 
{
    1,2,3,4,5,6,7,8,9,0
};

int main()
{
    // Open file
    H5::H5File file("test.hdf", H5F_ACC_TRUNC);

    // Create compound type
    // PLEASE NOTE: I am not using HOFFSET since in my real program I don't know the structure of the data until runtime
    H5::CompType compType( (size_t)100 );

    H5::StrType type = H5::StrType(0, H5T_VARIABLE);
    type.setCset(H5T_CSET_UTF8);

    compType.insertMember("uint1", 0, H5::PredType::NATIVE_UINT32);
    compType.insertMember("str", sizeof(uint32_t), type);
    compType.insertMember("uint2", sizeof(uint32_t) + sizeof(char *), H5::PredType::NATIVE_UINT32);
    compType.setSize(sizeof(uint32_t) + sizeof(char *) + sizeof(uint32_t));

    // Create dataset/space
    H5::DataSpace dataSpace(dataspaceRank, dataspaceDims);

    H5::DataSet dataSet = file.createDataSet("test", compType, dataSpace);

    // Organize data into buffer

    std::string databuffer(compType.getSize() * datapointCount, ' ');

    uint32_t offset = 0;
    for(uint32_t i = 0; i < datapointCount; i++)
    {
        databuffer.replace(offset, sizeof(uint32_t), (char *)&uintData[i], sizeof(uint32_t));
        offset += sizeof(uint32_t);

        if(recreateIssue)
            databuffer.replace(offset, sizeof(char *), stringData[i].c_str(), sizeof(char *));
        else
            databuffer.replace(offset, sizeof(char *), empty.c_str(), sizeof(char *));

        offset += sizeof(char *);

        databuffer.replace(offset, sizeof(uint32_t), (char *)&uintData[i], sizeof(uint32_t));
        offset += sizeof(uint32_t);
    }

    // Write buffer to file

    dataSet.write(databuffer, compType);

    file.close();

    return 0;
}

Platform

Additional context

N-Jay-Dee commented 3 months ago

backtrace from program

#0  0x00007ffff699ce57 in __strlen_avx2 () from /lib64/libc.so.6
#1  0x00007ffff7a85812 in H5T__conv_vlen () from /lib64/libhdf5.so.103
#2  0x00007ffff7a7a29b in H5T_convert () from /lib64/libhdf5.so.103
#3  0x00007ffff7a840df in H5T__conv_struct_opt () from /lib64/libhdf5.so.103
#4  0x00007ffff7a7a29b in H5T_convert () from /lib64/libhdf5.so.103
#5  0x00007ffff790e931 in H5D__scatgath_write () from /lib64/libhdf5.so.103
#6  0x00007ffff78f6426 in H5D__contig_write () from /lib64/libhdf5.so.103
#7  0x00007ffff790a260 in H5D__write () from /lib64/libhdf5.so.103
#8  0x00007ffff790a9aa in H5Dwrite () from /lib64/libhdf5.so.103
#9  0x00007ffff7621673 in H5::DataSet::write(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, H5::DataType const&, H5::DataSpace const&, H5::DataSpace const&, H5::DSetMemXferPropList const&) const () from /lib64/libhdf5_cpp.so.103
#10 0x0000000000402bc4 in main () at /home/nicholas.desmarais/Documents/hdf_example/src/main.cpp:75