C++ c_str of std::string returns empty

So, I’m running into an issue with the following code whereby the result of std::cout << cstr << std::endl is the single character

PyObject * CKKSwrapper::SerializeContext() {
    std::string s;                                      // 1
    std::ostringstream os(s);                           // 2
    Serial::Serialize(m_cc, os, SerType::BINARY);   // 3
    const std::string string_repr = os.str();                   // 4
    std::cout << string_repr << std::endl;                      // 5

    char *cstr = new char[string_repr.length() + 1];            // 6
    std::strcpy(cstr, string_repr.c_str());                     // 7
    std::cout << "******************************************************" << std::endl; // 8

    std::cout << string_repr << std::endl;                      // 9
    std::cout << "******************************************************" << std::endl; // 10
    std::cout <<  cstr << std::endl;                    // 11

    auto resp = PyBytes_FromString(cstr);               // 12
    return resp;
}

Checking the std::cout result on line 5 looks good and is non-empty.

@ � �4 lbcrypto::LPCryptoParametersCKKSlbcrypto::DCRTPoly � @ �

^ the first few characters (not sure if that helps)

Later, I create a char array and copy over the c_str to it which (I think) avoids the issue of a temporary result as was discussed https://stackoverflow.com/a/39006531/3532564

Don’t attempt to store the pointer returned by c_str(). If you need that string as a C-string for an extended period of time, allocate memory buffer for it yourself and copy the result of c_str() to that buffer.


I also found https://stackoverflow.com/a/35981001/3532564 which made me wonder if my string_repr object was being destroyed so I did a std::cout on line 9 and it looks good also.


Can anyone help me? I’m really not sure where the issue stems from. Unfortunately, I need to pass a char * [] to PyBytes_FromString despite what the name might make one think

Answer

Presumably the string contains one or more nul characters, resulting in strcpy() not copying all of the bytes. You also have a memory leak from not freeing cstr before you return from the function.

You can avoid both problems by bypassing the unnecessary string array and calling PyBytes_FromStringAndSize:

return PyBytes_FromStringAndSize(string_repr.c_str(), string_repr.size());