Passing pointer to new object over nested calls - c++

The code is really simple, consisting of nested similar method calls on different classes, but the program keeps segfaulting on random occasions (always during the Add method though).
I call method Add on class CScreen instance to add an object CCircle, which is cloned (a new instance is created) and pointer is passed down hierarchically until it reaches xnode (my own implementation of list node).
int main (){
CScreen S1;
S1 . Add ( CCircle ( 3, 20, 20, 15 ) );
}
class CScreen {
public:
Qlist <Planimetric*> objects;
void Add (const Planimetric & ob ) {
objects.push_back( ob.clone() ); // returns pointer to new instance
}
...
template<typename _Type>
class Qlist{
public:
Qnode <_Type> *start;
Qlist() : start(null) {
start = new Qnode<_Type>(-coordInfinity, -coordInfinity, coordInfinity, coordInfinity);
}
void push_back (const _Type & data) {
start->push_back(data);
}
...
template<typename _Type>
struct Qnode{
xlist <_Type> objects;
void push_back (const _Type & data) {
objects.push_back(data);
}
...
template<typename _Type>
class xlist{
public:
int sizeOfList;
xnode<_Type> *first, *last;
void push_back (const _Type & data) {
sizeOfList ++;
xnode<_Type> *nnp; // new node pointer ;)
if(first == null)
first = last = new xnode<_Type> (data);
else
last = last->next = nnp = new xnode<_Type>(data, last);
}
...
template<typename _Type>
struct xnode{
_Type data;
xnode *prev, *next;
xnode(const _Type & data, xnode* prev = null, xnode* next = null)
: data(data), prev(prev), next(next) {}
...
class CCircle : public Planimetric {
public:
long long int x,y;
long long int rsq;
CCircle * clone () const {return new CCircle(*this);}
CCircle (int ID, int x, int y, int r) : Planimetric(ID), x(x), y(y) { ...
...
}
I thought it might be a stack overflow because of the high overhead, but it sometimes segfaults on first call. The xlist and xnode implementation worked perfectly until i implemented Qlist.
I'm passing down const pointer reference, which is then copied in constructor in xnode. Could the problem be there? I've tried to debug with gdb, with no luck.

Related

How to implement the two member functions (push_front and the destructor)?

I am trying to implement two member functions, i.e., push_front and the destructor. I have written the code of the push_front function. But I seem, I am doing wrong anywhere. How can I fix this issue? How can I insert a node in front of Linked-List properly?
template <typename T>
class Node {
public:
Node():next_p_{nullptr} {}
Node(T v, Node* n):data_{v}, next_p_{n} {}
~Node() {};
void setData( T &v ) { data_ = v; }
const T &getData() const { return data_; }
void setNext( Node *n ) { next_p_ = n; }
Node *getNext() const { return next_p_; }
private:
T data_;
Node *next_p_;
};
template <typename T>
class LinkedList {
private:
Node<T> *head_ptr_;
public:
LinkedList():head_ptr_{nullptr} {}
~LinkedList() {
}
// Insert at the front of the linked list (UPDATED)
void push_front( T v ){
Node *new_node = new Node;
new_node->setNext(*head_ptr_) = v;
new_node->next_p_ = this->head_ptr_;
this->head_ptr_ = new_node;
}
};
The first Node constructor takes the value and next pointer, use that to create the new node in one step.
You shouldn't dereference head_ptr_ when using it as the next pointer. It's already a Node*, which is the correct type for head_ptr_.
void push_front( T v ){
Node *new_node = new Node(v, head_ptr_);
this->head_ptr_ = new_node;
}
I would also recommend not dealing with manual memory management and instead use smart pointers to simplify your life a bit.
Using std::unique_ptr you wont have to deal with reclaiming the memory you allocated from the free store.
One caveat to this approach is you lose your ability to copy the List but usually that's what you want anyway.
template<typename T>
class List {
struct Node {
Node( T value ) noexcept
: data{ std::move_if_noexcept( value ) }
{ }
T data;
std::unique_ptr<Node> next{ nullptr };
};
public:
auto push_front( T value ) -> void {
auto node{ std::make_unique<Node>( std::move_if_noexcept( value ) ) };
std::swap( node->next, head_ );
std::swap( head_, node );
}
~List()
{
while (head_) {
std::unique_ptr<Node> tmp(std::move(head_));
head_ = std::move(tmp->next);
}
}
private:
std::unique_ptr<Node> head_{ nullptr };
};

How to get pointer to new variable when using a move constructor

So I've got this code:
//movable_ptr.hpp
//Michal Cermak
template<typename T> class movable_ptr;
template<typename T> class enable_movable_ptr {
public:
//default constructor
enable_movable_ptr() {};
//move constructor and assignment
enable_movable_ptr(enable_movable_ptr<T>&& p) {
first_ = p.getFirst();
p.retarget_to(this);
};
enable_movable_ptr<T>& operator=(enable_movable_ptr<T>&& p) {
if (this != &p)
{
first_ = p.getFirst();
p.retarget_to(this);
delete &p;
}
return *this;
};
//retargets all pointers in the linked list to a new address
void retarget_to(T* p)
{
if (first_ != nullptr)
{
auto current = first_;
do
{
current->set(p);
current = current->getNext();
} while (current != first_);
}
};
movable_ptr<T>* getFirst() { return first_; };
void setFirst(movable_ptr<T>* p) { first_ = p; };
private:
movable_ptr<T>* first_ = nullptr;
};
template<typename T> class movable_ptr {
public:
//constructors and stuff...
//access to variables
T* get() {return ptr_; };
void set(T* p) { ptr_ = p; };
movable_ptr<T>* getNext() { return next_; };
void setNext(movable_ptr<T>* p) { next_ = p; };
movable_ptr<T>* getPrevious() {return prev_; };
void setPrevious(movable_ptr<T>* p) { prev_ = p; };
private:
T* ptr_ = nullptr;
movable_ptr<T>* next_ = this;
movable_ptr<T>* prev_ = this;
};
My problem is that I need to give T * to retarget_to, but I use retarget_to(this) in the move constructor and assignment in enable_movable_ptr. That passes it enable_movable_ptr<T> * instead of just T *. The thing is, I assume that T inherits from enable_movable_ptr, which will never be used directly, only through the object that inherits from it. For example:
class A : public enable_movable_ptr<A>
{
public:
int val;
A(int val) : val(val) {}
};
And then used like this:
A x(42);
A y = move(x);
In this case, this would be enable_movable_ptr<A> *, but I need something that would give me A * instead. Basically I need a pointer to the lvalue of the = operator, while inside an overload of said operator. Is there any way to do this or am I asking for something impossible?
I haven't understood your question entirely, because it's not clear what you want to achieve with this enable_movable_ptr class. I think your way of writing operator= is ill-formed. You are trying to explicitly call delete on a pointer to r-value (which may firstly be allocated on stack, and moreover probably will be destroyed later anyway via some other mechanism).
I would suggest to consider copy-and-swap approach for operator=, this would allow you to not worry about checking if you are assigning object into itself. The signature would be enable_movable_ptr<T>& operator=(enable_movable_ptr<T> other) (note passing by value).

calling the destructor from a friend class

I am using friend classes and I want to use rec's destructor when I call DeleteItem from my list class. However, there is a pointer pointing to the record that I want to delete, so I do not know how to call the destructor so it will do what I want.
Classes:
class rec
{
friend class list;
private:
char * id;
char firstname[15];
char lastname[15];
int ar[10];
rec* prev;
rec* next;
public:
void SetData ( char * id_in, char * fn, char * ln, int * ans_in);
rec( char *i, char *fn, char *ln, int *a);
rec();
void operator= (const rec& r);
rec (const rec& r);
void Print();
~rec();
};
class list
{
private:
rec* first;
rec* last;
public:
int AddItem(rec r);
int DeleteItem (char* delid);
void PrintList( int order);
int ReadData(char *inanswer, char *inkey);
int WriteData(char *answer, char *key);
list();
void operator= (list l);
private:
int CheckDuplicate(rec r);
void DeleteData();
int Count(char *filename);
};
~rec()
rec :: ~rec()
{
if (id != NULL)
{
delete [] id;
}
}
DeleteItem (Snipet)
int list :: DeleteItem(char *delid)
{
int id_counter;
rec *current = first;
while (current || current == NULL)
{
if (current == NULL)
{
return 0;
}
else
{
id_counter = strcmp(current -> id, delid);
if (id_counter != 0)
{
current = current -> next;
}
else
{
if (current == first && current != last)
{
~rec(); //Here
first = current -> next;
delete current;
first -> prev = NULL;
return 1;
}
Delete item will compile fine if I manually put in delete[] current ->id; but does this when I try to compile as is
list.cpp:292: error: no match for ‘operator~’ in ‘~rec()’
/usr/lib/gcc/x86_64-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ios_base.h:105: note: candidates are: std::_Ios_Fmtflags std::operator~(std::_Ios_Fmtflags)
/usr/lib/gcc/x86_64-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ios_base.h:145: note: std::_Ios_Openmode std::operator~(std::_Ios_Openmode)
/usr/lib/gcc/x86_64-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ios_base.h:183: note: std::_Ios_Iostate std::operator~(std::_Ios_Iostate)
Is it my destructor that needs to be fixed or is it something to do in DeleteItem?
To call a destructor, the syntax is current->~rec(), but in almost cases, you shouldn't call directly a destructor in C++. By calling delete current, the C++ will automatically call the destructor before de-allocating its memory.
In your case, as you are also using delete after calling ~rec(), your destructor will be called twice, so you will result to a double free corruption as your constructor is trying to free id memory.
Advice: To avoid using friend class, in your case, next and prev members are related to the list, and not to rec class. So your list class could have a nested decorator class that will wrap your rec class like:
class list
{
struct item {
rec* value;
rec* prev;
rec* next;
};
item * first;
item * last;
public:
// ...
};
Then the logic of your list will be well isolated from the logic of your rec class.

HUGE memory leak when returning std::map<std::string, int> from dereferenced iterator

**Be careful**, not only does this program hang, but apparently it takes all of your memory forever, rendering your computer a slow and awful mess. I've been struggling with this for a real long time, and have figured out a lot of things—except for why it actually hangs. Sorry that there's so much code, but I cut out everything irrelevant and this is what was left.
LinkedList
//=====================
// Linked List
#include <stdexcept>
template<class T> struct LinkedList {
public:
LinkedList();
LinkedList(const LinkedList& srcList);
~LinkedList();
void addObject (T& addedObject);
class ListIterator {
public:
ListIterator();
explicit ListIterator(LinkedList<T>& parentList);
// Operators
ListIterator& operator++();
T& operator*() const;
bool operator!=(const ListIterator& otherIter);
private:
typename LinkedList::Node* current_;
};
ListIterator begin();
ListIterator end();
std::size_t size_;
private:
struct Node {
Node();
Node(T& object);
Node(const Node&) = delete;
T* const object_;
Node* next_;
Node* prev_;
};
Node head_;
Node tail_;
};
//====================
// Classes (Implementation)
// Linked List default constructor
template<class T> LinkedList<T>::LinkedList()
: size_{0} {
head_.next_ = &tail_;
tail_.prev_ = &head_;
};
// Linked List copy constructor
template<class T> LinkedList<T>::
LinkedList(const LinkedList& srcList) {
size_ = srcList.size_;
head_.next_ = &tail_;
tail_.prev_ = &head_;
ListIterator nodesToCopy = srcList.begin();
while (nodesToCopy != srcList.end()) {
this->addObject(*nodesToCopy);
srcList.removeObject(1);
};
delete &srcList;
};
// Linked List destructor
template<class T> LinkedList<T>::~LinkedList() {
for (unsigned int ii = 1; ii == size_; ++ii) {
Node* toDelete = head_.next_;
head_.next_ = head_.next_->next_;
delete toDelete;
};
};
// Add object to Linked List
template<class T> void LinkedList<T>::addObject(T& addedObject) {
Node* node = new Node(addedObject);
node->prev_ = tail_.prev_;
tail_.prev_->next_ = node;
tail_.prev_ = node;
node->next_ = &tail_;
++size_;
};
// Linked List Iterator constructor
template<class T> LinkedList<T>::ListIterator::
ListIterator(LinkedList<T>& parentList) {
current_ = parentList.head_.next_;
};
// Iterator operators
// Increment forward
template<class T> typename LinkedList<T>::ListIterator& LinkedList<T>::
ListIterator::operator++() {
current_ = current_->next_;
return *this;
};
// Return object pointed to
template<class T> T& LinkedList<T>::ListIterator::
operator*() const {
return *(current_->object_);
};
template<class T> bool LinkedList<T>::ListIterator::
operator!=(const ListIterator& otherIter) {
return &(**this) != &(*otherIter);
};
// Return an iterator object via begin() and end()
template<class T> typename LinkedList<T>::ListIterator
LinkedList<T>::begin() {
ListIterator beginIterator(*this);
return beginIterator;
};
template<class T> typename LinkedList<T>::ListIterator
LinkedList<T>::end() {
ListIterator endIterator(*this);
for (unsigned int ii = 0; ii < size_; ++ii) { ++endIterator; };
return endIterator;
};
// Node constructors
template<class T> LinkedList<T>::Node::Node()
: object_(nullptr), next_(nullptr), prev_(nullptr) {};
template<class T> LinkedList<T>::Node::Node(T& object)
: object_(&object) {};
Item
//=====================
// Item
//====================
// Included dependencies
#include <string>
#include <array>
#include <map>
#include <iostream>
class Item {
public:
Item();
Item(std::string name);
Item(std::string name, std::array<int, 2> stats);
std::map<std::string, int> getStats();
std::string name_;
private:
std::map<std::string, int> enhancements_;
};
// Constructors
Item::Item() {
enhancements_["Str"] = 0;
enhancements_["Def"] = 0;
};
Item::Item(std::string name) : Item::Item() { name_ = name; };
Item::Item(std::string name, std::array<int, 2> stats)
: Item::Item(name) {
enhancements_["Str"] = stats[0];
enhancements_["Def"] = stats[1];
};
// Return map of stats
std::map<std::string, int> Item::getStats() { return enhancements_; };
Room
//====================
// Room
class Room {
public:
void addItem(Item item);
LinkedList<Item>::ListIterator getItems();
LinkedList<Item> itemsInThisRoom_;
};
// Add item to room
void Room::addItem(Item item) { itemsInThisRoom_.addObject(item); };
// Get iterator which iterates over items in room
LinkedList<Item>::ListIterator Room::getItems() {
return itemsInThisRoom_.begin();
};
main
int main() {
std::array<int, 2> swordStats = {{5, 0}};
std::array<int, 2> shieldStats = {{0, 2}};
std::array<int, 2> armorStats = {{0, 3}};
Item sword("Sword", swordStats);
Item shield("Shield", shieldStats);
Item armor("Armor", armorStats);
Room room;
room.addItem(shield);
room.addItem(sword);
room.addItem(armor);
LinkedList<Item>::ListIterator roomItems = room.itemsInThisRoom_.begin();
while (roomItems != room.itemsInThisRoom_.end()) {
(*roomItems).getStats();
++roomItems;
};
return 0;
};
All of this can be put in a single file and compiled (I split it up by class to make it easier to read). This is the line, in main, where it hangs:
(*roomItems).getStats();
This leads me to believe there's something wrong with my dereference operator, right? If we create an iterator outside of the Room class, dereference it, and getStats the same way—everything works ok.
... so it's an issue with the Room class?
But, if we change Item and main to the following:
//=====================
// Item
//====================
// Included dependencies
#include <string>
#include <array>
#include <map>
#include <iostream>
class Item {
public:
Item();
Item(std::string name);
Item(std::string, int);
int getStats();
std::string name_;
private:
int enhancements_;
};
// Constructors
Item::Item() {
enhancements_ = 0;
};
Item::Item(std::string name) : Item::Item() { name_ = name; };
Item::Item(std::string name, int stats)
: Item::Item(name) {
enhancements_ = stats;
};
// Return map of stats
int Item::getStats() { return enhancements_; };
//====================
// Room
class Room {
public:
void addItem(Item item);
LinkedList<Item>::ListIterator getItems();
LinkedList<Item> itemsInThisRoom_;
};
// Add item to room
void Room::addItem(Item item) { itemsInThisRoom_.addObject(item); };
// Get iterator which iterates over items in room
LinkedList<Item>::ListIterator Room::getItems() {
return itemsInThisRoom_.begin();
};
int main() {
Item sword("Sword", 1);
Item shield("Shield", 2);
Item armor("Armor", 3);
Room room;
room.addItem(shield);
room.addItem(sword);
room.addItem(armor);
LinkedList<Item>::ListIterator roomItems = room.itemsInThisRoom_.begin();
while (roomItems != room.itemsInThisRoom_.end()) {
(*roomItems).getStats();
++roomItems;
};
return 0;
};
Everything runs excellently. I can return int values alright.
... so... it's neither an issue with the Room class or the dereference operator, but returning std::map? GDB does not have much to say. When I break at the offending line and step, I get:
24 std::map<std::string, int> Item::getStats() { return enhancements_; };
(gdb) step
_Rb_tree_impl (__a=<optimized out>, __comp=..., this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:474
474 _M_header(), _M_node_count(0)
(gdb) step
475 { _M_initialize(); }
(gdb) step
_M_initialize (this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:484
484 this->_M_header._M_left = &this->_M_header;
(gdb) step
485 this->_M_header._M_right = &this->_M_header;
(gdb) step
_Rb_tree (__x=..., this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:674
674 if (__x._M_root() != 0)
(gdb) step
_M_root (this=0x7fffffffd048)
at /usr/include/c++/4.9/bits/stl_tree.h:498
498 { return this->_M_impl._M_header._M_parent; }
(gdb) step
_Rb_tree (__x=..., this=0x7fffffffced0)
at /usr/include/c++/4.9/bits/stl_tree.h:674
674 if (__x._M_root() != 0)
(gdb) step
676 _M_root() = _M_copy(__x._M_begin(), _M_end());
(gdb) step
std::_Rb_tree<std::string, std::pair<std::string const, int>, std::_Select1st<std::pair<std::string const, int> >, std::less<std::string>, std::allocator<std::pair<std::string const, int> > >::_M_copy (
this=this#entry=0x7fffffffced0, __x=0x619f10,
__p=__p#entry=0x7fffffffced8)
at /usr/include/c++/4.9/bits/stl_tree.h:1207
1207 _Link_type __top = _M_clone_node(__x);
... which is gibberish to me. :( It does this infinitely, so I know that it (somehow) describes the hangup.
I've got no clue what's going on here, haha. I'm very new to C++, and have struggled with this since I woke, so for all I know my code is terrible and I should feel bad for writing it.
Any ideas?
In addition to what's already been mentioned, your Node object nonchalantly stores a pointer an object passed from outside by reference
template<class T> LinkedList<T>::Node::Node(T& object)
: object_(&object) {};
However, the reference arguments you pass to the constructor of Node are actually bound to local variables
template<class T> void LinkedList<T>::addObject(T& addedObject) {
Node* node = new Node(addedObject);
node->prev_ = tail_.prev_;
tail_.prev_->next_ = node;
tail_.prev_ = node;
node->next_ = &tail_;
++size_;
};
void Room::addItem(Item item) { itemsInThisRoom_.addObject(item); };
i.e. the reference is bound to parameter item which is a local variable inside addItem.
That local variable item is destroyed as soon as addItem exits. Your Node::object_ pointers remain pointing nowhere.
Considering the amount of gratuitous copying you perform in your code, it is completely unclear how you managed to come up with the idea to store a pointer to a non-owned object inside your Node (instead of gratuitously copying the entire data into the Node, as you do virtually everywhere else).
Anyway, the memory ownership is completely broken in your code, which leads to object lifetime issues as the one above. You need to design some meaningful memory ownership plan from scratch, and then write your code following that plan. What you have now is nonredeemable mess.
If you want to use pointers and you don't think you're ready to untangle this mess, just use smart pointers and let them handle things for you.
P.S. And drop that nasty habit of placing a ; after each and every }.
From template<class T> LinkedList<T>::LinkedList(const LinkedList& srcList)
delete &srcList;
Really? Just removing this line will improve your code. &srcList is not necessarily an address that has been allocated on the heap. And in any case a copy constructor should not be deleting the original.
From template<class T> LinkedList<T>::~LinkedList()
for (unsigned int ii = 1; ii == size_; ++ii)
This loop has no effect unless the size of the list is one, it should be
for (unsigned int ii = 0; ii < size_; ++ii)

how to preserve const correctness across pointers?

I am trying to have a const operation on a class that is truly const - it does not change data that the class points to.
For example:
class Node{
public:
int val;
};
class V{
public:
Node * node; //what is the change that is needed here?
void const_action()const{
node->val=5; //error wanted here
}
void action(){
node->val=5; //error is not wanted here
}
};
You can use a template to enforce the const correctness on a pointer without changing the meaning or the implementation of your class:
template <typename T>
class PreseveConstPointer
{
T *t_;
public:
PreseveConstPointer(T *t = nullptr)
: t_(t)
{
}
PreseveConstPointer<T> * operator=(T *t)
{
t_ = t;
return this;
}
T* operator->()
{
return t_;
}
T const * operator->() const
{
return t_;
}
T * data()
{
return t_;
}
};
class Node{
public:
int val;
};
class V{
public:
PreseveConstPointer<Node> node;
V()
{
node = new Node;
}
~V()
{
if(node.data())
delete node.data();
}
void const_action()const{
node->val=5; // You will get an error here
}
void action(){
node->val=5; // No error here
}
};
const after a function declaration says that the function is not allowed to change any class members (except ones that are marked mutable).
Since your code doesn't change any class member, and only changes the object node points to, both function will compile.
AFAIK there's no way to prevent this. If you mark the node const, neither will compile.
You're confusing Node* const for Node const*.
An [unfortunate?] side effect of using indirection here is that constness of the pointer member has nothing to do with the actual Node on which you're operating.
If you don't need that member to be a pointer, then this is pleasingly easy:
class V
{
public:
Node node;
void const_action() const
{
node.val = 5; // error here
}
void action()
{
node.val = 5; // no error here
}
};
However, given its name, I suspect life is not that simple and you are basically out of luck.