0

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

IanQ
  • 1,831
  • 5
  • 20
  • 29
  • 1
    Do you know how `strcpy()` knows how many characters, exactly, it needs to copy? Once you find out the answer to this question, take a look at what the 2nd character in `string_repr` is, and then you should be able to figure this out yourself! – Sam Varshavchik Apr 03 '21 at 18:37
  • 1
    More than likely this is caused by a NUL as previous commenters suggest. Try using `PyBytes_FromStringAndSize` instead. Likewise you shouldn't need to copy the string yourself as PyBytes will make a copy on its own. – Kyle Apr 03 '21 at 18:40

1 Answers1

3

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());
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60