1

I'm trying to copy a structure to be read by another program.

Source program :

        struct datas{               
            std::string key;
        };

        datas mystructure = datas();
        std::string mychar = "mychar";// if length of char > 8, it doesn't get copied.

        mystructure.key = mychar;

        WriteToResources(param, 0, (BYTE*)&mystructure, sizeof(mystructure));

Destination program :

struct datas{               
            std::string key;
        };

datas mystructure;
memcpy(&mystructure, pbindata, rsrcsize);

std::cout << (char*)mystructure.key.c_str();

When mychar's length is <= 8 it gets copied to the resource and is read fine by the destination program. However, if mychar's length is > 8 nothing gets copied.

Thank you for your time.

wolfk
  • 15
  • 1
  • 4
  • It's not possible to write complex types like string that way because internally the string class contains pointers and they have no meaning when you read them back in. Instead write out the string length, followed by the string characters. Do the opposite when you read it back in. – john Sep 09 '18 at 09:24
  • Did you try char array instead of std::string which does have small string optimization for small strings and heap data when the data length increases? – PraAnj Sep 09 '18 at 09:25
  • 1
    Ok, I will try to do so, thanks for your quick answer. – wolfk Sep 09 '18 at 09:25
  • The reason for the difference when length <= 8 is that some string implementations use something called the small string optimization, which stores string characters directly in the object instead of using pointers when the string is small. – john Sep 09 '18 at 09:26
  • Serializing a struct via memcpy or via reading/writing from the instance pointer is unsafe at best. And will absolutely not work if the struct/class has anything other that plain-old-data types (int, char, double, etc... or arrays thereof). – selbie Sep 09 '18 at 09:26
  • Suggestion: With the wide-open availability of many open source JSON reader/writer libraries, such as the one in Boost library, it's a lot easier to serialize data to text than it is to binary. XML would also work... – selbie Sep 09 '18 at 09:32
  • Avoid using stl types like std::string when you share data across process/dll boundary. Instead use native types like char/int/flat etc and adhere to ABI rule. – GSAT Sep 09 '18 at 10:43

1 Answers1

2

First, I do not recommend doing this for production code. Please use a proper data sharing mechanism. You can solve this for now by using plain char array given the size known at compile-time instead of std::string which might allocate memory in the head for long strings.

Second, for < 8 you experience what is called SSO (Small String Optimization) of std::string. Many std::string implementations does have this optimization now. This value will not be 8 always.

Third, for > 8 you have only have the meta data (size, capacity, pointer to heap data) in your structure copy. All data lies in the heap. Read this skeleton implementation.

EDITED: Read this post as well.

DATA SHARING : Read this post.

  1. https://learn.microsoft.com/en-us/windows/desktop/Memory/creating-named-shared-memory
  2. https://www.boost.org/doc/libs/1_38_0/doc/html/interprocess.html
PraAnj
  • 899
  • 1
  • 10
  • 27