I should get the same in both lines..
what happen I get two different values.. like it was aiming to different positions..
I think the error is inside the d->add(*b)
the output is
thiago 14333804
Ph¿├┌ 2816532
to describe it better I put the code below
I got a program
int main(int argc, char **argv) {
CClass* c = new CClass();
BClass* b = c->getNext();
printf("%s %d \n", b->getValue(), b->getValue());
DClass* d = new DClass();
d->add(*b);
printf("%s %d \n", d->getNext(), d->getNext());
cin.get();
return 0;
}
the interfaces are below
class BClass
{
private:
char* value;
bool stale;
public:
BClass(char* value);
~BClass(void);
char* getValue();
bool isStale();
};
class CClass
{
private:
vector<BClass*> list;
public:
CClass(void);
~CClass(void);
BClass* getNext();
};
class DClass
{
private:
vector<BClass*> list;
static bool isStale(BClass* b) { return b->isStale();};
public:
DClass(void);
~DClass(void);
void add(BClass s);
char* getNext();
};
and the implementation follows
//BClass
BClass::BClass(char* value)
{
this->value = value;
this->stale = false;
}
BClass::~BClass(void)
{
}
char* BClass::getValue()
{
return value;
}
bool BClass::isStale()
{
return stale;
}
//CClass
CClass::CClass(void)
{
list.push_back(new BClass("thiago"));
list.push_back(new BClass("bruno"));
list.push_back(new BClass("carlos"));
}
CClass::~CClass(void)
{
}
BClass* CClass::getNext()
{
return list.at(0);
}
//DClass
DClass::DClass(void)
{
}
DClass::~DClass(void)
{
}
void DClass::add( BClass s )
{
list.push_back(&s);
}
char* DClass::getNext()
{
BClass* b = list.at(0);
return b->getValue();
}
When you pass in an instance of class B into D::add() function you create a deep copy of the object and that copy is what is put on stack. Later on you use the address of that copy to push it into list. Once the function is done this automatic variable goes out of scope thus the pointer you used to put into list is no longer valid.
To fix change your interface to avoid deep copies as follows:
void DClass::add( BClass * s )
{
list.push_back(s);
}
Step-by-step of what your code is doing
BClass* b = c->getNext(); // you get the address of the first element from the list (created in constructor) and assign it to b
d->add(*b); // the *b will dereference the object pointed to by b and put it onto stack in preparation to the call to add()
void DClass::add( BClass s ){ // the deep copy of a dereferenced object is put into this function's stack frame
list.push_back(&s); // an address of that temporary copy of the original object is being used to be added to your list
} // this is where the fun happens - once the function is done it will unwind the stack back up and the memory, previously occupied by that temp copy, will be re-used for other purposes. In your case - it will be used to pass parameters to functions d->getNext() (there's always a hidden this parameter to non-static member functions) and later to the printf() function. Remember - your previous pointer to that temp copy is still pointing to the stack, but it's now occupied by different data, causing you to see corruption
General rule of thumb - never use pointers to temp objects ;-)
in the DClass::add function, BClass s is a local variable.
void DClass::add( BClass s )
{
list.push_back(&s);
}
When you call d->add(*b);, you're passing a BClass by value, meaning you're creating a copy of it, and the address of that copy is not the same address of the original.
s will go out of scope as soon as the function returns, and the pointer to it will be invalid. So storing that pointer is no good to you, since dereferencing it would be undefined behaviour.
Related
I'm trying to return pointer from function in derived class,
This is the code:
class A
class A {
protected:
C c;
public:
virtual void func(){
unsigned char *data;
int size=getData(data);
}
}
class B
class B : public A {
private:
int size;
public:
B(const C &_c) { c=_c; };
const int B::getData(unsigned char *data) const {
data=(unsigned char *)malloc(size);
memcpy(data,c.getMem(),size);
if(!data){
//err
}
return size;
}
class C
class C {
private:
unsigned char *mem;
public:
C(unsigned char *_mem) : mem(_mem);
const unsigned char *getMem() const { return mem; };
}
main.cpp
C c(...);
B *b=new B(c);
b->func();
The error I get when getData returns
(this=0x50cdf8, data=0x2 <error: Cannot access memory at address 0x2>, size=32)
Thanks.
In class A, the func() is worthless because:
1. size is not returned to the caller.
2. The pointer data is local to func and it's contents will disappear after the end of execution in func().
You don't need to return const int from a function. A function will return a copy of variables, so they are constant (copies).
Don't use malloc in C++, use operator new. The malloc function does not call constructors for objects.
Don't use new or malloc unless absolutely necessary. Usually, dynamic memory is for containers where their capacity is not known at compile time; or for objects that live beyond a function or statement block's execution time. If you must use dynamic memory, use a smart pointer (like boost::shared_ptr).
Use std::vector for dynamic arrays. It works; it's been tested; you don't have to write your own, including memory management.
You are passing data by value (a copy of the pointer). If you want to modify a pointer, pass it by reference or pass a pointer to the pointer; (what I call the address of the pointer).
Example:
void my_function(uint8_t * & p_data)
{
p_data = new uint8_t[512];
}
Or
void another_function(unsigned char * * pp_data)
{
*pp_data = new unsigned char [1024];
}
A much better solution:
void better_function(std::vector<uint8_t>& data)
{
data.reserve(64);
for (uint8_t i = 0; i < 64; ++i)
{
data[i] = i;
}
}
So, I've found myself doing this a lot, and wonder if it's correct practice (this probably won't compile - I'm writing this on my phone):
class Shared
{
private:
int _x;
public:
void X(int newValue) { _x = newValue; }
int X() { return _x; }
Shared(void) : _x(0)
{
}
};
class Owner
{
private:
shared_ptr<Shared> _shared;
public:
const Shared& Shared() const
{
return *_shared;
}
void Shared(const Shared& newValue)
{
_shared.reset(&newValue);
}
void DoSomethingWithShared()
{
/// yeah, this could be cleaner, not the point!
_shared.X(_shared.X() + 1);
}
};
void CreateStuff(Owner& a, Owner &b)
{
Shared s;
a.Shared(s);
b.Shared(s);
}
int main(int argc, char *argv[])
{
Owner a;
Owner b;
CreateStuff(a,b);
a.DoSomethingWithShared();
b.DoSomethingWithShared();
///...
/// "Shared" instance created in CreateStuff() hopefully lives until here...
}
The idea is that multiple instances of Owner need a shared resource of type Shared.
Is CreateStuff() an error? (ie, does s go out of scope, leaving a and b with invalid pointers to a destroyed object? (Am I returning the address of a temporary in a roundabout way?)
Are there any other scope/GC issues I'm not seeing?
Is there an easier way to do this?
CreateStuff is definitively wrong. You're (eventually) passing a pointer to a local variable into the shared_ptrs, which outlive that variable. Once it goes out of scope, you'll have two dangling pointers inside those _shareds.
Since you're using smart pointers, why not dynamically allocate that Shared on the heap, and let the smart pointers worry about deleting it when they're done?
void CreateStuff(Owner& a, Owner &b)
{
std::shared_ptr<Shared> s(new Shared);
a.Shared(s); // have that Shared() modified to take the shared_ptr,
b.Shared(s); // of course
}
In an effort to become a more competent C++ programmer I'm experimenting w/ using references. In the past I have usually used pointers when referring to objects, as you would for example in Objective-C.
So I've been programming a Polynomial class that stores a list of Term objects
(TermNode* termHead,termTail)
But when I try to add a term to the list using the first implementation listed, calling the constructor on Term in add term, overwrites the Term& reference in the previously created Term node, as if it used the this pointer from the previous invocation of the constructor.
What is technically wrong about the first implementation listed, that causes it to behave so abnormally? It just works when I use pointers and new even though I do not change the structure of TermNode.
struct TermNode {
Term& value;
TermNode* next;
};
Term::Term(int coefficient,int firstTermDegrees,int secondTermDegrees) {
this->coefficient = coefficient;
this->xDegree = firstTermDegrees;
this->yDegree = secondTermDegrees;
}
//Doesn't work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree) {
Term term(coefficient,xDegree,yDegree);
addTerm(term);
}
void Polynomial::addTerm(Term& term) {
TermNode* t = new TermNode{term,nullptr};
if(isEmpty())
{
termHead = t;
termTail = t;
}
else
{
termTail->next = t;
termTail = termTail->next;
}
}
//Does work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree) {
Term* term = new Term(coefficient,xDegree,yDegree);
addTerm(term);
}
void Polynomial::addTerm(Term* term) {
TermNode* t = new TermNode{*term,nullptr};
if(isEmpty())
{
termHead = t;
termTail = t;
}
else
{
termTail->next = t;
termTail = termTail->next;
}
}
bool isEmpty() {
return nullptr == termHead;
}
//Doesn't work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree)
{
Term term(coefficient,xDegree,yDegree);//here you created automatic object
addTerm(term); //it will be deleted in next line
} //it is an error to call addTerm(Term& term)
this works
//Does work
void Polynomial::addTerm(int coefficient, int xDegree, int yDegree)
{
Term* term = new Term(coefficient,xDegree,yDegree);
addTerm(term);
}
because here you created object on a free store. It's life is extended till you call delete on it (side note: call delete somewhere, at this moment you have a memory leak! or use smart pointer), so this works just fine.
void Polynomial::addTerm(Term* term)
{
TermNode* t = new TermNode{*term,nullptr};
// ...
}
You can use references but in the way they are supposed to be used. You can't use a reference to temporary when it was actually deleted. You can bind temporary object to const reference however, but because of your struct definition
struct TermNode
{
Term& value;
TermNode* next;
};
in constructor you take a reference again, so binding temporary to const reference in this case will again result in segmentation fault.
In the first implementation you passes a reference to a temporary object which is destroyed at the end of method addTerm.
I have narrowed my problem down to passing 2 objects (which contain pointer data members) to a simple void function. The function returns clean, but when main() attempts to exit, it can not reclaim the first of the 2 objects. Here is a sample piece of code that shows the issue - along with print statements to show the address's of the objects as they are constructed, passed, and destructed.
If I only call "print1" - the program runs fine. However, if I call "printboth" - then the object "myNumbers" can not be freed. I can also make the error go away by removing the destructor statement:
delete [] number;
but I don't think this is a good idea.
Anyone have any ideas?
class dummy
{
public:
dummy() {
number = new int[1];
currentPos = -1;
std::cout<<"default constructor called for "<<this<<std::endl;
}
dummy(int len) {
number = new int[len];
currentPos = -1;
std::cout<<"parameterized constructor called for "<<this<<std::endl;
}
~dummy() {
cout<<"Calling destructor for "<<this<<endl;
delete [] number;
}
int getNextNumber() {
currentPos++;
return number[currentPos];
}
void setNumbers(int position, int value) {
number[position] = value;
}
private:
int* number;
int currentPos;
};
void print1(dummy);
void printboth(dummy, dummy);
int main() {
dummy myNumbers(3);
myNumbers.setNumbers(0,0);
myNumbers.setNumbers(1,1);
dummy myOtherNumbers(3);
myOtherNumbers.setNumbers(0,4);
myOtherNumbers.setNumbers(1,5);
cout<<"Address of myNumbers is "<<&myNumbers<<endl;
cout<<"Address of myOtherNumbers is "<<&myOtherNumbers<<endl;
print1(myNumbers);
printboth(myNumbers, myOtherNumbers);
system("PAUSE");
return 0;
}
void print1(dummy num) {
cout<<"Address of num is "<<&num<<endl;
for (int i=0;i<4;i++)
cout<<"Dummy number1 is "<<num.getNextNumber()<<endl;
return;
}
void printboth(dummy num1, dummy num2) {
cout<<"Address of num1 is "<<&num1<<endl;
cout<<"Address of num2 is "<<&num2<<endl;
for (int i=0;i<4;i++) {
cout<<"Dummy number1 is "<<num1.getNextNumber()<<endl;
cout<<"Dummy number2 is "<<num2.getNextNumber()<<endl;
}
return;
}
You didn't follow rule of three
The problem is that when you call print1 or printboth the compiler calls the default copy-constructor (since you didn't provide one). That copy-constructor sets the number member variable of the copy to the same value as the original. When the destructor is called on the copy, the memory is released. Your original object now points to memory that has already been released so when its destructor is called, you crash(Nik Bougalis).
void print1(dummy);
void printboth(dummy, dummy);
You could pass dummy by const reference to avoid unnecessary copy, but strong recommand you follow rule of three
void print1(const dummy& );
void printboth(const dummy&, const dummy&);
Note:
You only created size =1 array which is not necessary at all, just use int number; as member. If number holds dynamically allocated array, try use std::vector<int>.
getNextNumber is flawed, when it's called multiple times, number[currentPos]; access boundry out of number which is undefined behavior.
int getNextNumber() {
currentPos++;
return number[currentPos];
}
Which implies what suggested:
int getNextNumber() const {
return number[currentPos];
}
I have a list where I store a pointer to a pointer of objects. I have a function where I create pointers to these objects and store their addresses in the list (hence pointer to a pointer). However once this function is done that pointer is no longer valid (the object is but not the pointer because it's out of scope) so now my pointer to pointer doesn't work. How do you get around this?
list<Actor**> lst;
void CreateEnemy()
{
Actor* a = new Actor();
lst.push_back(&a);
}
int _tmain(int argc, _TCHAR* argv[])
{
CreateEnemy();
// at this point the pointer to a pointer stored in lst isn't valid anymore because it went out of scope after CreateEnemy() completed.
}
Here's a simple example of something you could do based on your comments.
list<unique_ptr<Actor>> lst;
void CreateEnemy()
{
lst.push_back(unique_ptr<Actor>(new Actor));
}
void KillRandomEnemies()
{
for (auto& i : lst)
{
if (rand() % 100)
i.reset();
}
}
class Projectile
{
public:
Projectile(unique_ptr<Actor> & a)
:actor(&a)
{}
bool IsTargetDead() const { return !(*actor); }
private:
unique_ptr<Actor> * actor;
};
int main()
{
CreateEnemy();
Projectile proj(lst.front());
while (something())
{
KillRandomEnemies();
if (proj.IsTargetDead())
whatever();
}
}
Just use std::list<Actor*> and store the pointer. Or, even better, std::list<Actor>. There's nothing here that suggests a need for any pointers, much less a pointer to a pointer.
Try this :
after the call to createEnemy :
Actor * a = * lst.front();
a -> some function.
Is this still doing problems?
I tested the code on my own class and it was fine.