I am new to c++.
It looks like member variable _scheduleSize gets value kind of "integer_half_max" without any reason. Could someone please explain me why is this happening?
Invocation
leds.addSchedulePoint(new ScheduledLedPoint(ScheduleTime(9), 0));
of method:
void ScheduledLeds::addSchedulePoint(ScheduledLedPoint *schedulePoint) {
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
_schedule[_scheduleSize++] = schedulePoint;
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
for (size_t i = 0; i < _scheduleSize; i++) {
Serial.println(_schedule[i]->getLevel());
}
}
results in such console output :
_scheduleSize:0
_scheduleSize:1073680860
0
Exception (28):
epc1=0x40206514 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000010 depc=0x00000000
Below you can see entire class:
class ScheduledLeds {
public:
ScheduledLeds(int pin);
void addSchedulePoint(ScheduledLedPoint *schedulePoint);
void process(ScheduleTime currentTime);
void freezeLedLevel(int targetLevel, int minutes);
int _pin;
private:
ScheduledLedPoint *_schedule[];
int _scheduleSize;
int _count;
int _size;
long _unfreezeTime;
int _lastLevel;
ScheduleTime _lastTime;
void setTransitionalLightLevel(ScheduleTime now, ScheduledLedPoint nextPoint);
void setLightLevel(int targetLevel);
};
ScheduledLeds::ScheduledLeds(int pin) {
pinMode(pin, OUTPUT);
_pin = pin;
_scheduleSize = 0;
_size = 10;
_unfreezeTime = millis();
ScheduledLedPoint *_schedule[_size];
}
void ScheduledLeds::addSchedulePoint(ScheduledLedPoint *schedulePoint) {
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
_schedule[_scheduleSize++] = schedulePoint;
Serial.print("_scheduleSize:");
Serial.println(_scheduleSize);
for (size_t i = 0; i < _scheduleSize; i++) {
Serial.println(_schedule[i]->getLevel());
}
}
ScheduledLedPoint *_schedule[]; is not valid C++ and shouldn't compile. Some compilers accept it as an extension - but even there, it's an array of zero size; _schedule[x] exhibits undefined behavior for any value of x.
When you write ScheduledLedPoint *_schedule[_size] in the constructor, that doesn't affect the data member named _schedule, as you seem to believe. Instead, it creates and immediately destroys a local variable that also happens to be named _schedule; this has exactly zero net effect.
For an array-like data structure of variable size, use std::vector.
because you have syntax error including this recursive function
Related
I need to modifiy an existing API and basically the only option I have is returning a pointer to a ragged array through a function argument (this would normally not be me personal preference). I can't get my head around doing this and keep getting a segmentation fault at this part of the code:
void getMxByArg(int ***pppX) {
*pppX = m_ppMx; // SEGMENTATION FAULT HERE
}
I've provided an example below which doesn't have any external dependencies and encapsulates the problem.
#include <stdint.h>
#include <iostream>
using namespace std;
class Mx {
public:
Mx() {
int *buff01 = (int*)malloc(3 * sizeof(int));
int *buff02 = (int*)malloc(3 * sizeof(int));
buff01[0] = 0;
buff01[1] = 1;
buff01[2] = 3;
buff02[0] = 4;
buff02[1] = 5;
buff02[2] = 6;
m_n = 2;
m_ppMx = (int**)malloc(m_n * sizeof(int*));
m_ppMx[0] = buff01;
m_ppMx[1] = buff02;
}
~Mx() {
for (int i=0; i<m_n; ++i) {
free(m_ppMx[i]);
}
free(m_ppMx);
}
int** getMx() {
return m_ppMx;
}
void getMxByArg(int ***pppX) {
*pppX = m_ppMx; // SEGMENTATION FAULT HERE
}
private:
int **m_ppMx;
int m_n;
};
int main()
{
Mx mx;
// SUCCESS
int **ppX = mx.getMx();
// FAILURE, Results in segmentation fault in getMxByArg
int ***pppX;
mx.getMxByArg(pppX);
return 0;
}
In the posted code, you are dereferencing an uninitialized pointer. That's cause for undefined behavior.
The solution is:
Create a variable of type int**.
Pass the address of that variable to the function.
int **ppX2;
mx.getMxByArg(&ppX2);
Another option is to change the argument type to int**&.
void getMxByArg(int**& ppX) {
ppX = m_ppMx;
}
Then, you can use:
int **ppX2;
mx.getMxByArg(ppX2);
Here is the class defination:
class Unit
{
public:
Unit();
~Unit();
void set_unit(int a);
void modify_flag(Unit&);
void modify_array(Unit array[], int len); // ?? The problem
int show_unit();
private:
int ai;
};
And the implementation of the member functions:
void Unit::set_unit(int a)
{
ai = a;
}
void Unit::modify_flag(Unit& u)
{
u.set_unit(20);
}
void Unit::modify_array(Unit array[], int len) // ?? The problem
{
for (int i = 0; i < len; ++i)
{
modify_flag(array[i]);
array[i].modify_array(array, len);
}
}
int Unit::show_unit()
{
return ai;
}
And finally the main code:
int main(int argc, char const *argv[])
{
int len = 10;
Unit* array = new Unit[len];
for (int i = 0; i < len; ++i)
{
array[i].set_unit(0);
}
array[5].modify_array(array,len); // ?? The problem
for (int i = 0; i < len; ++i)
{
cout << array[i].show_unit() << endl;
}
delete [] array;
return 0;
}
I passed an array of objects into the member function of the class as the parameter, but it aborted suddenly. I have checked my code many times to make sure the counter did not accumulate over the array length. Therefore, I think there must be something wrong with the object array as the parameter, but I could not figure it out. What happened with my code ??
You have uncontrolled recursion.
In modify_array the program will call
array[i].modify_array(array, len);
len times, each of which will call
array[i].modify_array(array, len);
len times, each of which will call
array[i].modify_array(array, len);
len times, each of which will call
array[i].modify_array(array, len);
len times...
You should be able to see where this is going.
Unfortunately, I'm not sure what your goal is so a can't suggest a proper solution, but You must have some exit condition to stop the chain of calls before you run out of automatic storage (most likely stack space).
For example you could
void Unit::modify_array(Unit array[], int len) // ?? The problem
{
for (int i = 0; i < len; ++i)
{
modify_flag(array[i]);
array[i].modify_array(array, len - 1); // note the -1
}
}
so that every iteration looks at less of the array. Eventually len will be 0 and i < 0 will result in no further calls. What good this does you, I can't say, but it stops the recursion.
Do you need the recursion at all? I don't know.
Define the contructor & destructor of Unit Class.
To create array of objects : Unit *array[len].
Now you need to instantiate the objects by using new operator.
Eg. array[1] = new Unit();
As you are using an object pointer you need to use arrow (->) operator to call functions instead of dot(.) operator.
Now when you call member functions from other member function of the same class you don't need to create and object to call that method.
One more point which was mentioned earlier by some other personnel modify_arraycalls itself and it is an infinite recursion.
Thanks user4581301 for help! I finally found the mistake I made.
The code I had written was to modify the whole array with a random starting index, so I tried to do it by resursive calls. I forgot to put the terminal condition, which must be the most important part, in my recursive function.
void Unit::modify_array(Unit array[], int len)
{
for (int i = 0; i < len; ++i)
{
if(need_to_modify(array[i]))
array[i].modify_array(array, len);
}
}
Something like this to jump out the loop. This was the my practice to get familiar with the recursive function. Thanks everyone.
I have a C++ Qt static library with two classes - dataprocthread and calcvalue. In the first one, when I call a method from an instance of calcvalue, pointer this (which references to dataprocthread class) suddenly becomes null.
This is dataprocthread.h:
class DataProcThread : public QThread
{
Q_OBJECT
public:
DataProcThread(int sarray[9], int val);
signals:
workDone(int result);
private:
int _sarray[9];
int _val;
void run();
};
dataprocthread.cpp:
DataProcThread::DataProcThread(int sarray[9], int val)
{
for (int x = 0; x < 9; x++)
{
_sarray[x] = sarray[x];
}
_val = val;
}
void DataProcThread::run()
{
CalcValue* cv = new CalcValue();
int myval = 0;
for (int i = 0; i < 100; i++)
{
myval = cv->processData(this->_val);
if (this->_sarray[0] != myval)
{
//do something
}
}
emit workDone(intValue);
}
calcvalue.h:
class CalcValue
{
public:
CalcValue();
int processData(int someval);
};
calcvalue.cpp:
CalcValue::CalcValue()
{
}
int processData(int someval)
{
//do something and return int value
}
When I run this code, it suddenly recieves signal "Segmentation fault". Using debugger, I found that the problem in DataProcThread::run() function: when I call cv->processData function, all works good. But on the next line (if (this->_sarray[0] != myval)), this pointer becomes null (I can see it in Locals window), therefore, I can't access this->_sarray variable.
In case it is important, that's how I start the thread (from another class outside my library):
DataProcThread* thread = new DataProcThread(sarray, val);
QObject::connect(thread, SIGNAL(workDone(int)), this, SLOT(collectWork(int)));
thread->start();
What I am doing wrong?
The problem, as was pointed out in comments, took place in processData function: it was writing over memory.
I simply used strncpy instead of strcpy and the problem gone (here is a good explanation about this).
I define arrays of integers in my code:
unsigned int tara[1024][3];
unsigned int data[1024][4];
I have storage structure, that allows me to pass them as void*:
struct storage {
unsigned int (*data)[4];
unsigned int (*tara)[3];
};
This is my use of structure above:
int main() {
unsigned int tara[1024][3];
unsigned int data[1024][4];
storage but_data;
but_data.data = data;
but_data.tara = tara;
tara_button.setCallback(taraButtonCallback, (void*)&but_data); //Some UI class
while(true); //The program
return 0;
}
In callback, this is how I try to access data:
bool taraButtonCallback(Opencv_Button* but, void* but_data)
{
storage* data_struct = (storage*)but_data;
int max = -5;
int max_value = 0;
cout<<data_struct->data[0][0]<<'\n'; //!!ERROR!!
return true;
}
This is runtime error I get:
Unhandled exception at 0x00394f1c in OpenCV.exe: 0xC0000005: Access violation reading location 0x00000005.
Edit:
The problem is not related to to where is the but_data defined! This callback works:
bool taraButtonCallback(Opencv_Button* but, void* but_data)
{
storage* data = (storage*)but_data;
set_tara(data->data, data->tara, *data->mat);
*(data->tara_set) = true;
return true;
}
void set_tara(unsigned int data[][4], unsigned int tara[][3], Mat &UI_bot)
{
UI_bot = Scalar(0, 0, 0);
for(int x=0; x<cam_frame_width; x++) {
tara[x][0]=data[x][0];
tara[x][1]=data[x][1];
tara[x][2]=data[x][2];
}
}
At the time the callback is called, but_data is already destroyed:
storage but_data;
It is allocated locally, which means that its lifetime is limited with the end of current function. After the function is completed, it ceases to exist, and the callback uses a dangling pointer.
Just assign it to a variable and print it
int taraButtonCallback(void* but_data)
{
struct storage* data = ( struct storage*)but_data;
int max = -5;
int max_value = 0;
int val = data->data[0][0];
cout <<val ; //!!works!!
return 0;
}
I think cout is unable to handle [][] in this case .. I am not sure why someone can enlighten both of us
You could try allocating the variable storage but_data like this:
storage *but_data = new storage;
effectively creating a variable with infinite lifetime.
Than you would define your callback function a bit differently (because you already have a pointer, so you do not need the address of the variable) - like this:
tara_button.setCallback(taraButtonCallback, (void*)but_data);
//note the lack of '&' sign before the but_data variable name
Just don't forget to delete it after you no longer need it!
delete but_data;
I have a double function
double Grid::getAverageNeighborhoodFitnessEvaluation(int agentPositionX, int agentPositionY)
{
GetNeighbourhood(agentPositionX, agentPositionY,neighborhoodEvaluations);
int neighborscount = 0;
double fitnesssum = 0;
double neighborfitness;
double value;
for (size_t i = 0; i < neighborhoodEvaluations.size(); ++i)
{
if ((*(neighborhoodEvaluations.at(i))) != NULL)
{
neighborfitness = (*(neighborhoodEvaluations.at(i)))->GetFitness();
if(neighborfitness<0)
neighborfitness=0;
fitnesssum+=neighborfitness;
neighborscount++;
}
}
value = fitnesssum/neighborscount;
return value;
}
GetNeighbourhood assigns an array of a defined type (Agent) to neighborhoodEvaluations
*(neighborhoodEvaluations.at(i)))->GetFitness(); returns a double that represents a value for that point in the array. These have all been used previously with no issues.
When called from my main (where RealX and RealY are two integers)
int currentFitness = getAverageNeighborhoodFitnessEvaluation(RealX,RealY);
always works
double currentFitness = getAverageNeighborhoodFitnessEvaluation(RealX,RealY);
causes Segmentation fault
Does anyone know what possibilities could result in this and/or what value an int can take but a double can't seem to?
So far i have traced the error to our Agent implementation
Agent.cpp
#include "Agent.h"
Agent::Agent(void)
{
m_age = 0;
m_fitness = -1;
}
Agent::~Agent(void)
{
}
int Agent::GetAge()
{
return m_age;
}
double Agent::GetFitness()
{
return m_fitness;
}
void Agent::IncreaseAge()
{
m_age++;
}
AgentType Agent::GetType()
{
return m_type;
}
Agent.h
#ifndef AGENT_H
#define AGENT_H
enum AgentType { candidateSolution, cupid, reaper, breeder};
class Agent
{
public:
Agent(void);
virtual ~Agent(void);
double GetFitness();
int GetAge();
void IncreaseAge();
AgentType GetType();
virtual void RandomizeGenome() = 0;
protected:
double m_fitness;
AgentType m_type;
private:
int m_age;
};
#endif // !AGENT_H
Can't seem to locate the exact problem though
From your comment on the gdb debugger answer, I see that you are calling the GetFitness method on a null object (Agent::GetFitness (this=0x0)). This means that neighborhoodEvaluations.at(i) is returning a null-pointer. at() only checks for out of bounds, but if what was put into the array to begin with is a null pointer, at() won't help you. To guard agains this, you should change
if ((*(neighborhoodEvaluations.at(i))) != NULL)
into
if (neighborhoodEvaluations.at(i) != NULL)
If neighborhoodEvaluations is not supposed to contain null pointers, you will have to track down why getNeighborhood() is putting them there. Perhaps you are looking for out-of-bound neighbors for the elements at the edge of your set of points?
Quickly get started on gdb debugger using this article http://www.cs.cmu.edu/~gilpin/tutorial/ . Then tell us which line produces the segmentation fault .