I am having an issue with segmentation faults when trying to access a class member, which is a structure, from within a class function. I assume I am declaring this wrong somewhere, but I can't see what the problem is. I have tried many variations with no luck so far. Any help would be greatly appreciated.
program.h:
struct ButtonState {
int analog_pin;
};
class LEDGarden {
public:
ButtonState *the_state;
LEDGarden(void) {}
void init(void);
void initButtons(void);
};
program.cpp:
#include "program.h"
void LEDGarden::init(void) {
ButtonState *the_state = new ButtonState();
the_state->analog_pin = 5;
initButtons();
}
void LEDGarden::initButtons(void) {
// The problem happens here.
the_state->analog_pin = 5;
}
int main() {
LEDGarden garden;
garden.init();
}
The segmentation fault happens when I try to make an assignment in the structure in the function initButtons. I am at quite a loss as to what the problem is.
Note that this program works fine for me when using gcc so long as I don't use the -O2 flag. Using clang I get the segfault regardless of the compilation flags.
Your LEDGarden has a pointer to a ButtonState which you never set.
The init method shadows the member variable with a local of the same name (so the member variable is not set when you go to use it). try
void LEDGarden::init(void) {
this->the_state = new ButtonState();
the_state->analog_pin = 5;
initButtons();
}
What you should probably do is get rid of init() and make it a constructor.
The different behaviors probably depends on what the member variable is set to null or random memory location (which may be "good" or "bad", but never "right" ;-)
Related
I am not sure why my function is not working. It should be printing out something out (an error message after the user goes out of bounds)I have set the array index at 3 index slots. I'm also getting an error "unused variable 'yourArray' I am not sure where to go from here. Still trying to learn c++ so and advice or help will be greatly appreciated.
#include <iostream>
using namespace std;
class safeArray{
public:
void outofBounds(int,int);
int yourArray[3];
int i;
};
void outofBounds(int,int);
int yourArray[3];
int i;
void outofBounds(int yourArray[],int sizeofArray) {
for (i=0;i<sizeofArray;i++){
cout<<"Please enter integer";
cin >>yourArray[i];
yourArray[i]++;
for (i=0;i>sizeofArray;){
cout<<"safeArray yourArray (" <<yourArray[0]<<","<<yourArray[3]<<")"
<<endl;
}}}
int main() {
void outofBounds(int,int);
int yourArray[3]; //Error: Used variable "yourArray"
};
Your Program is running fine. Unless you added the "-Werror" flag to the compiler, which would treat the "unused variable"-Warning as an Error.
The code compiles fine as seen on here: http://coliru.stacked-crooked.com/a/d648b94f205b51dc
Though your Program does not do what you want it to do, because of the following reasons:
1.) You have 3 redefinitions of outofBounds inside different namespaces:
one inside the classes namespace SafeArray which is a member function
of it
then inside the global space
and then inside the main-function (the entry point)
But the one being actually defined is the one in the global space (2nd one)
2.) You are not passing anything to the function inside main.
define your Array there first then call the function by doing:
int yourArray[3];
outofBounds(yourArray, 3);
3.) You probably wanted to define the member method "outofBounds" inside SafeArray-class. This can be done by writing the scope operator:: which specifies the class to which the member function belongs to:
class SafeArray { // is a class, can also be struct since everything is public anyways
public:
void outofBounds(int,int); // a member of the class SafeArray
// private:
int yourArray[3];
int i;
};
void SafeArray::outofBounds(int yourArray[],int sizeofArray) {
// do something...
}
but then again you need some constructor that initializes the members of your class. Some work needs to be done to make it work, like you want. Good Luck :)
What are good practice options for passing around objects in a program, avoiding accessing non initialized member variables.
I wrote a small example which I think explains the problem very well.
#include <vector>
using namespace std;
class container{public:container(){}
vector<int> LongList;
bool otherInfo;
};
class Ship
{
public:Ship(){}
container* pContainer;
};
int main()
{
//Create contianer on ship1
Ship ship1;
ship1.pContainer = new container;
ship1.pContainer->LongList.push_back(33);
ship1.pContainer->otherInfo = true;
Ship ship2;
//Transfer container from ship1 onto ship2
ship2.pContainer = ship1.pContainer;
ship1.pContainer = 0;
//2000 lines of code further...
//embedded in 100 if statements....
bool info = ship1.pContainer->otherInfo;
//and the program crashes
return 0;
}
The compiler cannot determine if you are introducing undefined behavior like shown in your example. So there's no way to determine if the pointer variable was initialized or not, other than initializing it with a "special value".
What are good practice options for passing around objects in a program, avoiding accessing non initialized member variables.
The best practice is always to initialize the pointer, and check before dereferencing it:
class Ship {
public:
Ship() : pContainer(nullptr) {}
// ^^^^^^^^^^^^^^^^^^^^^
container* pContainer;
};
// ...
if(ship1.pContainer->LongList) {
ship1.pContainer->LongList.push_back(33);
}
As for your comment:
So there are no compiler flags that could warn me?
There are more simple and obvious cases, where the compiler may leave you with a warning:
int i;
std::cout << i << std::endl;
Spits out
main.cpp: In functin 'int main()':
main.cpp:5:18: warning: 'i' is used uninitialized in this function [-Wuninitialized]
std::cout << i << std::endl;
^
See Live Demo
One good practice to enforce the checks is to use std::optional or boost::optional.
class Ship
{
public:
Ship() : pContainer(nullptr) {}
std::optional<container*> Container()
{
if(!pContainer)
return {};
return pContainer;
}
private:
container* pContainer;
};
It will force you (or better: provide a firm reminder) to check the result of your getter:
std::optional<container*> container = ship1.Container();
container->otherInfo; // will not compile
if(container)
(*container)->otherInfo; // will compile
You would always need to check the result of operation if you use pointers. What I mean is that with optional the situation is more explicit and there's less probability that you as the programmer will forget to check the result.
It seems that you are looking for a way to make your code
bool info = ship1.pContainer->otherInfo;
work even though the pContainer may be null.
You can use a sentinel object, which holds some default data:
container default_container;
default_container.otherInfo = false; // or whatever the default is
Then use a pointer to the sentinel object instead of a null pointer:
//Transfer container from ship1 onto ship2
ship2.pContainer = ship1.pContainer;
ship1.pContainer = &default_container; // instead of 0
//2000 lines of code further...
//embedded in 100 if statements....
bool info = ship1.pContainer->otherInfo;
If you use this, you should make sure the sentinel object cannot be destroyed (e.g. make it a static member, or a singleton).
Also, in the constructor, initialize your pointers so they point to the sentinel object:
class Ship
{
public: Ship(): pContainer(&default_container) {}
...
};
I found an additional solution. It is admittedly not preventing the access of uninitialized objects, but at least the program crashes AND returns an error message, that enables us to correct our mistake. (This solution is particularly for the g++ compiler.)
First of all set the compiler flag _GLIBCXX_DEBUG. Then instead of naked pointer use unique_ptr.
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class container{
public:container(){}
int otherInfo = 33;
};
class Ship
{
public:Ship(){}
std::unique_ptr<container> upContainer;
};
int main()
{
Ship ship1;
cout<<ship1.upContainer->otherInfo<<endl;
return 0;
}
This code will produce an error:
std::unique_ptr<_Tp, _Dp>::pointer = container*]: Assertion 'get() != pointer()' failed.
Hence telling us that we should probably include an if(ship1.upContainer) check.
What are good practice options for passing around objects in a program, avoiding accessing non initialized member variables.
Good practice would be to initialize everything in the constructor.
Debatable better practice is to initialize everything in the constructor and provide no way of modifying any members.
I am trying to work with pointers - you know experiment.
My code will work fine if I remove the pointer for name and the dereferences for
this->name. But I wouldn't really be learning anything.
// Example program
#include <iostream>
#include <string>
using namespace std;
string dogsbreed[3];
struct dog
{
string *name;
string breed;
int age;
void set_dogs_breed()
{
dogsbreed[0] = "Collie";
dogsbreed[1] = "Poodle";
dogsbreed[2] = "Pit Ball";
}
void set_dog_name(string names)
{
*this->name = names;
}
string get_dog_name()
{
return *this->name;
}
};
int main()
{
dog doggies;
doggies.set_dogs_breed();
doggies.set_dog_name("Socks");
doggies.get_dog_name();
}
In regards to
void set_dog_name(string names)
{
*this->name = names;
}
Everything works fine - makes sense, name is a pointer, I dereference name in set_dog_breed() and change it's value.
string get_dog_name()
{
return *this->name;
}
Causes
29:23: warning: 'doggies' may be used uninitialized in this function
[-Wmaybe-uninitialized]
35:9: note: 'doggies' was declared here
OK doggies is uninitialized but the compiler didn't mind when I wasn't using pointers - I am unclear as to why this is required or even if that is the actual issue.
The warning message is correct, the doggies object is uninitialized, you never initialize the member variables which has to be done in a constructor.
And since you don't initialize the object, the member variable name will have an indeterminate value and using the variable in any way except to initialize it will lead to undefined behavior.
The compiler doesn't stop you from doing bad things, it might detect them but it isn't required to do anything about it. And C++ doesn't have any kind of run-time checking either, the compiler and run-time system will happily let you shoot yourself in the foot.
Also, if you mostly use the dereference operator to access a pointer then you probably don't need a pointer in the first place.
The member string *name has no memory allocated for it. So you'd get a segmentation fault inside set_dog_name, where you assign another string to it.
Additionally, you don't initialize the members either in-class or in a constructor. This perhaps is pointed out by the compiler. GCC 5.2 however shows no warnings or errors, with both -Wall and -Wextra. I just get a segmentation fault when running the program. Live demo here.
Aside:
Initializing the global dogsbreed array is in no way the struct's concern. Instead you could make the variable as the struct's static member and initialize it separately.
struct dog {
static string dogsbreed[3];
};
string dog::dogsbreed[3] = { "Collie", "Poodle", "Pit Ball" } ;
i am running into a segfault in my c++ program and can't figure out my mistake.
I have a class Map which is a 2D-vector of objects of the class MapCells. The task is to go from cell to cell. From each cell, there are two possible ways to other cells. Maybe some 'pseudo' code can explain it better:
//map.h
class MapCell {
private:
MapCell *p_way1_, *p_way2_;
int some_information_;
public:
MapCell* getWayPointer1();
MapCell* getWayPointer2();
int getInformation();
void setWayPointer1(MapCell* new_p_way1);
void setWayPointer1(MapCell* new_p_way2);
};
class Map {
private:
std::vector< std::vector<MapCell> > map_;
public:
void initializeMap();
MapCell* getStartPointer();
};
int main()
{
Map map;
map.initializeMap();
MapCell *p_current_cell, *p_next_cell;
p_current_cell = map.getStartPointer();
while(p_current_cell->getInformation() != 0)
{
if(p_current_cell->getInformation() == 1)
{
p_next_cell = p_current_cell->getWayPointer1();
}
else
{
p_next_cell = p_current_cell->getWayPointer2();
}
p_current_cell = p_next_cell;
}
return 0;
}
This is only a little part of the real code. But i think i made a fundamental mistake so i hope this is enough code to fix it.
The problem is, that my code runs for minutes without problems and suddenly i get a segfault. gdb states, that the segfault happens when getInformation() is called. I also found out, that at some point all p_way2_ vectors lead to nonsense. Can you help me?
Thank you very much in advance!
Problem in lines
MapCell* p_current_cell, p_next_cell;
MapCell* p_way1_, p_way2;
Second parameter is not pointer and MapCell is implicit convert from pointers (or you will get multiple compile-times errors).
Try change to
MapCell* p_current_cell, *p_next_cell;
MapCell* p_way1_, *p_way2;
I have the following structure:
struct CountCarrier
{
int *CurrCount;
};
And this is what I want to do:
int main()
{
CountCarrier carrier = CountCarrier();
*(carrier.CurrCount) = 2; // initialize the *(carrier.CurrCount) to 2
IncreaseCount(&carrier); // should increase the *(carrier.CurrCount) to 3
}
void IncreaseCount(CountCarrier *countCarrier)
{
int *currCounts = countCarrier->CurrCount;
(*currCounts)++;
}
So, my intention is specified in the comments.
However, I couldn't get this to work. For starters, the program throws an exception at this line:
*(carrier.CurrCount) = 2;
And I suspect the following line won't work as well. Anything I did wrong?
struct CountCarrier
{
int *CurrCount; //No memory assigned
};
You need to allocate some valid memory to the pointer inside the structure to be able to put data in this.
Unless you do so, What you ar trying to do is attempting to write at some invalid address, which results in an Undefined Behavior, which luckiy in this case shows up as an exception.
Resolution:
struct CountCarrier
{
int *CurrCount; //No memory assigned
CountCarrier():CurrCount(new(int))
{
}
};
Suggestion:
Stay away from dynamic allocations as long as you can.
When you think of using pointers always think whether you really need one. In this case it doesn't really seem that you need one, A simple int member would be just fine.
You need to create the pointer. ie. carrier->CurrCount = new int;
*(carrier.CurrCount)
This is dereferencing the pointer carrier.CurrCount, but you never initialized it. I suspect this is what you want:
carrier.CurrCount = new int(2);
I seriously doubt that your program throws an exception at the line:
*(carrier.CurrCount) = 2;
While throwing an exception is certainly allowed behaviour, it seems much more likely that you encountered an access violation that caused the process to be killed by the operating system.
The problem is that you are using a pointer, but your pointer is not initialised to point at anything. This means that the result of the pointer dereference is undefined.
In this situation there does not seem to be any advantage to using a pointer at all. Your CurrCount member would work just as well if it was just a plain int.
If you are using C++, then you should encash its facilities. Instead of correcting your code, I am showing here that how the code should look like:
struct CountCarrier
{
int CurrCount; // simple data member
CountCarrier(int count) : CurrCount(count) {} // constructor
CountCarrier& operator ++ () // overloaded operator
{
++ CurrCount;
return *this;
}
};
We are overloading operator ++, because you have only one data member. You can replace with some named method also, like void IncrementCount().
CountCarrier carrier(2);
++ carrier;
As Als said, you need to provide some memory for the code to work.
But why make it so complicated? You don't need any pointers for the code you have to work. The "modern C++" way looks more like this:
struct CountCarrier
{
public:
CountCarrier(int currCount) : currCount(currCount) {}
void IncreaseCount() { ++currCount; }
int GetCount() const { return currCount; }
private:
int currCount;
};
int main()
{
CountCarrier carrier(2); // Initialize carrier.currCount to 2
carrier.IncreaseCount(); // Increment carrier.currCount to 3
}
Note how much cleaner and less error prone that is. Like I said, pick up a good introductory C++ book and read through it.