i am the "proud" heir of an old VC++ DLL and try to understand a problem with it. My predecessor used some union/struct constructions for dataprocessing. Now i debugged it to a point he put the data in the struct, but the whole app crashes, printing a memory dump and no try-catch works.
A small CodeExample.
MyCode.h:
union
{
struct
{ double _dm;
};
struct
{ double _dm;
bool _links;
};
struct
{ double _dm;
double _dummy;
double _angle;
};
struct
{ double _dm;
double _angle;
double _dummy1;
string _name;
string _descr;
double _param_d1, _param_d2, _param_d5;
double _dummy2;
string _dummy3;
int _epuzae;
int _param_i2;
string _sob, _snr2, _param_s3, _param_s4;
void *_data;
};
struct
{ void *_data;
};
}
MyCode.cpp
... Rest of the method...
_dm = 100; // Will be set
_angle = 0; // Will be set
_dummy1 = 0; // Will be set
_name = "Unittest"; // Here it crashes the whole app
_descr = "This is a test";
_param_d1 = 1;
_param_d2 = 2;
_param_d5 = 5;
_dummy2 = 0;
_dummy3 = "";
_epuzae = 99;
_param_i2 = 101;
...
Is there a method to test what struct constructor is called or what i am doing wrong here?
Best regards
Lord_Pinhead
After to much trouble and helpfull links why not use struct with strings, i refactored it yesterday to a class, what runs like a charme:
class DPic {
public:
DPic();
~DPic();
double DM;
double Angle;
std::string Name;
std::string Descr;
double Param_d1, Param_d2, Param_d5;
int Epuzae;
int Param_i2;
std::string Sob, Snr2, Param_s3, Param_s4;
void *_data;
};
So if anybody ever find this in his code, just throw it out and use proper classes or membervariables.
Related
I have to do a little c++ reflection in my way, by creating a pointer for each property of my class(I have create a tool to help me generate corresponding c++ code), but surprise, Building on x86 mode worked fine, but on x64 mode it's crashed, I have no idea why! here is my code.
Product.h File
class Product
{
public:
int ID;
std::string Designation;
};
class Property
{
public:
std::string Name;
int Shift;
};
class ProductSchema
{
private:
ProductSchema();
public:
static ProductSchema* Default();
ProductSchema(const ProductSchema& other) = delete;
Property ID;
Property Designation;
Property Prix;
};
Product.cpp File
ProductSchema::ProductSchema()
{
Product* p = new Product();
ID.Name = "ID";
ID.Shift = (int)(int*)&p->ID - (int)p;
Designation.Name = "Designation";
Designation.Shift = (int)(int*)&p->Designation - (int)p;
}
ProductSchema* ProductSchema::Default()
{
static ProductSchema* instance_;
if (instance_ == nullptr)
instance_ = new ProductSchema;
return instance_;
}
main.h file
int main()
{
for (int i = 0; i < 10000; i++)
{
Product* p = new Product();
int* pID = (int*)((unsigned long int)p + ProductSchema::Default()->ID.Shift);
*pID = i; // <--- error here
}
}
Your ProductSchema class, and your main(), are leaking the objects they new.
You don't need to create an object at runtime to calculate offsets to its members, you can use offsetof() at compile-time instead.
Don't use int or unsigned long to perform calculations on pointers. They are not guaranteed to be large enough. Use (u)intptr_t instead.
Your singleton is not initializing its instance_ pointer before using it. It does not need to use dynamic memory at all.
Try this instead:
class Product
{
public:
int ID;
std::string Designation;
};
struct Property
{
std::string Name;
int Shift;
};
class ProductSchema
{
private:
ProductSchema();
public:
static ProductSchema& Default();
ProductSchema(const ProductSchema& other) = delete;
Property ID;
Property Designation;
Property Prix;
};
ProductSchema::ProductSchema()
{
ID.Name = "ID";
ID.Shift = offsetof(Product, ID);
Designation.Name = "Designation";
Designation.Shift = offsetof(Product, Designation);
}
ProductSchema& ProductSchema::Default()
{
static ProductSchema instance_;
return instance_;
}
int main()
{
for (int i = 0; i < 10000; i++)
{
Product p;
int* pID = reinterpret_cast<int*>(reinterpret_cast<uintptr_t>(&p) + ProductSchema::Default().ID.Shift);
*pID = i;
}
}
Online Demo
I have an array in my MainProcessor
float waveforms[2][1080] = { {0}, {0} };
And I pass it to a SynthVoice like this:
osc1Voice->setWavetable(waveforms, 0); //[1]
osc2Voice->setWavetable(waveforms, 1);
There I read it like this in SynthVoice.h:
typedef float array_of_wavetable[1080];
void setWavetable(array_of_wavetable* waveform, int number)
{
wavetable = waveform;
id = number;
}
so i can use it like this in my SynthVoice class:
wavetable[id][first_sample + int(phase_0)]
Now I have moved [1] in a new class (OscilatorProcessor.h) and I want to set a pointer from MainProcessor -> OscillatorProcessor -> SynthVoice in a way that I can use it as wavetable[id][phase].
Now I don't know how to pass it from my MainProcessor to my OscillatorProcessor in the middle. So I can read it in the same way in the SynthVoice class.
I hope this made sense. Thank you for your time
edit: minimal reproducible example
#include <iostream>
typedef float array_of_wavetable[1080];
class SynthVoice
{
public:
void setWavetable(array_of_wavetable* waveform, int number)
{
wavetable = waveform;
id = number;
}
void outputWavetable()
{
for(int i = 0; i < 1080; i++)
{
std::cout << wavetable[id][i];
}
}
private:
array_of_wavetable * wavetable;
int id;
};
class OscillatorProcessor
{
public:
void setWavetable(array_of_wavetable * waveform, int number)
{
wavetable = waveform;
id = number;
}
void sendWaveToVoice()
{
SynthVoice voice;
voice.setWavetable(wavetable, id);
voice.outputWavetable();
}
private:
array_of_wavetable * wavetable;
int id;
};
int main() {
float waveform_templates[4][1080] = { {0}, {0}, {0}, {0} };
OscillatorProcessor oscillator;
oscillator.setWavetable(waveform_templates, 2);
return 0;
}
I'm trying to create a class for employees, and have a problem with its constructor.
My class looks like that (please note the name parameter which is char* type):
class Employee {
int id;
char * name ;
float salary;
int hours;
int extra;
public:
//constructor
Employee(int, char *, float, int, int);
//Getters and Setters:
void setId(int a) { id = a; }
int getId() { return id; }
void setName(char * c) { name = c; }
char * getName() { return name; }
void setSalary(float f) { salary = f; }
float getSalary() { return salary; }
void setHours(int h) { hours = h; }
int getHours() { return hours; }
void setExtra(int e) { extra = e; }
int getExtra() { return extra; }
};
I built a constructor and I want it to have default parameters, and I don't know how to deal with the name parameter to have a default of let's say "unknown".
This is the constructor:
Employee::Employee(int i = 123456789, char * na, float sal = 30, int ho = 45, int ex = 10)
{
id = i;
name = na;
salary = sal;
hours = ho;
extra = ex;
}
You can use a character array, and initialise the array to point to the first element of the array. You can store the array for example as a static member:
// in the class definition
inline static char default_name[] = "unknown";
// in argument list of the constructor
... char * na = default_name, ...
Although, you may want to consider whether it makes sense for name to be pointer to non-const. Perhaps a pointer to const would suffice. In such case, you could initialise it to point to the literal "unknown" directly.
A cleaner version
class Employee {
int id = 0;
char *name = nullptr;
float salary = 0.0;
int hours = 0;
int extra = 0;
And you don't need to have constructors, this depends on the case, but you get the idea that by initializing the variables on the definition you reduce the inconsistency of having multiples constructors for example
I am making a game that includes orcish enemies. I have one problem, how do initialize their HP, MP, Attack, defense, and speed without writing different code for each like this:
int orcishHP = 50;
int orcishMP = 5;
int orcishAttack = 15;
int orcishDef = 10;
int orcishSpeed = 20;
Isn't there some way to initialize all that when I refer to the orc, like this:
int orcishStats(){
int HP = 50
etc...
}
So instead of calling orcish MP HP and all that stuff, I have all of it in one one place.
If this made sense, please help. If this didn't make sense, don't help.
Here's the correct way to do this:
You define your attributes in a class/struct, and when that struct is initialized, the constructor(OrcishAttributes()) is called:
struct OrcishAttributes
{
int m_orcishHP;
int m_orcishMP;
int m_orcishAttack;
int m_orcishDef;
int m_orcishSpeed;
OrcishAttributes(int orcishHP, int orcishMP, int orcishAttack, int orcishDef, int orcishSpeed)
{
m_orcishHP=orcishHP;
m_orcishMP = orcishMP;
m_orcishAttack = orcishAttack
m_orcishDef = orcishDef;
m_orcishSpeed = orcishSpeed;
}
}
class Orc
{
public:
Orc(OrcishAttributes oa)
{
m_orcAttributes = oa;
}
private:
OrcishAttributes m_orcAttributes;
}
int main()
{
OrcishAttributes oa(50,5,15,10,20);
Orc* o = new Orc(oa);
}
That's why we have OOP.
You can define a base class, lets say Unit. It can store common members like fields or methods:
class Unit
{
protected:
int HP;
int MP;
int Attack;
int Def;
int Speed;
public:
int getHPplusMP()
{
return HP + MP;
}
};
Then, you can create inherited classes and initialize these values in its constructors:
class OrcUnit : public Unit
{
public:
OrcUnit()
{
HP = 20;
MP = 0;
Attack = 13;
Def = 4;
Speed = 5;
}
};
class ElfUnit : public Unit
{
public:
ElfUnit()
{
HP = 25;
MP = 15;
Attack = 15;
Def = 1;
Speed = 8;
}
};
Then, you will be able to work with it:
ElfUnit elf;
OrcUnit orc;
Unit u = elf;
cout << u.getHPplusMP();
Unit u = orc;
cout << u.getHPplusMP();
In general, it is definitely a good idea to learn OOP very well before trying to implement games.
I've a structure DutPlayerArrayElement defined in following lines:
namespace Common
{
namespace Constants {
const int MaxNumberOfIPAddresses = 10;
const int NumberOFRFOutputs = 100;
const int NumberOfPlayers = 100;
const int SignalFileNameSize = 30;
}
enum AntennaType
{
Omni = 0,
Directive,
Custom,
InvalidAntenna
};
enum ModulationID
{
CW = 0,
SSB,
LSB,
AM,
FM,
WFM,
DVBT
};
enum SigFileID
{
SIG_FILE_ID_ARB12 = 1,
SIG_FILE_ID_ARB16,
SIG_FILE_ID_WAV,
SIG_FILE_ID_TXT
};
typedef struct
{
//Basic
double dLatitude;
double dLongitude;
double dAltitude;
double dHeading;
float fNorthSudVelocity;
float fEastOvestVelocity;
float fVerticalVelocity;
unsigned int uiIsValid;
bool bIsDestroyed;
bool bTxIsOn;
ModulationID xModulationID;
SigFileID xSigFileType ;
char cSigFileName[128];
bool bLoopPlayback ;
char cAntennaTableFile[128];
bool bUseAntGainFactor;
double dAntGainFactor;
double dAntennaOrientation;
double dCarrierFrequency;
bool bTxIsLOS;
double dPwr;
double dAzimuth;
double dElevation;
double dDistance;
char cEntityName[128];
//char cModulation[2];
}PlayerArrayElement;
typedef struct
{
//Basic
double dLatitude;
double dLongitude;
double dAltitude;
double dHeading;
float fNorthSudVelocity;
float fEastOvestVelocity;
float fVerticalVelocity;
bool bIsDestroyed;
unsigned int uiNumAssignedRFOut;
bool bIsSync;
unsigned int uiNumRFOutXIP;
int iAssignedRFOut[Constants::NumberOFRFOutputs];
unsigned int uiRfGenCount;
int iIpAddress[Constants::MaxNumberOfIPAddresses];
unsigned int xPort[10];
double xCarrierFrequency[10];
//AntennaType xAntennatype;
char cAntennaTableFile[128];
bool bUseAntGainFactor;
double dAntGainFactor;
double dAntennaOrientation;
unsigned int uiNumOfPlayer;
PlayerArrayElement xScenarioPlayer[Constants::NumberOfPlayers];
char cEntityName[128];
unsigned int uiIsValid;
bool simIsRunning;
} DutPlayerArrayElement;
typedef std::vector<DutPlayerArrayElement> DutPlayers;
}
I also define a typedef std::vector<DutPlayerArrayElement> DutPlayers;
In a Visual studio 2008 library, I declare a class with this vector as member:
class COM_API MyClass
{
public:
SimComintManager();
~SimComintManager() ;
bool init();
void runme();
private:
void setup();
private:
// ....
Common::DutPlayers m_xDutPlayers;
// other structures...
};
in runme method:
void MyClass::runme()
{
while(m_bScenarioIsRunning)
{
if(m_uiIterationCount == 0)
{
m_pGen->setRfOutState(0, ON);
}
else
{
//aggiornare RF scenario in base a SHM attuale
m_xDutPlayers.clear() ;
m_xShmReader.getData(m_xDutPlayers) ;
}
}
}
ShmReader is a class defined in another library, that uses the same .h file in which vector is defined:
bool Reader::getData( Common::DutPlayers& xDutVector)
{
Common::DutPlayerArrayElement xEntityArrayElement;
for(int i = 0; i < m_iNumberOfEntities; i++)
{
xEntityArrayElement = m_pxPlayerShmVector->getValue(i);
if(xEntityArrayElement.uiIsValid == 1)
m_bSimulationState = xEntityArrayElement.simIsRunning;
xDutVector.push_back(xEntityArrayElement);
}
return true;
}
When I call xDutVector.push_back(xEntityArrayElement); I've an error and program crashes. Visual studio says Microsoft Visual Studio C Runtime Library has detected a fatal error in program.exe and when I click Break button the callstack is in row 161 of vector.h, the _SCL_SECURE_VALIDATE_RANGE row of this piece of code:
_Myt& operator+=(difference_type _Off)
{ // increment by integer
_SCL_SECURE_VALIDATE(this->_Has_container());
_SCL_SECURE_VALIDATE_RANGE(
_Myptr + _Off <= ((_Myvec *)(this->_Getmycont()))->_Mylast &&
_Myptr + _Off >= ((_Myvec *)(this->_Getmycont()))->_Myfirst);
_Myptr += _Off;
return (*this);
}
I've googled a bit and I've found this error regarding iterator erasing, but nothing regarding the push_back. What I'm doing wrong and how can I use push_back correctly?