79460

Difference in byte-size of STL-containers in Visual Studio 2010 and 2012

<strong>I am working in a solution with projects of both VS2010 and VS2012.</strong>

The VS2010 project calls functions in VS2012 and vice-versa. This worked fine at first, but when I also needed to share variables between both projects I noticed variables doesn't seem to have the same memory alignments and each project interprets the same memory address differently.

<strong>Update</strong>: It only seems to occur when using <strong>STL-containers</strong>, other structs and classes which doesn't contain std:: works fine.

To illustrate the problem, the following code should yeld different results when run on different Visual Studio versions.

#include <string> #include <vector> int main() { int stringSize = sizeof(std::string); // Yelds 32 on VS2010, 28 on VS2012 int intVectorSize = sizeof(std::vector<int>); // Yelds 20 on VS2010, 16 on VS2012 return 0; };

Updating both projects to the same version is <strong>not possible</strong> for me yet as I have a few dependencies tied to each version.

<strong>Does anyone know of a solution or a way to bypass the problem?</strong>

I will upgrade both project to the VS2012 compiler as soon as it's possible, but right now I'm hopping for a <strong>quick and dirty solution</strong> so I just can get along with working. Since it only seems to occur with STL-containers, is it perhaps possible to use an older version of the library on all projects? Or is it possible to fool the compiler? Perhaps changing the padding size?

Also, <strong>the first</strong> element in a std::vector seems to read fine, only <strong>subsequent</strong> elements in the vector seems to get <strong>scrambled</strong>. (See picture.)

<img src="https://i.stack.imgur.com/WRJP2.png" alt="Debug Image">

Image of debugging the "Fetched" variable in "main.cpp" compiled in both 2010 and 2012.

<hr>

<strong>Someone wanted me to clarify the way variables is being shared.</strong>

We are compiling the first project into a DLL in VS2012 compile mode and then trying to access that one in VS2010.

Here's some code to recreate the problem. If you would like to try for yourself you can download the full VS2012 solution here.

<strong>This code is compiled into a DLL using VS2012.</strong>

DllExport.h

#ifdef DLLHELL_EX #define DLL_API __declspec(dllexport) #else #define DLL_API __declspec(dllimport) #endif #include <vector> #include <string> class DLL_API Foo { public: Foo(); ~Foo(); std::vector<std::string>* exposedMember; };

DllExport.cpp

#include "DllExport.h" Foo::Foo() { // Create member exposedMember = new std::vector<std::string>(); // Fill member with juicy data for(int i=0; i<5; i++) exposedMember->push_back("Fishstick"); } Foo::~Foo() { // Clean up behind ourselves like good lil' programmers delete exposedMember; }

<strong>This code uses the DLL and is compiled using VS2010.</strong>

main.cpp

#include "DllExport.h" int main() { // Creating class from DLL Foo bar; // Fetching "exposedMember" from class std::vector<std::string>* member = bar.exposedMember; return 0; }

The DLL was created, using this tutorial

Answer1:

You absolutely should not mix types from different versions of the runtime. Even if they are the same size, they might store variables in different locations, or some algorithm might slightly change. Even if the types are exactly the same, different compilers might choose to represent them differently.

There really is no good way to do this. C++ doesn't guarantee the implementation of its standard library won't change, and compilers can't seem to agree on an ABI (even between versions of the same compiler) even if they didn't. When writing APIs for others to consume, most people choose to export only C types which are entirely under their control.

Answer2:

Since I don't have the option of not using different versions, the closest to solving the problem I think is by using pointers to <strong>STL-containers</strong> instead of accessing them directly (e.g. std::vector<std::string*>* instead of std::vector<std::string>*).

I would still very much prefer a <strong>non-pointer</strong> solution if it is possible, but at least this way I won't have to invent my own string and vector-class as a workaround.

<img src="https://i.stack.imgur.com/VhQZz.png" alt="Pointers inside visual studio">

<hr>

<strong>Update</strong>

People apparently didn't very much like this answer. Personally I think it's better being told there is a solution rather than being told something should not be done at all. The solution saved us as it allowed us to continue working until we could upgrade everything to the same compiler a few weeks later.

Although, the criticism has some merits. The solution although working could be very dangerous and it is probably a coincidence that the layout of the String class is identical in both compilers when allocated alone rather than as part of a struct.

A better solution would probably simply be:

Use C types instead, e.g. use .c_str() to expose a C string instead of accessing you string-directly from the DLL or replace all your strings with C strings.

I now think this is what @CoryNelson meant with most people choose to export only C types, but due to my ignorance and inexperience with C-types at the time, I didn't understand this, and I thought I was simply being told it was not possible and I was stupid for trying.

Also for people down-voting it would be greatly appreciated if you provided an explanation as to why instead of me having to guess on my own. I have no problem with criticism as long as a reason is given.

Recommend

  • Global VBA date format and decimal separator
  • Including direct dependency download links in setup.py
  • MATLAB Efficiently find the row that contains two of three elements in a large matrix
  • Gettings substrings between tags
  • F# Convert 'a discriminated union to string
  • PHP IntlDateFormatter wrong date/time conversion
  • replacing a value in all columns with value of that column
  • “Complex Header” not responsive in current DataTables.net build?
  • How to get to older Xcode beta version?
  • How can I make a right-click behave as a left-click for the purpose of selecting or focusing an obje
  • write text on image and show it to a imageview
  • Certain Arabic text gets incorrectly shown while other Arabic text gets showed normally?
  • How to change placeholder text in an autocomplete activity of android google place?
  • is it possible to insert a line break in this tooltip?
  • SQL: Getting the physical size of a subset of a table
  • Primefaces lazy datascroller calling load twice
  • how to populate a SQLite database and use that database in phonegap?
  • How to access meteor package name inside package?
  • Rest Services conventions
  • SonarQube: Cannot deactivate rule with missing quality profile
  • How Lists (specifically, RecyclerView with CardViews) in Android work
  • C: Incompatible pointer type initializing
  • why xml file does not aligned properly after append the string in beginning and end of the file usin
  • Combining SpatialPolygonsDataFrame of two neighbour countries
  • Change multiple background-images with jQuery
  • Insert into database using onclick function
  • Android screen density dpi vs ppi
  • Encrypt data by using a public key in c# and decrypt data by using a private key in php
  • Why HTML5 Canvas with a larger size stretch a drawn line?
  • Why doesn't :active or :focus work on text links in webkit? (safari & chrome)
  • DirectX11 ClearRenderTargetViewback with transparent buffer?
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Change an a tag attribute in JavaScript based on screen width
  • When should I choose bucket sort over other sorting algorithms?
  • Weird JavaScript statement, what does it mean?
  • Why winpcap requires both .lib and .dll to run?
  • Unanticipated behavior
  • Setting background image for body element in xhtml (for different monitors and resolutions)
  • Django query for large number of relationships
  • reshape alternating columns in less time and using less memory