std::vector kétfélekép avagy támad a harcikuki

 ( Foltos | 2011. november 15., kedd - 17:07 )

Sziasztok!

C++ expertek véleményére lennék kíváncsi a következőkkel kapcsolatban:

Adott egy C++ programocska amely Visual studio 2008 alatt íródik, eredménye pedig egy DLL fájl lészen. Ez a DLL egy másik program plugin -ja, így az adott programhoz kapott .h és és .lib fájlokat kell használjam.

Csináltam egy fagolyó bonyolultságú osztályt TMocsing, néhány változóval, set_xx() get_xx() függvénnyel illetve egy std::vector bubu; vektorral. A .h amiben az osztályt definiálom (mocsing.h) hivatkozik egy rakat plugin header -re illetve a
vector -ra.

Abban a .cpp fájlban (csirkehus.cpp) ahol a mocsing.h -t include -olom, szintén vannak plugin headerek include -olva, valamint sokszoros include mélységben a vector is.

Mármost, olyan pofára esésben volt részem, hogy csak na! Ugyanis a csirkehus.cpp -ben máshogy sikeredett leforduljon a vector, mint a mocsing.cpp -ben. Ennek eredményeként a bubu.push_back() rendszeresen bad_accoc kivételeket dobált, ugyanis a vector _Myfirst, _Mylast és _Myend mutatói az osztályon belül rossz offset -tel címződtek. Megoldás:

  1. mocsing.h -ban hivatkozni ugyanarra a .h -ra, amelyik csirkehus.cpp -ben a vectort include -olja
  2. csirkehus.cpp -ben std::vector bubu; változót létrehozni TMocsing bárminemű hivatkozása előtt.

Látott már valaki hasonlót?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

DLL felületi header-be és osztályba soha ne tegyél STL könyvtári element. Oka: az egyes VS verziókban* az STL mérete változhat. Simán előfordulhat, hogy az STL-es osztályt használó könyvtár kevés memóriát allokál az STL-t tartalmazó, a DLL felületéről vett osztályodnak.

Tipikus meogoldás worker oszályt írni, ami tartalmazza az STL-es cuccaidat.

DLL headerben:

#pragma once

class exampleWorker;

#ifdef PROJECTNAME
#define projectEXPORT __declspec( dllexport )
#else
#define projectEXPORT __declspec( dllimport )
#endif

class projectEXPORT example
{
public:
 example();
 ~example();
 size_t size();
private:
 exampleWorker * worker;
};

Cpp-ben:

#include "example.h"

#include <vector>

class exampleWorker
{
 std::vector<int> store;
};

example::example(void)
 : worker(new exampleWorker)
{
}

example::~example(void)
{
 if ( this->worker )
 {
  delete this->worker;
  this->worker = 0;
 }
}

size_t example::size(void)
{
 return this->worker->store.size();
}

Hasznos olvasni való. És ez is.

*: VS 2005 / 2005 SP1 / 2008 / 2008 SP1 / 2010 / 2010 SP1
--
http://naszta.hu

Na, rendesen rám ijesztettetek.... Egyelőre működik a dll de hosszabb távon rendbe kell tegyem ezt a dolgot :S Elképzelni sem merem mi lesz itt, ha más verziójú binárissal akarják majd használni. Majd hétfőn kiderül a prezentáción... ;)

Akárhogy is, köszönöm az okítást mindkettőtöknek. Most már el tudok indulni.

Ez csak akkor fog menni, ha pontosan ugyanazt a VS verziót használod amit a dll.
Nem csak a főverzió, de a Service Pack is számít, illetve az sem mindegy, hogy debug vagy release.

Welcome to the world of MS.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Azért tegyük hozzá, hogy ez nem bug, hanem feature. Mármint:

- az STL inline (tehát ahol használod, ott jó a teljesítménye),
- a bináris hosszú évekig hordozható, nem kell fordítgatni hetente. Gyakorlatilag egy VS 6.0 alatt fordított DLL-t is tudsz akár ma is használni.

Ennek az az ára, hogy az STL nincs DLL felületen. Együtt lehet élni ezzel a megkötéssel.
--
http://naszta.hu

Azért a gcc srácok megoldották valahogy, hogy ritkábban változzon az STL, és nincs is annyi szívás vele...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Azért tegyük hozzá, hogy gcc alatt nem szempont a bináris kompatibilitás évekig. Többször fordult már elő, nem is egy distro-val, hogy a libc és a libc++ verzió váltást is csak fő disztró verzió váltáskor érvényesítettek, pont ebből az okból (hogy legalább a major disztro verzión belül legyen olyan, mintha szempont lenne a bináris kompatibilitás).
--
http://naszta.hu

"Ennek az az ára, hogy az STL nincs DLL felületen. Együtt lehet élni ezzel a megkötéssel."

Akkor már inkább megkötöm a fordító verziót... Egy-egy osztály esetén még lehet itt wrapperekkel bohóckodni, de egyébként esélytelen.
Nagyobb projectek is vagy megkötik a fordító verzióját (Qt), vagy több verziójú fordítóhoz is elkészítik a binárist. (TBB, OpenCV)

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o

Meg egy apróság:

Ha #include <istream>-ot vagy >#include <ostream>-ot szúrsz be és std::istream &is vagy std::ostream &os van az osztály felületén, azért nem károg a VS. Azt nem tudom, hogy mennyire átjárható, mert nem próbáltam, de kiváncsi lennék rá. (Pl.: tud egy VS 2005 SP1-es DLL normálisan menni a VS 2010 SP1-as környezetben?)
--
http://naszta.hu

elirtad a cimet, std::vector-ra gondoltal gondolom

Köszi, javítva.