Guys I can't seem to do simple modification of a container object member stored in a vector. This member is an object itself. Both the container and its member are allocated on the stack. I think it is trying to deallocate a stack variable of the original name of the device when assigning a new one.
Please give me a clue on how to fix this while keeping variables allocated on the stack.
class Device{
public:
Device(string name):m_name(name)
{}
string getName(){
return m_name;
}
string setName(string newName){
m_name = newName;
}
private:
string m_name;
};
Then there is a Server that contains Devices:
class Server
{
public:
Device & getDevice(int i)
{
return devices.at(i);
}
void addDevice(Device && dev)
{
devices.push_back(dev);
}
private:
vector<Device> devices;
};
Here is how I test:
int main()
{
Server s{};
s.addDevice(Device{"ONE"});
s.addDevice(Device{"TWO"});
s.addDevice(Device{"THREE"});
cout<<s.getDevice(0).getName()<<endl;
s.getDevice(0).setName("XXX");
cout<<s.getDevice(0).getName()<<endl;
return 0;
}
What I am getting out is :
ONE
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000000617c20 ***
Aborted (core dumped)
You need to fix your setName method, is not returning anything and is marked to return a string.
string setName(string newName)
{
m_name = newName;
return m_name; //this is missing in the original code
}
Related
How can I store a pointer to the name of a person's spouse as a private member of the person's class?
For example, say I have the following code:
#include <iostream>
#include <list>
using namespace std;
class person
{
private:
string name;
string *spouse;
public:
void setName(string tempName) { name = tempName; }
void setSpouse(string &tempSpouse) { spouse = &tempSpouse; } // ERROR HERE?
string getName() { return name; }
string getSpouse() { return spouse; } // ERROR HERE?
};
int main()
{
person entry;
list<person> personList;
list<person>::iterator itr1, itr2;
/* Adding two people/nodes to the linked list. */
entry.setName("John Doe");
personList.push_back(entry);
entry.setName("Tina Doe");
personList.push_back(entry);
/* Attempting to assign Tina Doe as John Doe's spouse. */
for (itr1 = personList.begin(); itr1 != personList.end(); itr1++)
{
if (itr1->getName() == "John Doe")
{
for (itr2 = personList.begin(); itr2 != personList.end(); itr2++)
{
if (itr2->getName() == "Tina Doe")
{
itr1->setSpouse(itr2->getName()); // ERROR HERE?
}
}
}
}
/* Displaying all Names with Spouses afterwards. */
for (itr1 = personList.begin(); itr1 != personList.end(); itr1++)
{
cout << "Name: " << itr1->getName() << " | Spouse: " << itr1->getSpouse() << endl;
}
return 0;
}
I am unable to assign the address of the spouses name to the pointer member in the class. I've noted in the comments where I believe the errors might be.
You can view the code and errors here: https://ideone.com/4CXFnt
Any help will be greatly appreciated. Thank you.
getName returns a temporary std::string (copy of the name variable), and the compiler is trying to save you from referencing a part of memory that will be soon deleted. This error has nothing to do with lists - to fix it you need to either store copies in spouse variable (which will result in storing same data in multiple places) or return a reference in getName. You can also consider creating another accessor (private one), but it's ugly.
I'd recommend storing copies, but if references/pointes are really required then it's sufficient to modify lines:
string getName() { return name; }
string getSpouse() { return spouse; } // ERROR HERE?
to
string& getName() { return name; }
string getSpouse() { return *spouse; } // ERROR HERE?
however, for consistency I'd recommend:
string& getName() { return name; }
string& getSpouse() { return *spouse; } // ERROR HERE?
You have two problems. The first is easy to fix: getSpouse doesn't return the right type. You should write
string getSpouse() { return *spouse; } // Derefencing the pointer and returning a string
// or
string* getSpouse() { return spouse; } // Returning the pointer
The second problem is more subtle. When you write: itr2->getName() , you only have a value (a copy of itr2->name): you do not store a variable that you will be able to change, so you cannot make a reference to it.
There is no easy way you can have a pointer in a class instance pointing the a private variable of another instance. I guess you should question the way you are doing things and create a pointer to the person and not to the name (remember pointer are cheap, they are just memory locations).
class person
{
private:
string name;
person *spouse;
public:
void setSpouse(person *_spouse) { spouse = _spouse; }
person* getSpouse() { return spouse; }
string getSpouseName() { return spouse->getName(); }
};
This work, but still it is not safe: if spouse is destroyed and try to access it from person, you will run into deep problems… (note that you had the same problem with the string).
So what is the fix? Well, if you only want B to be the spouse of A, you can create B first and make a reference in A with a constructor. But if you want B to be the spouse of A and A the spouse of B, you have to use either the unsafe trick above and be careful, or stock the spouses' list outside the class.
Strange problem, already looked into with several colleagues...
Using Qt Creator and Qt 4.8.5
define an object
set a number of values with setters
request values with a getters
result: getting an int no problem, all other values give segmentation fault
but with breakpoint in debugger the values are correctly shown, so they are in the object!
same code worked before, problem "just appeared". Compiler issue?
private:
int id;
QString name;
public;
int getId() { return this->id; } // OK
void setId(int id) { this->id = id; }
QString getName() { return this->name; } // SIGSEGV
void setName(QString name) { this->name = name; }
Any ideas? Same issue known?
UPDATE
Changed code to this, based on comments, still same issue
private:
int id;
QString name;
public;
int getId() { return id; } // OK
void setId(int setTo) { id = setTo; }
QString getName() { return name; } // SIGSEGV
void setName(QString setTo) { name = setTo; }
I was facing similar issue. Although I could not find the root cause of this issue, I have another observation.
If we define the getter functions outside the class declaration using scope resolution operator the code works.
QString MyClass::GetX(void) {
return mX;
}
QString MyClass::GetY(void) {
return mY;
}
class MyClass
{
public:
MyClass(){}
/* Functions for setting mX and mY strings. */
QString GetX(void);
QString GetY(void);
isDataAvailable()
{
return mAvailable;
}
private:
bool mAvailable;
QString mX;
QString mY;
};
As I understand, in C++, if we define a function within class declaration, by default it is inline... so the issue could be something related with inlining of the functions.
thinking further about the way objects are created in memory, I thought that a QString maybe doesn't reserve fixed number of bytes, which could be the cause of this strange behavior and guess what, a dummy change solved my problem...
This feels like a really "dirty" solution, but at least I can go on with my work ;-)
But any idea's on the root cause would really be appreciated! Thanks already for all the valuable comments!!!
private:
QString name; // FIRST DEFINE QSTRING
int id; // THEN DEFINE INT
public;
int getId() { return id; } // OK
void setId(int setTo) { id = setTo; }
QString getName() { return name; } // OK
void setName(QString setTo) { name = setTo; }
Would anyone please explain this case: why I am facing 'double free' problem in this simple code?
void Rreceive (myclass){}
int main () {
myclass msg (1);
Rreceive(msg);
return 0;
}
where myclass is:
class myclass
{
private:
HeaderType header;
byte * text;
public:
myclass(int ID);
~myclass();
HeaderType getHeader();
byte * getText();
};
myclass::myclass(int ID){
header.mID = ID;
text = (byte *)malloc (10);
memset (text, '.', 10);
}
myclass::~myclass(){
free (text);
}
HeaderType myclass::getHeader(){
return header;
}
byte * myclass::getText(){
return text;
}
and HeaderType is:
typedef struct {
int mID;
}HeaderType;
The error is: *** glibc detected *** ./test: double free or corruption (fasttop): 0x0868f008 ***...
When you enter your Rreceive function you call the default copy constrcuctor which will not make a deep copy of your text pointer (in other words, he will just assign the pointer to the new copy).
When exiting the Rreceive scope you free (text) from the copied instance, which will point to the same memory address.
The you will try to free the same memory address again when exiting the scope of your main function.
I got a unhandled exception error at runtime when using the following C++ code, you can follow the error with debug using Visual Studio. Why will this exception happen, can you explain it?
First I define a class with a menber variable "_name"
void insert_Fenster(int pos,wstring name);
wstring get_Fenster_name(int pos);
class Fenster
{
public:
Fenster(wstring name)
:_name(name)
{}
void reload()
{
_name;
insert_Fenster(1,L"temp");
wstring tmp = get_Fenster_name(1);
_name = tmp; //ERROR!!!
}
wstring get_name()
{
return _name;
}
private:
wstring _name;
};
Second I define a class to hold a map of the class
class FensterManager
{
public:
bool has(int pos)
{
if (_mapFenster.find(pos)!=_mapFenster.end())
return true;
else
return false;
}
void insert(int pos,wstring name)
{
if (has(pos))
{
_mapFenster.erase(pos);
}
_mapFenster.insert(make_pair(pos,Fenster(name)));
}
Fenster& get_Fenster(int pos)
{
return _mapFenster.at(pos);
}
private:
static map<int,Fenster> _mapFenster;
};
And some util functions
void insert_Fenster(int pos,wstring name)
{
FensterManager fm;
fm.insert(pos,name);
}
void reload_Fenster(int pos)
{
FensterManager fm;
if (fm.has(pos))
fm.get_Fenster(pos).reload();
}
wstring get_Fenster_name(int pos)
{
wstring name;
FensterManager fm;
if (fm.has(pos))
name = fm.get_Fenster(pos).get_name();
return name;
}
//Init of static member before main function
map<int,Fenster> FensterManager::_mapFenster;
that is the main function
void main()
{
insert_Fenster(1,L"xyz");
reload_Fenster(1);
}
The exception happen at "reload" function in class "Fenster".
With error message:
Unhandled exception at 0x005cca34 (msvcr100d.dll) in Regular_Expression.exe: 0xC0000005: Access violation writing location 0xfeeefeee.
When you call reload_Fenster(1);, it will call Fenster::reload. In that function you call insert_Fenster(1,L"temp");. FensterManager::insert will first erase position 1 from the map. So when you return to Fenster::reload, the instance has been deleted. As soon as you try to access _name, you try to access memory which has been deleted.
edit:
To clarify; this function call:
fm.get_Fenster(pos).reload();
will first call fm.get_Fenster(pos) and then call reload() on the result. If fm.get_Fenster(pos) changes in the reload() function, execution will not move the new Fenster, but the old one will keep executing. Even if you delete the old Fenster.
You should make sure not to delete an instance if you are still running functions inside it. It will crash the application as soon as you try to access members, because they are stored in memory which has been deleted.
looks like something inside void insert_Fenster(int pos,wstring name); - look further up the call stack and you'll see which part of your code is calling into the runtime dll. That'll be the error.
Can you please provide more information regarding the unhandled exception.
There is one obvious mistake in the above code. The insert_Fenster is inserting into a FensterManager instance and the reload_Fenster is trying to reload from a different instance of the FensterManager which is wrong.
void main()
{
FensterManager fm;
insert_Fenster(fm, 1,L"xyz");
reload_Fenster(fm, 1);
}
The insert and reload method should be updated as follows:
void insert_Fenster(FensterManager &fm, int pos,wstring name)
{
fm.insert(pos,name);
}
void reload_Fenster(FensterManager &fm, int pos)
{
if (fm.has(pos))
fm.get_Fenster(pos).reload();
}
Let's say I have the following:
char cipan[9];
then what should I pass to the function? how about the get and set method??
I'm currently doing like this
set method
void setCipan(char cipan[]){
this->cipan = cipan;
}
and the get method
char getCipan(){
return cipan;
}
and I get an error when compiling??
Im totally blur.. can someone explain what should i pass to the function??
class userData{
private:
string name;
char dateCreate[9];
void userDataInput(string name,char dateCreate[]){
this->name = name;
this->dateCreate = dateCreate;
}
public:
//constructor
userData(string name){
userDataInput(name,dateCreate);
}
userData(string name,char dateCreate[]){
userDataInput(name,dateCreate);
}
//mutator methods
void changeName(string name){this->name = name;}
void changeDateCreate(char *dateCreate){this->dateCreate = dateCreate;}
//accesor methods
string getName(){return name;}
char *getDateCreate(){return dateCreate;}
};
I'd do the following:
void setCipan(const char* new_cipan)
{
strcpy(cipan, new_cipan);
}
const char* getCipan() const
{
return cipan;
}
Of course, the better approach is to use std::string:
void setCipan(const string& new_cipan)
{
cipan = new_cipan;
}
string getCipan() const
{
return cipan;
}
Constructor's purpose is to initialize class variables. I think it's unnecessary to call another method in the constructor to do initialization.
void userDataInput(string name,char dateCreate[]){
this->name = name;
this->dateCreate = dateCreate; // Both the dateCreate are class variables.
}
userData(string name){
userDataInput(name,dateCreate); // dateCreate is already a class variable.
}
dateCreate is the class scope variable. You are just passing it to a method, and re-assigning the same to dateCreate. Assignment operation doesn't copy elements of one array to another and are invalid operations.
To copy array elements, use std::copy instead.