This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 5 years ago.
This code is meant to help in profiling game code - and I can't seem to get my head around why it isn't working. I'm getting the following error message: undefined reference to `ProfileSample::profileSamples', and another for each of the points at which I've used its members.
#ifndef PROFILER_HPP_
#define PROFILER_HPP_
#define MAXIMUM_PROFILE_SAMPLES 16
class ProfileSample {
private:
int sampleIndex, parentIndex;
static int previousSampleIndex;
inline float getTime(void) {
return ((float)SDL_GetTicks()) / 1000.0f;
}
static struct profileSamples {
float start, duration;
char *name;
} profileSamples[MAXIMUM_PROFILE_SAMPLES];
public:
ProfileSample(const char *name) {
sampleIndex = 0;
while(profileSamples[sampleIndex].name != NULL)
sampleIndex ++;
parentIndex = (sampleIndex > 1) ? previousSampleIndex : -1;
previousSampleIndex = sampleIndex;
profileSamples[sampleIndex].name = (char *)name;
profileSamples[sampleIndex].start = getTime();
}
~ProfileSample(void) {
float end = getTime();
profileSamples[sampleIndex].duration = (end - profileSamples[sampleIndex].start);
if(parentIndex >= 0)
profileSamples[parentIndex].start -= profileSamples[sampleIndex].duration;
if(sampleIndex == 0)
output();
}
static void output(void) {
for(int i = 1; i < MAXIMUM_PROFILE_SAMPLES; i ++) {
printf("\nName: %s"
"\nDuration: %f"
"\nOverall percentage: %f",
profileSamples[i].name,
profileSamples[i].duration,
(profileSamples[0].duration / 100) * profileSamples[i].duration);
}
}
};
#endif /* PROFILER_HPP_ */
Can anybody explain what I'm missing here? Go easy, I've only just left C for C++
static struct profileSamples {
float start, duration;
char *name;
} profileSamples[MAXIMUM_PROFILE_SAMPLES];
You have just declared this static structure.
You haven't actually initialised it.
If you add
struct ProfileSample::profileSamples ProfileSample::profileSamples[16] = {};
int ProfileSample::previousSampleIndex = 1;
After the class declaration it will actually fix the issue.
You can think about it as a 2nd step, which is filling the memory with actual data. The first is just describing that some memory will be used and what interpretation data will have.
Hope that this, combined with issue marked in comments will help you understand what is going on.
Related
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 months ago.
I am facing the error as in below,
Undefined first referenced
symbol in file
void bcMwMrsh::cppListFromWire<CSSCODERec*>(void*&, RWTValSlist<CSSCODERec*, std::allocator<CSSCODERec*> >&, AISObject* (*)()) /app/sdasup/home/mhp/source/develop/sd/lib/libsdHostSupport.so
ld: fatal: symbol referencing error
Under bc/include/bcMwMrsh.h cppListFromWire defined as below, Please note I have declared and defined the cppListFromWire in .h
typedef AbcObject *(*factory)()
namespace bcMwMrsh
{
template<typename listT>
void cppListFromWire(void *&src,RWTValSlist<listT> &dest, factory);
}
template<typename listT>
void bcMwMrsh::cppListFromWire(void *&src, RWTValSlist<listT> &list, factory factoryFunc)
{LOG (LM_MARSHAL_COM, (" bcMwMrsh::cppAbcListFromWire()...\n"));
int nItems = 0;
ptrdiff_t* pstart = (ptrdiff_t*) src;
bcMwMrsh::cppIntFromWire(src, &nItems);
for (int i = 0; i < nItems; i++)
{
AbcObject *elem = factoryFunc();
assert (elem); // improper assert; should cause exception - KD
elem->fromWire(src);
list.append(elem);
}
LOG (LM_MARSHAL_COM, (" bcMwMrsh::cppAbcListFromWire(): length %i\n", ptrdiff_t((ptrdiff_t*)src - pstart)));
}
and under "wv/include/cppmarsh.h" cppListFromWire been defined as in below,
typedef AISObject *(*factorywv)();
namespace bcMwMrsh
{
template<typename listT>
void cppListFromWire(void *&src,RWTValSlist<listT> &dest, factorywv);
}
template<typename listT>
void cppListFromWire(void *&src,RWTValSlist<listT> &list, factorywv factoryFunc)
{
LOG (LM_MARSHAL_COM, (" cppmarsh::cppListFromWire()...\n"));
ptrdiff_t* pstart = (ptrdiff_t*) src;
short nItems=0;
bcMwMrsh::cppShortFromWire(src, &nItems);
for (int i=0; i < nItems; i++)
{
AISObject *elem = factoryFunc();
assert(elem); // improper assert; should cause exception - KD
elem->fromWire(src, 0);
list.append(elem);
}
LOG (LM_MARSHAL_COM, (" cppmarsh::cppListFromWire(): length %i\n",
ptrdiff_t((ptrdiff_t*)src - pstart)));
}
And the .so (/app/sdasup/home/mhp/source/develop/sd/lib/libsdHostSupport.so) path where the error is pointing out has cppListFromWire used at two files as in below,
under sd/sdHostSupport/csscode.cpp
#include "csscode.h"
#include "cppmarsh.h"
int CSSCODERecList::fromWire(void *&buf, long bufLen)
{
bcMwMrsh::cppListFromWire(buf, contents, CSSCODERec::AISFactory);
return 0;
}
and under sd/sdHostSupport/__cppmarsh.cpp
#include "cppmarsh.h"
void cppIntFromWire(void *&src, int *dest)
{
assert(sizeof(int)==4);
*dest=0;
#ifndef LITTLE_ENDIAN //NT Port
*((char*)dest+3)=*((char*)src);
*((char*)dest+2)=*((char*)src+1);
#else
*((char*)dest)=*((char*)src);
*((char*)dest+1)=*((char*)src+1);
#endif
(char*&)src+=2;
}
template<typename listT>
void cppListFromWire(void *&src,RWTValSlist<listT> &list, factorywv factoryFunc)
{
int nItems = 0;
cppIntFromWire(src, &nItems);
for (int i = 0; i < nItems; i++)
{
AISObject *elem = factoryFunc();
assert(elem); // improper assert; should cause exception - KD
elem->fromWire(src, 0);
list.append(elem);
}
}
Is this something related to function-overloading, as I can see cppListFromWire defined has one parameter with different return type? However I see that is falling under overloading rules. Anything that differs here please let me know.
I tried including signature in both the files didn't work. Also tried including absolute header paths didn't work. One thing that worked was when I commented out below line form the file sd/sdHostSupport/csscode.cpp but that vague thing one can do.
bcMwMrsh::cppListFromWire(buf, contents, CSSCODERec::AISFactory);
I am unable to figure out what's the problem and how to resolve that. Been stuck for about 2 weeks now. Any kind of help/suggestions/inputs are greatly appreciated.
I am working on some arduino code and my program keeps on giving me this error,
ISO C++ forbids comparison between pointer and integer [-fpermissive]
I've tried searching on the internet to solve this issue but, either the solution is incorrect, or irrelevant. here is where the arduino software is saying the problem is,
if((millis - incLastDebounce) > debounceDelay) {
and if you need the rest of the code here it is,
#include <LiquidCrystal.h>
int freq = 0;
int change = 0;
const int incPin = 3;
const int setPin = 2;
int incButtonState;
int setButtonState;
int incPreviousState;
int setPreviousState;
int incLastDebounce;
int setLastDebounce;
const int debounceDelay = 50;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
// put your setup code here, to run once:
lcd.begin(16, 2);
pinMode(setPin, INPUT);
pinMode(incPin, INPUT);
lcd.print("Frequency: " + freq);
}
void loop() {
// put your main code here, to run repeatedly:
int incReading = digitalRead(incPin);
int setReading = digitalRead(setPin);
if(setReading != setPreviousState) {
setLastDebounce = millis();
}
if(incReading != incPreviousState) {
incLastDebounce = millis();
}
if((millis - setLastDebounce) > debounceDelay) {
if(setReading != setButtonState) {
setButtonState = setReading;
}
if(setButtonState == HIGH) {
//Okay so here you will do your set lcd voodoo
}
}
if((millis - incLastDebounce) > debounceDelay) {
if(incReading != buttonState) {
incButtonState = incReading;
}
if(buttonState == HIGH) {
// here you can put the lcd code
change = change + 500;
if(change == 10500){
change = 0;
}
}
}
incPreviousState = incReading;
setPreviousState = setReading;
}
hopefully you can find the problem and help.
Looks like you're missing parentheses after millis, so instead of calling the function, you're trying to do arithmetic with its memory address.
This will probably work better:
if ((millis() - incLastDebounce) > debounceDelay) {
This question already has answers here:
Concatenating Variable Names in C?
(5 answers)
Closed 8 years ago.
i create a structure in c like this
struct book {
char name;
int page;
} b2,b3,b4;
how can i print these using a for loop.
i mean
for(int i=2 ; i<5 ; ++i)
printf("%c %d", b{i}.name , b{i}.page); //bi.name will not work obviously
is there some kind of special operation that need to do this ?
and i sincerely apologize if it has been answered somewhere else on the site already. i don't know myself what i'm supposed to search for precisely.
I have a solution :
Store structure into an Array of pointer and loop through it
struct book **arr = malloc(sizeof(struct book *) * 4);
arr[0] = &b2;
arr[1] = &b3;
arr[2] = &b4;
arr[3] = NULL;
for (int i=0; i < 3; ++i)
{
printf("%c %d", arr[i]->name , arr[i]->page);
}
EDIT:
Or like other community gyus said, create at begining an array of structure (easier to manipulate)
Example :
struct book books[3];
Or
struct book *books = malloc(sizeof(struct book) * 3);
You could use arrays and macros:
struct book {
char name;
int page;
};
#ifndef __cplusplus
struct
#endif
book library[3];
#define b2 (library[0])
#define b3 (library[1])
#define b4 (library[2])
void initialize(void)
{
b2.name = 'a';
b2.page = 5;
b3.name = 'F';
b3.page = -85;
b4.name = '$';
b4.page = 65535;
}
void Print_Library(void)
{
unsigned int i = 0;
for (i = 0; i < 3; ++i)
{
printf("First character of book %d: %c\n", i, library[i].name);
printf("Page of book %d: %d\n", i, library.page);
printf("\n");
}
}
The name field is a single character not a string.
Note: I used the #if preprocessor directive because instances of structures are defined differently between C and C++ and you specified both.
Edit 1: Accessing variables by name during run-time.
Although I have never needed to access variables by name during run-time, one method is to map variables to their names.
struct book; // forward declaration, see above.
struct Variable_Name_Entry
{
#ifdef __cplusplus // Required since you tagged both languages
std::string name;
book * p_variable;
#else
char name[16];
struct book * p_variable;
#endif
};
#ifndef __cplusplus
struct
#endif
Variable_Name_Entry variable_names[] =
{
{"b2", &b2},
{"b3", &b3},
{"b4", &b4},
};
const unsigned int number_of_variable_names =
sizeof(variable_names) / sizeof(variable_names[0]);
#ifndef __cplusplus
struct
#endif
book * name_to_variable(const char * p_name)
{
unsigned int i = 0;
for (i = 0; i < number_of_variable_names; ++i)
{
#ifdef __cplusplus
if (variable_names[i].name == p_name)
#else
if (strcmp(variable_names[i].name, p_name) == 0)
#endif
{
return variable_names[i].p_variable;
}
}
return NULL;
}
Do you really need to access variable by names or is there a different design available?
You can collect pointers to the variables in an array, e.g. like this in C++11:
for( auto p : {&b2, &b3, &b4} )
{
cout << p->name << " " << p->page << endl;
}
I leave it to you to create similar C language solution, if you want that (the question was/is tagged both C++ and C).
In C the array has to be created more manually, so to speak.
I'm trying to code a robot, and I'm having a confusing situation. I need to pass an array of pointers to objects to a constructor of a class. I can't, however, populate the array before I pass it into the constructor. To solve this I want to pass a pointer to said array, and access its elements from the pointer. The problem is that I'm new to C++, and so I'm not sure of the syntax. Could you guys help me out?
Code for the main file
class RobotDemo : public SimpleRobot
{
Joystick stick;
JoystickOne joyOne;
Victor *victors [8];
public:
RobotDemo(void):
stick(1),
joyOne(&stick)// these must be initialized in the same order
// as they are declared above.
/*It doesnt seem like I can do anything but initialize things here*/
{
/*Populate array with pointers to victors. Will need to update channels*/
for (int x = 1; x <= 7; x++) {
victors[x] = new Victor(x);
}
/*And I don't think I can initialize anything here*/
myRobot.SetExpiration(0.1);
}
/**
* Drive left & right motors for 2 seconds then stop
*/
void Autonomous(void)
{
}
/**
* Runs the motors with arcade steering.
*/
void OperatorControl(void)
{
myRobot.SetSafetyEnabled(true);
while (IsOperatorControl())
{
joyOne.testForActions(); /*Check joystick one for actions*/
Wait(0.005); // wait for a motor update time
}
}
/**
* Runs during test mode
*/
void Test() {
}
};
START_ROBOT_CLASS(RobotDemo);
Here's the code for the JoystickInput class, which the JoystickOne class extends
//the .h
#ifndef JOYSTICKINPUT_H
#define JOYSTICKINPUT_H
#include "WPILib.h"
class JoystickInput {
public:
JoystickInput(Joystick*);
JoystickInput(Joystick*, Victor* [8]);
Joystick * joystick;
bool buttons [10];
Victor** victors [8];
bool buttonClicked(int id);
virtual void testForActions();
};
#endif
//and the .cpp
#include "JoystickInput.h"
JoystickInput::JoystickInput(Joystick * joy) {
joystick = joy;
for (int x = 0; x < 10; x++) {
buttons[x] = false;
}
}
JoystickInput::JoystickInput(Joystick * joy, Victor* vicArray [8]) {
joystick = joy;
for (int x = 0; x < 10; x++) {
buttons[x] = false;
}
for (int n = 0; n <=7; n++) {
*victors[n] = vicArray[n];
}
}
bool JoystickInput::buttonClicked(int id) {
if (buttons[id] == false and joystick->GetRawButton(id) == true) {
buttons[id] = true;
return true;
} else if (buttons[id] == true and joystick->GetRawButton(id) == false) {
buttons[id] = false;
return false;
} else {
return false;
}
}
void JoystickInput::testForActions() {
}
What I'm asking you guys to help me do is rework the constructor of JoystickInput() so that it also takes a pointer to an array of pointers (to Victors), and performs methods on elements of the array. Googling it hasnt turned up anything useful. I'd research it more myself, but its been a few days and I'm still hung up on this.
Thanks for the help (and if not that, then at least reading my post)!
You should be able to use:
JoystickInput(Joystick*, Victor**, int);
and just pass vicArray into the constructor. If victors can be anything else than an array of length 8, then you should also pass the length as an argument because c++ cannot find the length of an array from a pointer.
Whenever types get complicated (functions or arrays), use a typedef:
typedef char char_buffer_type[8]; //char_buffer_type is an array
typedef char (*char_buffer_ptr)[8]; //char_buffer_ptr is a pointer to an array
typedef char (&char_buffer_ref)[8]; //char_buffer_ref is a reference to an array
typedef int main_type(int, char**); //main_type is a "int(int, char**)" function
typedef Victor*(array_of_ptr)[8]; //array_of_ptr is an array of 8 Victor*
Also, you should name the values 8 and 10.
class JoystickInput {
public:
static const int victor_count = 8;
static const int button_count = 10;
typedef Victor*(array_of_victor_ptr)[victor_count];
JoystickInput(Joystick*){}
JoystickInput(Joystick*, array_of_victor_ptr& vicArray);
bool buttonClicked(int id){return true;}
virtual void testForActions(){}
Joystick * joystick;
bool buttons [button_count];
array_of_victor_ptr victors; //that's simpler
};
//then pass this one by reference
JoystickInput::JoystickInput(Joystick * joy, array_of_victor_ptr& vicArray) {
joystick = joy;
for (int x = 0; x < button_count; x++) {
buttons[x] = false;
}
for (int n = 0; n < victor_count; n++) {
victors[n] = vicArray[n]; //don't have to dereference here anymore
}
}
Proof of compilation. Typedefs are wonderful. Use them.
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 .