template class in DLL (g++/Cygwin)

D

David Komanek

Hi all,

I am trying to learn more about how to use g++/Cygwin to produce dll
files on WinXP. And I have a problem which at the first look seems to
be an obvious dll-export problem, but I don't think this is really the
issue. Here is a description of my problem.

MathLibrary.dll:
- SpaceTimeVector (uses various stuff from this dll)

PhysLibrary.dll:
- PointMassless (uses instances of SpaceTimeVector)
- PointMassive (derived from PointMassless + a few simple data and
method members)
- SetPoints as a template class (see bellow)

Test framework(binary .exe):
- TestPhysLibraryTemplate as a template class for various tests. It
has a static member function TestPhysLibraryAbstract* getInstance() {
return(new T);}
- TestPhysLibraryAbstract (from this type are devired various tester
classes, each has to have a member method called void runTest() which
contains concrete tests)
- PhysLibraryTest (instantiates TestPhysLibraryTemplate and passes
this instance to member function testFactory as a parameter, where
runTest() is ran and the result is evaluated


This works for me fine for some simple tests on PointMassless and
PointMassive instances (of regular classes). But I have a big problem
with SetPoints which is a template class. This class contains a
private member called points which is std::vector of the same type as
the class template type parameter. Linker gives following info:

Info: resolving vtable for PhysLibrary::pointMasslessby linking to
__imp___ZTVN11PhysLibrary13PointMasslessE (auto-import)
Info: resolving vtable for PhysLibrary::pointMassiveby linking to
__imp___ZTVN11PhysLibrary12PointMassiveE (auto-import)

It seems o.k. to me, because it vas resolved to the proper template
class instances. But running the test it crashes with

5 [main] PhysLibraryTest 2136 handle_exceptions: Exception:
STATUS_ACCESS_VIOLATION

What seems strange to me, the problem only arises when I use at least
two instances of the template class. For the first one, it works fine,
the runtime error arises only if I try to add data to the vector<> of
the second instance.

Does anybody know here, what conceptual mistake am I doing here ?
Bellow is copy of the relevant parts of the code.

Thank you very much in advance.

David Komanek



setPoints.h:
============
#ifndef _SETPOINTS_H_
#define _SETPOINTS_H_

#include <ctype.h>
#include <vector>
#include <bitset>
using namespace std;

namespace PhysLibrary
{

template<class PointType>
class SetPoints
{
public:
SetPoints<PointType>() { };
virtual ~SetPoints<PointType>() { };
vector<PointType> getPoints();
unsigned long countPoints();
void addPoint(PointType *);
void removePointsAll();
//private: //commented out untill the issues are resolved to be
able to get the address of private members directly
vector<PointType> points;
};

template<class PointType>
vector<PointType> SetPoints<PointType>::getPoints()
{
vector<PointType> v = new vector<PointType>(this->points);
return v;
}

template<class PointType>
unsigned long SetPoints<PointType>::countPoints()
{
return ((unsigned long) (points.size()));
}

template<class PointType>
void SetPoints<PointType>::addPoint(PointType *p)
{
points.push_back(*p);
}

template<class PointType>
void SetPoints<PointType>::removePointsAll()
{
points.clear();
}

}; // namespace

#endif //_SETPOINTS_H_





TestPhysLibrarySetPoints.h
==========================
#ifndef _TESTPHYSLIBRARYSETPOINTS_H_
#define _TESTPHYSLIBRARYSETPOINTS_H_

#include "TestPhysLibraryAbstract.h"
#include "../PhysLibrary/Primitives/PointMassless.h"
#include "../PhysLibrary/Primitives/PointMassive.h"
#include "../PhysLibrary/Primitives/PhysFunctions.h"
#include "../PhysLibrary/Compounds/SetPoints.h"

class TestPhysLibrarySetPoints : public TestPhysLibraryAbstract
{
public:
TestPhysLibrarySetPoints();
virtual ~TestPhysLibrarySetPoints();
virtual void runTest();
};

#endif //_TESTPHYSLIBRARYSETPOINTS_H_




TestPhysLibrarySetPoints.cpp
============================
#include "TestPhysLibrarySetPoints.h"

TestPhysLibrarySetPoints::TestPhysLibrarySetPoints()
{
}

TestPhysLibrarySetPoints::~TestPhysLibrarySetPoints()
{
}

void TestPhysLibrarySetPoints::runTest()
{
double coord01[3] = {1,2,3};
double coord02[3] = {11,-3,28.0};
double veloc01[3] = {-1,8,1.5};
double veloc02[3] = {5,0,-1};
bool dimension_characteristics[3] = {true,true,true};
MathLibrary::SpaceTimeVector *c1 = new
MathLibrary::SpaceTimeVector(coord01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *c2 = new
MathLibrary::SpaceTimeVector(coord02, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v1 = new
MathLibrary::SpaceTimeVector(veloc01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v2 = new
MathLibrary::SpaceTimeVector(veloc02, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *c3 = new
MathLibrary::SpaceTimeVector(coord01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *c4 = new
MathLibrary::SpaceTimeVector(coord02, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v3 = new
MathLibrary::SpaceTimeVector(veloc01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v4 = new
MathLibrary::SpaceTimeVector(veloc02, 3, dimension_characteristics,
3);
PhysLibrary::pointMassive *pm1 = new PhysLibrary::pointMassive(*c1,
*v1, 8);
PhysLibrary::pointMassive *pm2 = new PhysLibrary::pointMassive(*c2,
*v2, 8);
PhysLibrary::pointMassless *pl1 = new PhysLibrary::pointMassless(*c3,
*v3);
PhysLibrary::pointMassless *pl2 = new PhysLibrary::pointMassless(*c4,
*v4);

//following two lines are responsible for the linker info
typedef PhysLibrary::SetPoints<PhysLibrary::pointMassive> setMassive;
typedef PhysLibrary::SetPoints<PhysLibrary::pointMassless>
setMassless;

setMassive *sp1 = new setMassive();
cout << typeid(sp1->points).name() << endl;
cout << (&(sp1->points)) << endl;
sp1->addPoint(pm1); // WORKS FINE
sp1->addPoint(pm2); // WORKS FINE

// commenting out the following block makes the program working :)
setMassless *sp2 = new setMassless();
cout << typeid(sp2->points).name() << endl;
cout << (&(sp2->points)) << endl;
sp2->addPoint(pl1); // CRASHES THE PROGRAM !!!!
sp2->addPoint(pl2);
}




OUTPUT of the :
=======
St6vectorIN11PhysLibrary12PointMassiveESaIS1_EE
0x100842a4
St6vectorIN11PhysLibrary13PointMasslessESaIS1_EE
0x100852bc
4 [main] PhysLibraryTest 3972 handle_exceptions: Exception:
STATUS_ACCESS_VIOLATION
604 [main] PhysLibraryTest 3972 open_stackdumpfile: Dumping stack
trace to PhysLibraryTest.exe.stackdump
 
D

David Komanek

Well, after the whole night by the comp I found the cause: missing copy
constructor. But the symptoms are evil, do not understand why compiler
did not detected it. What makes me even more frustrated is that copying
STL vector does not perform deep copying of compound objects, but this
is probably my fault, too. I am seeking for some good guide how to use
containers for storing complex objects (not pointers to them). Every
help highly is appreciated :)

Thanks,

David



David said:
Hi all,

I am trying to learn more about how to use g++/Cygwin to produce dll
files on WinXP. And I have a problem which at the first look seems to
be an obvious dll-export problem, but I don't think this is really the
issue. Here is a description of my problem.

MathLibrary.dll:
- SpaceTimeVector (uses various stuff from this dll)

PhysLibrary.dll:
- PointMassless (uses instances of SpaceTimeVector)
- PointMassive (derived from PointMassless + a few simple data and
method members)
- SetPoints as a template class (see bellow)

Test framework(binary .exe):
- TestPhysLibraryTemplate as a template class for various tests. It
has a static member function TestPhysLibraryAbstract* getInstance() {
return(new T);}
- TestPhysLibraryAbstract (from this type are devired various tester
classes, each has to have a member method called void runTest() which
contains concrete tests)
- PhysLibraryTest (instantiates TestPhysLibraryTemplate and passes
this instance to member function testFactory as a parameter, where
runTest() is ran and the result is evaluated


This works for me fine for some simple tests on PointMassless and
PointMassive instances (of regular classes). But I have a big problem
with SetPoints which is a template class. This class contains a
private member called points which is std::vector of the same type as
the class template type parameter. Linker gives following info:

Info: resolving vtable for PhysLibrary::pointMasslessby linking to
__imp___ZTVN11PhysLibrary13PointMasslessE (auto-import)
Info: resolving vtable for PhysLibrary::pointMassiveby linking to
__imp___ZTVN11PhysLibrary12PointMassiveE (auto-import)

It seems o.k. to me, because it vas resolved to the proper template
class instances. But running the test it crashes with

5 [main] PhysLibraryTest 2136 handle_exceptions: Exception:
STATUS_ACCESS_VIOLATION

What seems strange to me, the problem only arises when I use at least
two instances of the template class. For the first one, it works fine,
the runtime error arises only if I try to add data to the vector<> of
the second instance.

Does anybody know here, what conceptual mistake am I doing here ?
Bellow is copy of the relevant parts of the code.

Thank you very much in advance.

David Komanek



setPoints.h:
============
#ifndef _SETPOINTS_H_
#define _SETPOINTS_H_

#include <ctype.h>
#include <vector>
#include <bitset>
using namespace std;

namespace PhysLibrary
{

template<class PointType>
class SetPoints
{
public:
SetPoints<PointType>() { };
virtual ~SetPoints<PointType>() { };
vector<PointType> getPoints();
unsigned long countPoints();
void addPoint(PointType *);
void removePointsAll();
//private: //commented out untill the issues are resolved to be
able to get the address of private members directly
vector<PointType> points;
};

template<class PointType>
vector<PointType> SetPoints<PointType>::getPoints()
{
vector<PointType> v = new vector<PointType>(this->points);
return v;
}

template<class PointType>
unsigned long SetPoints<PointType>::countPoints()
{
return ((unsigned long) (points.size()));
}

template<class PointType>
void SetPoints<PointType>::addPoint(PointType *p)
{
points.push_back(*p);
}

template<class PointType>
void SetPoints<PointType>::removePointsAll()
{
points.clear();
}

}; // namespace

#endif //_SETPOINTS_H_





TestPhysLibrarySetPoints.h
==========================
#ifndef _TESTPHYSLIBRARYSETPOINTS_H_
#define _TESTPHYSLIBRARYSETPOINTS_H_

#include "TestPhysLibraryAbstract.h"
#include "../PhysLibrary/Primitives/PointMassless.h"
#include "../PhysLibrary/Primitives/PointMassive.h"
#include "../PhysLibrary/Primitives/PhysFunctions.h"
#include "../PhysLibrary/Compounds/SetPoints.h"

class TestPhysLibrarySetPoints : public TestPhysLibraryAbstract
{
public:
TestPhysLibrarySetPoints();
virtual ~TestPhysLibrarySetPoints();
virtual void runTest();
};

#endif //_TESTPHYSLIBRARYSETPOINTS_H_




TestPhysLibrarySetPoints.cpp
============================
#include "TestPhysLibrarySetPoints.h"

TestPhysLibrarySetPoints::TestPhysLibrarySetPoints()
{
}

TestPhysLibrarySetPoints::~TestPhysLibrarySetPoints()
{
}

void TestPhysLibrarySetPoints::runTest()
{
double coord01[3] = {1,2,3};
double coord02[3] = {11,-3,28.0};
double veloc01[3] = {-1,8,1.5};
double veloc02[3] = {5,0,-1};
bool dimension_characteristics[3] = {true,true,true};
MathLibrary::SpaceTimeVector *c1 = new
MathLibrary::SpaceTimeVector(coord01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *c2 = new
MathLibrary::SpaceTimeVector(coord02, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v1 = new
MathLibrary::SpaceTimeVector(veloc01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v2 = new
MathLibrary::SpaceTimeVector(veloc02, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *c3 = new
MathLibrary::SpaceTimeVector(coord01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *c4 = new
MathLibrary::SpaceTimeVector(coord02, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v3 = new
MathLibrary::SpaceTimeVector(veloc01, 3, dimension_characteristics,
3);
MathLibrary::SpaceTimeVector *v4 = new
MathLibrary::SpaceTimeVector(veloc02, 3, dimension_characteristics,
3);
PhysLibrary::pointMassive *pm1 = new PhysLibrary::pointMassive(*c1,
*v1, 8);
PhysLibrary::pointMassive *pm2 = new PhysLibrary::pointMassive(*c2,
*v2, 8);
PhysLibrary::pointMassless *pl1 = new PhysLibrary::pointMassless(*c3,
*v3);
PhysLibrary::pointMassless *pl2 = new PhysLibrary::pointMassless(*c4,
*v4);

//following two lines are responsible for the linker info
typedef PhysLibrary::SetPoints<PhysLibrary::pointMassive> setMassive;
typedef PhysLibrary::SetPoints<PhysLibrary::pointMassless>
setMassless;

setMassive *sp1 = new setMassive();
cout << typeid(sp1->points).name() << endl;
cout << (&(sp1->points)) << endl;
sp1->addPoint(pm1); // WORKS FINE
sp1->addPoint(pm2); // WORKS FINE

// commenting out the following block makes the program working :)
setMassless *sp2 = new setMassless();
cout << typeid(sp2->points).name() << endl;
cout << (&(sp2->points)) << endl;
sp2->addPoint(pl1); // CRASHES THE PROGRAM !!!!
sp2->addPoint(pl2);
}




OUTPUT of the :
=======
St6vectorIN11PhysLibrary12PointMassiveESaIS1_EE
0x100842a4
St6vectorIN11PhysLibrary13PointMasslessESaIS1_EE
0x100852bc
4 [main] PhysLibraryTest 3972 handle_exceptions: Exception:
STATUS_ACCESS_VIOLATION
604 [main] PhysLibraryTest 3972 open_stackdumpfile: Dumping stack
trace to PhysLibraryTest.exe.stackdump
 
R

Richard Herring

David Komanek said:
Well, after the whole night by the comp I found the cause: missing copy
constructor. But the symptoms are evil, do not understand why compiler
did not detected it. What makes me even more frustrated is that copying
STL vector does not perform deep copying of compound objects,

That's up to the objects themselves. All the STL containers can do is
to call their copy constructor or assignment operator. It's your
responsibility to make them (and, therefore, their members, recursively)
do the necessary deep copy.
but this is probably my fault, too. I am seeking for some good guide
how to use containers for storing complex objects (not pointers to
them).

Ensure that they satisfy the requirements of CopyConstructible and
Assignable.
 
K

Karl Heinz Buchegger

David said:
Well, after the whole night by the comp I found the cause: missing copy
constructor. But the symptoms are evil, do not understand why compiler
did not detected it.

Well. The thing is:
There is no copy constructor missing. If you don't write one on your
own, then the compiler will write one for you. But of course it can
be that this compiler generated one does the wrong thing. It does:
* copy construct all the base classes
* do a memberwise construction and initialzation from the passed object
(and thus is a shallow copy)
If this does not fit your needs (especially the second point), then you
will see such symptoms, and you have to write on on your own.

So in a nutshell: *Whenever* you write a class or add a member to a class,
you should check for:
do I have special needs for some of the members in the destructor ?
do I have special needs for some of the members in the copy constructor ?
do I have special needs for some of the members in the assignment operator ?

Now it can be that you really don't want a copy constructor. That can be eg. because
copy construction is costly process and you want to hinder yourself to do that.
In that case you can do: declare (but do not implement!) a copy constructor in
the private section of your class. This way you supress the compiler to generate
one of his own. But since it is private it cannot be used outside the class. And
even if you use it inside a class member function (which can access private members)
you will get a linker error, because it is not implemented.

Oh. BTW: There is the famous 'rule of three':
If you need one of:
destructor
copy constructor
assignment operator
you most likely need all 3 of them
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,119
Latest member
IrmaNorcro
Top