memory overlapping in an initialization of a class - c++

My problem is I have a header file in which I store all my classes and in my cpp file I have my initializations of these classes, the initialization is not dynamic I have a number of arrays of different classes.
Now the problem is when I started expanding the classes in my header, adding more members and methods,the initialization of 1 specific class start throwing assertions at me of memory overlapping and suggested using memmove() instead of memcpy(), though I use neither of them in that class.
I tried replacing this class with a downgraded version of it that worked in older versions of my source but it still threw the same assertion at me I don't know what part of the code is relevant here is the assertion is being asserted in the initialization of the class without any pointer to what exactly is wrong.
this is my initialization of the class :
Shuriken(cpFloat m,cpVect veloc,cpFloat elast,cpFloat myu) : Spark() , Bang1() , ShurikenFlame()
{
smass = m;
sv = veloc;
se = elast;
su = myu;
ToDraw = false;
Removed = true;
AllocatedBombAnim = false;
DrawFlamedShuriken = false;
DeployFlameBang = false;
PassedLine = false;
hitfruit = false;
FruitIsBeingHit = false;
ToRemoveBody = false;
DummyAdded = false;
HitBossBanana = false;
fruitnum = 11;//11 means it has no fruit
Sec_FlameCounter = 3;
LitShuriken_UVs[0] = CIwFVec2(0, 0);
LitShuriken_UVs[2] = CIwFVec2(1.0/4, 1.0/4);
LitShuriken_UVs[3] = CIwFVec2(1.0/4, 0);
LitShuriken_UVs[1] = CIwFVec2(0, 1.0/4);
Sparkle_UVs[0] = CIwFVec2(0, 0);
Sparkle_UVs[2] = CIwFVec2(1.0/2, 1.0/4);
Sparkle_UVs[3] = CIwFVec2(1.0/2, 0);
Sparkle_UVs[1] = CIwFVec2(0, 1.0/4);
lastPos = cpvzero;
lastAngle = 0;
struct cpVect initShurikenBody_Verts[35] =
{
cpv(-128.01,41.26),
cpv(-58.74,45.42),
cpv(-47.79,32.04),
cpv(-40.06,33.94),
cpv(-20.63,48.29),
cpv(-16.13,55.67),
cpv(-25.33,69.7),
cpv(0,134.67),
cpv(25.34,70.16),
cpv(16.14,55.67),
cpv(20.75,48.1),
cpv(39.98,34.04),
cpv(47.96,32.15),
cpv(58.86,45.38),
cpv(128.01,41.26),
cpv(74.55,-2.82),
cpv(57.95,1.45),
cpv(52.25,-5.19),
cpv(45.16,-26.79),
cpv(45.77,-35.34),
cpv(61.86,-41.64),
cpv(79.1,-108.95),
cpv(20.79,-71.41),
cpv(19.62,-54.33),
cpv(11.91,-51.14),
cpv(-12.02,-51.11),
cpv(-19.64,-54.26),
cpv(-20.81,-71.4),
cpv(-79.11,-108.95),
cpv(-61.87,-41.6),
cpv(-45.77,-35.03),
cpv(-45.18,-26.75),
cpv(-52.23,-5.35),
cpv(-57.88,1.31),
cpv(-74.48,-2.8),
};
struct cpVect initShurikenShape_Verts1[5] =
{
cpv(-128.01,41.26),
cpv(-58.74,45.42),
cpv(-47.79,32.04),
cpv(-57.88,1.31),
cpv(-74.48,-2.8),
};
struct cpVect initShurikenShape_Verts2[5] =
{
cpv(0,134.67),
cpv(25.34,70.16),
cpv(16.14,55.67),
cpv(-16.13,55.67),
cpv(-25.33,69.7),
};
struct cpVect initShurikenShape_Verts3[5] =
{
cpv(47.96,32.15),
cpv(58.86,45.38),
cpv(128.01,41.26),
cpv(74.55,-2.82),
cpv(57.95,1.45),
};
struct cpVect initShurikenShape_Verts4[5] =
{
cpv(79.1,-108.95),
cpv(20.79,-71.41),
cpv(19.62,-54.33),
cpv(45.77,-35.34),
cpv(61.86,-41.64),
};
struct cpVect initShurikenShape_Verts5[5] =
{
cpv(-79.11,-108.95),
cpv(-61.87,-41.6),
cpv(-45.77,-35.03),
cpv(-19.64,-54.26),
cpv(-20.81,-71.4),
};
struct cpVect initShurikenShape_Verts6[4] =
{
cpv(-47.79,32.04),
cpv(-40.06,33.94),
cpv(-52.23,-5.35),
cpv(-57.88,1.31),
};
struct cpVect initShurikenShape_Verts7[4] =
{
cpv(-20.63,48.29),
cpv(-16.13,55.67),
cpv(16.14,55.67),
cpv(20.75,48.1),
};
struct cpVect initShurikenShape_Verts8[4] =
{
cpv(39.98,34.04),
cpv(47.96,32.15),
cpv(57.95,1.45),
cpv(52.25,-5.19),
};
struct cpVect initShurikenShape_Verts9[4] =
{
cpv(45.16,-26.79),
cpv(45.77,-35.34),
cpv(19.62,-54.33),
cpv(11.91,-51.14),
};
struct cpVect initShurikenShape_Verts10[4] =
{
cpv(-12.02,-51.11),
cpv(-19.64,-54.26),
cpv(-45.77,-35.03),
cpv(-45.18,-26.75),
};
struct cpVect initShurikenShape_Verts11[10] =
{
cpv(-40.06,33.94),
cpv(-20.63,48.29),
cpv(20.75,48.1),
cpv(39.98,34.04),
cpv(52.25,-5.19),
cpv(45.16,-26.79),
cpv(11.91,-51.14),
cpv(-12.02,-51.11),
cpv(-45.18,-26.75),
cpv(-52.23,-5.35),
};
for(int i=0;i<5;i++)
ShurikenShape_Verts1[i] = initShurikenShape_Verts1[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts2[i] = initShurikenShape_Verts2[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts3[i] = initShurikenShape_Verts3[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts4[i] = initShurikenShape_Verts4[i];
for(int i=0;i<5;i++)
ShurikenShape_Verts5[i] = initShurikenShape_Verts5[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts6[i] = initShurikenShape_Verts6[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts7[i] = initShurikenShape_Verts7[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts8[i] = initShurikenShape_Verts8[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts9[i] = initShurikenShape_Verts9[i];
for(int i=0;i<4;i++)
ShurikenShape_Verts10[i] = initShurikenShape_Verts10[i];
for(int i=0;i<10;i++)
ShurikenShape_Verts11[i] = initShurikenShape_Verts11[i];
for(int i=0;i<35;i++)
ShurikenBody_Verts[i] = initShurikenBody_Verts[i];
}
I am using Visual Studio 2010 with Marmalade SDK and I am writing in C++.
Thanks for any help,
Anton

Ok, so if we assume that ShurikenShape_Verts1 is either a regular C style array or a C++ style std::array and has the type cpVect, and cpVect is a POD struct:
for(int i=0;i<5;i++)
ShurikenShape_Verts1[i] = initShurikenShape_Verts1[i];
can be copied as:
memcpy(ShurikenShape_Verts1, initShurikenShape_Verts1,
sizeof(initShurikenShape_Verts1));
However, I have made some assumptions here, since you haven't posted enough code. I'd hate to start a "can post this, can you post that" type thread, asking for a large number of other bits of your code, but it also means that I may not have answered the question correctly, since I don't know for sure that your cpVect is indeed a POD struct, for example.

(I'd submit a comment but I don't have enough of a stackoverflow "reputation" to do so:-()
I would seriously stand back and look at why you are trying to copy this stuff to start with. Copying lots of stuff is comparatively slow. Far better to use a pointer to the existing array or a reference, which depends on your style.
If by "cpVect is just 2 floats made into a vector" you mean vector, then don't use memcpy or whatever. This is just going to give you heap issues later. Remember that these work by allocating behind the scenes. If you use memcpy you are going to get two objects pointing to the same content, and when the first goes out of scope that content will be freed.

Related

Creating Vulkan instance causes access violation

I am trying to initialize the Vulkan API.
The problem I am having is that I get an access violation error after I call vkCreateInstance and I think the problem comes from the extension and layer lists.
I am using a char buff[20][256] to transfer them from strings to the structure for the API call, and the layer and extension names I see in the debugger(3 extensions and 15 layers) are all a lot shorter than 256 characters and are all null terminated.
There is no buffer overflow with the extension or layer names, yet it crashes.
The layer and extension lists of strings I received trough using vkEnumerateInstanceExtensionProperties and vkEnumerateInstanceLayerProperties beforehand and are all valid null-terminated strings like "VK_KHR_surface", etc.
Is it possible that even tho it says I support some extensions, that I don't really support them and the API is crashing when it's trying to initialize an extension I don't support?
void InitializeInstance(void** instance, const vector<string>& layers, const vector<string>& extensions)
{
VkApplicationInfo applicationInfo;
VkInstanceCreateInfo instanceInfo;
VkInstance* instanceOut = (VkInstance*)instance;
applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
applicationInfo.pNext = nullptr;
applicationInfo.pApplicationName = "MyApp";
applicationInfo.pEngineName = "MyEngine";
applicationInfo.engineVersion = 1;
applicationInfo.apiVersion = VK_API_VERSION_1_0;
instanceInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceInfo.pNext = null;
instanceInfo.flags = 0;
instanceInfo.pApplicationInfo = &applicationInfo;
char buffLayer[20][256];
char buffExt[20][256];
if(!layers.empty())
{
instanceInfo.enabledLayerCount = layers.size();
for(int i = 0; i < layers.size(); i++)
{
strcpy(buffLayer[i], layers[i].c_str());
}
instanceInfo.ppEnabledLayerNames = (char**)buffLayer;
}
else
{
instanceInfo.enabledLayerCount = 0;
instanceInfo.ppEnabledLayerNames = nullptr;
}
if(!extensions.empty())
{
instanceInfo.enabledExtensionCount = extensions.size();
for(int i = 0; i < extensions.size(); i++)
{
strcpy(buffExt[i], extensions[i].c_str());
}
instanceInfo.ppEnabledExtensionNames = (char**)buffExt;
}
else
{
instanceInfo.enabledExtensionCount = 0;
instanceInfo.ppEnabledExtensionNames = nullptr;
}
vkCreateInstance(&instanceInfo, nullptr, instanceOut);
}
When I have only 0 extensions AND 0 layers, it creates successfully. If any of them is not 0, it crashes.
char buffLayer[20][256];
instanceInfo.ppEnabledLayerNames = (char**)buffLayer;
ppEnabledLayerNames is supposed to be an array of pointers to character arrays. But you're passing it a 2D array of characters, which is effectively just an array of 20*256 characters.
If you're on a machine with 32-bit pointers, the driver is going to take the first four bytes in buffLayer and treat them as a pointer to a character array. But you've just stored the first four characters of a layer name there, and 'VK_K' is probably not going to be a valid pointer value :). So the loader will crash when trying to dereference that invalid pointer.
Probably the simplest change would be to add:
char* layerNames[20];
for (int i = 0; i < 20; i++)
layerNames[i] = &buffLayer[i][0];
and pass layerNames as ppEnabledLayerNames.

Using enums and a for-loop to create instances of a class

enum { WOOD, BRICK, GRAIN, HEMP, WOOL, RAWMETAL, HONEY, SALT, METALGOODS, MEAD, CLOTH, BEER, STOCKFISH, CLOTHING, CHEESE, PITCH, PELTS, MEAT, WINE, SPICES, TOTALRESOURCES };
// An array of strings for each of the resource names
// As long as these are in the same order as the enum everything should match up
// .: resName[PIGIRON] is "Pig Iron"
string resName[]{ "Wood", "Brick", "Grain", "Hemp", "Wool", "Raw Metal", "Honey", "Salt", "Metal Goods", "Mead", "Cloth", "Beer", "Stockfish", "Clothing", "Cheese", "Pitch", "Pelts", "Meat", "Wine", "Spices" };
enum { Edinburgh, Scarborough, Boston, London, Bruges, Haarlem, Nimwegen, Groningen, Cologne, Minden, Bremen, Erfurt, Hamburg, Lubeck, Rostock, Berlin, Ripen, Flensburg, Aalborg, Naevsted, Bergen, Stavanger, Oslo, Stockholm, Gothenburg, Malmo, Ahus, Visby, Stettin, Posen, Breslau, Danzig, Thorn, Warsaw, Konigsberg, Kaunas, Riga, Reval, Helsinki, Novgorod, TOTALTOWNS};
string townName[]{ "Edinburgh", "Scarborough", "Boston", "London", "Bruges", "Haarlem", "Nimwegen", "Groningen", "Cologne", "Minden", "Bremen", "Erfurt", "Hamburg", "Lubeck", "Rostock", "Berlin", "Ripen", "Flensburg", "Aalborg", "Naevsted", "Bergen", "Stavanger", "Oslo", "Stockholm", "Gothenburg", "Malmo", "Ahus", "Visby", "Stettin", "Posen", "Breslau", "Danzig", "Thorn", "Warsaw", "Konigsberg", "Kaunas", "Riga", "Reval", "Helsinki", "Novgorod"};
class resource
{
public:
float demand, production, businessNeeds, businessProduction;
// This function, called a constructor, is run every time a new resource is created
// In this case, it assigns 0 to everything
resource()
{
demand = 0;
production = 0;
businessNeeds = 0;
businessProduction = 0;
}
float net()
{
return (this->production - this->demand);
}
float businessNet()
{
return (this->businessProduction - this->businessNeeds);
}
};
class town
{
public:
// The array of pointers to each of a our resource objects
resource *resList[TOTALRESOURCES];
// This is the town constructor
town()
{
// Loops through the array and creates a new resource object in each
// the resource constructor assigns the default values of 0.
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
resList[i] = new resource();
}
}
~town()
{
// Loops through the array and deletes each resource object
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
delete resList[i];
}
};
int main()
{
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town townName[i];
}
system("pause");
return 0;
}
So, I'm a software engineering student and I just switched majors so I decided to take some personal time to learn how to code in c++ a bit better. I decided to build a program that can plan the logistics for a videogame called Patrician IV.
I have put about 5 days worth of work into this project and have found some serious problems with my initial code (hard to add new functionality and change stuff around). So I took a step back and am trying to build my classes in a more succinct manner while also being able to loop through each instance of town later in a loop so I can update the demand, production, businessNeeds, and businessProduction values easily. I was copying and pasting about 6 lines of code 40 times before this.
I want to know:
(A) is it possible to do what I want - i.e. can I use enums and a for-loop to construct instances of town.
(B) how to loop through each of the towns so that I can add values to the resource variables.
(C) a third-grade-level explanation of how to use pointers for similar purposes would also be great.
:) THANK YOU!
In your main function, use the same idea as resList to initialize your town objects, so:
town* townName[TOTALTOWNS]
for (int i = 0; i < TOTALTOWNS; i++)
{
townName[i]= new town();
}
Then, I'm guessing you want to give different values for each of the different resources. Switch statements go along with enums well. So I would recommend something like this:
for (int i = 0; i < TOTALRESOURCES; i = i + 1)
{
switch(i)
{
case WOOD:
townName[EDINBURGH]->resList[WOOD]->demand= yourValue;
break;
case BRICK:
break;
}
}
Or if you're cycling through towns:
for (int i = 0; i < TOTALTOWNS; i = i + 1)
{
switch(i)
{
case EDINBURGH:
break; //etc.
}
}
If you only want to update a single town or resource, depending on how you're organizing everything, you could create something like this. A function that takes your town array and the enum indexes, like this:
updateTownResources(town* (*townName)[TOTALTOWNS], int townEnum, int resourceEnum, int dValue, int pValue )
{
townName[townEnum]->resList[resourceEnum]->demand= dValue;
townName[townEnum]->resList[resourceEnum]->production= pValue;
//etc...
}
int main()
{
std::vector<town*> townArray;
//What do I do here?
for (int i = 0; i < TOTALTOWNS; i++)
{
town* pTown = new(std::nothrow) town;
townArray.push_back (pTown);
}
std::vector<town*>::iterator iter = townArray.begin();
for (;iter != townArray.end(); iter++) {
(*iter); // gives access to individual objects
}
system("pause");
return 0;
}

C++ pointers and arrays

I have a problem with dynamic array.
In header file class i have this:
class CTerrain
{
...
CRock *rocks;
int numRocks;//=0
...
}
and in cpp i have this:
void CTerrain::Create()
{
numRocks = 0;
int NUM_ROCKS = rand()%10+1;
for(int i=0;i<NUM_ROCKS;i++)
{
rocks = new CRock;
numRocks++;
...
}
}
void CTerrain::Render()
{
for(int i=0;i<numRocks;i++)
rocks[i].render();//it works ok when here is 0 instead of 'i'
}
When I run this code I got error:
Unhandled exception at 0x00913aea in OpenGL.exe: 0xC0000005: Access violation reading location 0x1c00001f.
Thanks for any help, I have been trying to resolve this problem for like 4 hours...
EDIT:
Ok, so I changed Create() method to this:
void CTerrain::Create()
{
numRocks = 0;
int NUM_ROCKS = rand()%10+1;
rocks = new CRock[NUM_ROCKS];
for(int i=0;i<NUM_ROCKS;i++)
{
rocks[i].position = ...
numRocks++;
...
}
and also added delete [] rocks and now it's working.
Your Create function would be more like
void CTerrain::Create()
{
int NUM_ROCKS = rand()%10+1;
rocks = new CRock[NUM_ROCKS];
numRocks = NUM_ROCKS;
for(int i=0; i<NUM_ROCKS; i++)
{
rocks[i] = CRock{};
}
}
Just to add bit of explanation to above answer. Here:
for(int i=0;i<NUM_ROCKS;i++)
{
rocks = new CRock;
numRocks++;
...
}
What you do is, each time assign new instance of CRock to the pointer rock; thereby losing reference to the old object and creating memory leaks. Use a solution similar suggester by Cyber.
First off, rocks is pointer to CRocks. Your implemenation:
rocks[i].render() should be something like this:
rocks = new CRock [x]; (where x is the number of objects of type CRock.)
rocks[i] -> render().
delete rocks[i] // Just be sure to delete.
You may want to reference this for your solution on handling how a dynamic array of objects.
This other reference is good.
rocks = new CRock;
you overwrite CRock* pointer rocks in this line over and over again
Use this
rocks = new CRock[NUM_ROCKS];

How to train in Matlab a model, save it to disk, and load in C++ program?

I am using libsvm version 3.16. I have done some training in Matlab, and created a model. Now I would like to save this model to disk and load this model in my C++ program. So far I have found the following alternatives:
This answer explains how to save a model from C++, which is based on this website. Not exactly what I need, but could be adapted. (This requires development time).
I could find the best training parameters (kernel,C) in Matlab and re-train everything in C++. (Will require doing the training in C++ each time I change a parameter. It's not scalable).
Thus, both of these options are not satisfactory,
Does anyone have an idea?
My solution was to retrain in C++ because I couldn't find a nice way to directly save the model. Here's my code. You'll need to adapt it and clean it up a bit. The biggest change you'll have to make it not hard coding the svm_parameter values like I did. You'll also have to replace FilePath with std::string. I'm copying, pasting and making small edits here in SO so the formatting won't e perfect:
Used like this:
auto targetsPath = FilePath("targets.txt");
auto observationsPath = FilePath("observations.txt");
auto targetsMat = MatlabMatrixFileReader::Read(targetsPath, ',');
auto observationsMat = MatlabMatrixFileReader::Read(observationsPath, ',');
auto v = MiscVector::ConvertVecOfVecToVec(targetsMat);
auto model = SupportVectorRegressionModel{ observationsMat, v };
std::vector<double> observation{ { // 32 feature observation
0.883575729725847,0.919446119013878,0.95359403450317,
0.968233630936732,0.91891307107125,0.887897763183844,
0.937588566544751,0.920582702918882,0.888864454119387,
0.890066735260163,0.87911085669864,0.903745573664995,
0.861069296586979,0.838606194934074,0.856376230548304,
0.863011311537075,0.807688936997926,0.740434984165146,
0.738498042748759,0.736410940165691,0.697228384912424,
0.608527698289016,0.632994967880269,0.66935784966765,
0.647761430696238,0.745961037635717,0.560761134660957,
0.545498063585615,0.590854855113663,0.486827902942118,
0.187128866890822,- 0.0746523069562551
} };
double prediction = model.Predict(observation);
miscvector.h
static vector<double> ConvertVecOfVecToVec(const vector<vector<double>> &mat)
{
vector<double> targetsVec;
targetsVec.reserve(mat.size());
for (size_t i = 0; i < mat.size(); i++)
{
targetsVec.push_back(mat[i][0]);
}
return targetsVec;
}
libsvmtargetobjectconvertor.h
#pragma once
#include "machinelearning.h"
struct svm_node;
class LibSvmTargetObservationConvertor
{
public:
svm_node ** LibSvmTargetObservationConvertor::ConvertObservations(const vector<MlObservation> &observations, size_t numFeatures) const
{
svm_node **svmObservations = (svm_node **)malloc(sizeof(svm_node *) * observations.size());
for (size_t rowI = 0; rowI < observations.size(); rowI++)
{
svm_node *row = (svm_node *)malloc(sizeof(svm_node) * numFeatures);
for (size_t colI = 0; colI < numFeatures; colI++)
{
row[colI].index = colI;
row[colI].value = observations[rowI][colI];
}
row[numFeatures].index = -1; // apparently needed
svmObservations[rowI] = row;
}
return svmObservations;
}
svm_node* LibSvmTargetObservationConvertor::ConvertMatToSvmNode(const MlObservation &observation) const
{
size_t numFeatures = observation.size();
svm_node *obsNode = (svm_node *)malloc(sizeof(svm_node) * numFeatures);
for (size_t rowI = 0; rowI < numFeatures; rowI++)
{
obsNode[rowI].index = rowI;
obsNode[rowI].value = observation[rowI];
}
obsNode[numFeatures].index = -1; // apparently needed
return obsNode;
}
};
machinelearning.h
#pragma once
#include <vector>
using std::vector;
using MlObservation = vector<double>;
using MlTarget = double;
//machinelearningmodel.h
#pragma once
#include <vector>
#include "machinelearning.h"
class MachineLearningModel
{
public:
virtual ~MachineLearningModel() {}
virtual double Predict(const MlObservation &observation) const = 0;
};
matlabmatrixfilereader.h
#pragma once
#include <vector>
using std::vector;
class FilePath;
// Matrix created with command:
// dlmwrite('my_matrix.txt', somematrix, 'delimiter', ',', 'precision', 15);
// In these files, each row is a matrix row. Commas separate elements on a row.
// There is no space at the end of a row. There is a blank line at the bottom of the file.
// File format:
// 0.4,0.7,0.8
// 0.9,0.3,0.5
// etc.
static class MatlabMatrixFileReader
{
public:
static vector<vector<double>> Read(const FilePath &asciiFilePath, char delimiter)
{
vector<vector<double>> values;
vector<double> valueline;
std::ifstream fin(asciiFilePath.Path());
string item, line;
while (getline(fin, line))
{
std::istringstream in(line);
while (getline(in, item, delimiter))
{
valueline.push_back(atof(item.c_str()));
}
values.push_back(valueline);
valueline.clear();
}
fin.close();
return values;
}
};
supportvectorregressionmodel.h
#pragma once
#include <vector>
using std::vector;
#include "machinelearningmodel.h"
#include "svm.h" // libsvm
class FilePath;
class SupportVectorRegressionModel : public MachineLearningModel
{
public:
SupportVectorRegressionModel::~SupportVectorRegressionModel()
{
svm_free_model_content(model_);
svm_destroy_param(&param_);
svm_free_and_destroy_model(&model_);
}
SupportVectorRegressionModel::SupportVectorRegressionModel(const vector<MlObservation>& observations, const vector<MlTarget>& targets)
{
// assumes all observations have same number of features
size_t numFeatures = observations[0].size();
//setup targets
//auto v = ConvertVecOfVecToVec(targetsMat);
double *targetsPtr = const_cast<double *>(&targets[0]); // why aren't the targets const?
LibSvmTargetObservationConvertor conv;
svm_node **observationsPtr = conv.ConvertObservations(observations, numFeatures);
// setup observations
//svm_node **observations = BuildObservations(observationsMat, numFeatures);
// setup problem
svm_problem problem;
problem.l = targets.size();
problem.y = targetsPtr;
problem.x = observationsPtr;
// specific to out training sets
// TODO: This is hard coded.
// Bust out these values for use in constructor
param_.C = 0.4; // cost
param_.svm_type = 4; // SVR
param_.kernel_type = 2; // radial
param_.nu = 0.6; // SVR nu
// These values are the defaults used in the Matlab version
// as found in svm_model_matlab.c
param_.gamma = 1.0 / (double)numFeatures;
param_.coef0 = 0;
param_.cache_size = 100; // in MB
param_.shrinking = 1;
param_.probability = 0;
param_.degree = 3;
param_.eps = 1e-3;
param_.p = 0.1;
param_.shrinking = 1;
param_.probability = 0;
param_.nr_weight = 0;
param_.weight_label = NULL;
param_.weight = NULL;
// suppress command line output
svm_set_print_string_function([](auto c) {});
model_ = svm_train(&problem, &param_);
}
double SupportVectorRegressionModel::Predict(const vector<double>& observation) const
{
LibSvmTargetObservationConvertor conv;
svm_node *obsNode = conv.ConvertMatToSvmNode(observation);
double prediction = svm_predict(model_, obsNode);
return prediction;
}
SupportVectorRegressionModel::SupportVectorRegressionModel(const FilePath & modelFile)
{
model_ = svm_load_model(modelFile.Path().c_str());
}
private:
svm_model *model_;
svm_parameter param_;
};
Option 1 is actually pretty reasonable. If you save the model in libsvm's C format through matlab, then it is straightforward to work with the model in C/C++ using functions provided by libsvm. Trying to work with matlab-formatted data in C++ will probably be much more difficult.
The main function in "svm-predict.c" (located in the root directory of the libsvm package) probably has most of what you need:
if((model=svm_load_model(argv[i+1]))==0)
{
fprintf(stderr,"can't open model file %s\n",argv[i+1]);
exit(1);
}
To predict a label for example x using the model, you can run
int predict_label = svm_predict(model,x);
The trickiest part of this will be to transfer your data into the libsvm format (unless your data is in the libsvm text file format, in which case you can just use the predict function in "svm-predict.c").
A libsvm vector, x, is an array of struct svm_node that represents a sparse array of data. Each svm_node has an index and a value, and the vector must be terminated by an index that is set to -1. For instance, to encode the vector [0,1,0,5], you could do the following:
struct svm_node *x = (struct svm_node *) malloc(3*sizeof(struct svm_node));
x[0].index=2; //NOTE: libsvm indices start at 1
x[0].value=1.0;
x[1].index=4;
x[1].value=5.0;
x[2].index=-1;
For SVM types other than the classifier (C_SVC), look at the predict function in "svm-predict.c".

Strange errors: EXC_BAD_ACCESS in my class

Here is my code:
typedef struct TItemSelector{
ItemSelectFrame* pItems[2];
} SItemSelector;
class item {
public:
void expMethod();
SItemSelector itemSelector_;
UILayerButton* startBtn_;
};
void item::expMethod(){
startBtn_ = new UILayerButton();
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
startBtn_->callMethodA();
}
void UILayerButton::callMethodA()
{
this->callMethodB();
}
void UILayerButton::callMethodB()
{
}
On this->callMethodB();, a "EXC_BAD_ACCESS" occoured.
After that I found a work-around:
class item {
public:
void expMethod();
SItemSelector itemSelector_;
SItemSelector itemSelector2_; // work around
UILayerButton* startBtn_;
};
Then everything goes well... I just don't know what happened, but callMethodB() is just an empty method, there's nothing to do with it.
I'm using Apple LLVM 3.1, default setting.
UPDATE: Fixed my code.
In this code:
for (i = 0; i < 3; i++) {
itemSelector_.pItems[i] = new ItemSelectFrame();
}
you are writing over the end of itemSelector_.pItems because pItems is an array of length 2 but you are writing 3 elements.
That then overwrites startBtn_ which happens to appear immediately after itemSelector_ in memory. And that explains the error when you subsequently read the now corrupted startBtn_.
Either change your loop termination test, or increase the length of pItems. I can't tell which one is the correct solution, but clearly you will know.