Copying a Pointer to Allocated Memory - c++

This is a general programming question, and I hope the answers will offer an alternative approach to the problem rather than a quick fix or hack. I have two objects, each of which has some pointers to allocated memory. I want to copy some internal information from one object to the other. Since the information is significantly large, I just want to copy the pointer. The problem is that when the destructor of the two objects are called, they each call the destructor on the internal information (which is now in both objects). This leads to the destructor being called twice on the same pointer.
Since this is quite a complex scenario, and it wouldn't be practical to show you the whole code. I have devised a simple example to illustrate the root of the problem. The code attaches two pre-existing lists without copying any data. As the output shows, the destructor gets called on the last two nodes multiple times. (Once as K is destroyed and again as L is destroyed, since both lists have a pointer to those nodes).
#include <iostream>
struct Node {
int data;
Node * next;
};
class List {
public:
List(const int);
~List();
void append(const int);
void append(const List&);
void print()const;
private:
Node * head;
Node * tail;
};
List::List(const int x)
{
Node * q = new Node;
q->data = x;
q->next = 0;
head = q;
tail = q;
}
List::~List()
{
while (head != 0){
Node * temp = head->next;
std::cout << "Deleting " << head->data << std::endl;
delete head;
head = temp;
}
}
void List::append(const int x)
{
Node * q = new Node;
q->data = x;
q->next = 0;
tail->next = q;
tail = q;
}
void List::append(const List& L2)
{
this->tail->next = L2.head;
this->tail = L2.tail;
}
void List::print()const
{
for (Node * iter = head; iter; iter=iter->next){
std::cout << iter->data << " ";
}
std::cout << std::endl;
}
int main()
{
List L = List(1);
L.append(3);
std::cout << "List L:\n";
L.print();
List K = List(5);
K.append(10);
std::cout << "List K:\n";
K.print();
L.append(K);
std::cout << "List L:\n";
L.print();
}
The output is:
List L:
1 3
List K:
5 10
List L:
1 3 5 10
Deleting 5
Deleting 10
Deleting 1
Deleting 3
Deleting 0
Deleting 39125056

Instead of using a raw pointer to your nodes, use std::shared_ptr<Node> and remove the explicit delete from your destructor. A shared pointer will keep the Node in memory as long as there is a shared_ptr instance pointing to it in scope. When there are no longer any shared_ptr instances pointing to a Node, the Node will be automatically deleted.

In the main function, you declared two local variable L, K, they will be deconstructed before program exists.
In your code, you're append the list K to list L, when deconstructing, K is deconstructed first, as the K still holds the pointer the Nodes 1,3, which means this nodes will be free. But the Node 3 in L still holds the pointer to K's head, that's how the error happens.
Put breakpoints in the deconstructors, you'll find out how it occurs.

Using std::shared_ptr instead of raw pointers will solve your problem.
Here's your code converted to use std::shared_ptr.
#include <iostream>
#include <memory>
struct Node {
int data;
std::shared_ptr<Node> next;
Node(int d) : data(d), next(nullptr) {}
};
class List {
public:
List(const int);
~List();
void append(const int);
void append(const List&);
void print()const;
private:
std::shared_ptr<Node> head;
std::shared_ptr<Node> tail;
};
List::List(const int x)
{
Node * q = new Node(x);
head.reset(q);
tail = head;
}
List::~List()
{
}
void List::append(const int x)
{
Node * q = new Node(x);
tail->next.reset(q);
tail = tail->next;
}
void List::append(const List& L2)
{
this->tail->next = L2.head;
this->tail = L2.tail;
}
void List::print()const
{
for (std::shared_ptr<Node> iter = head; iter.get() != nullptr; iter=iter->next){
std::cout << iter->data << " ";
}
std::cout << std::endl;
}
int main()
{
List L = List(1);
L.append(3);
std::cout << "List L:\n";
L.print();
List K = List(5);
K.append(10);
std::cout << "List K:\n";
K.print();
L.append(K);
std::cout << "List L:\n";
L.print();
}
The output:
List L:
1 3
List K:
5 10
List L:
1 3 5 10
Update
A bare bones implementation of the std::share_ptr functionality:
template <typename T>
struct SharedPtr
{
SharedPtr() : dataPtr(new Data(nullptr)) {}
SharedPtr(T* n): dataPtr(new Data(n)) {}
SharedPtr(SharedPtr const& copy) : dataPtr(copy.dataPtr)
{
dataPtr->useCount++;
}
~SharedPtr()
{
dataPtr->useCount--;
if ( dataPtr->useCount == 0 )
{
delete dataPtr;
}
}
void reset(T* n)
{
dataPtr->useCount--;
if ( dataPtr->useCount == 0 )
{
delete dataPtr;
}
dataPtr = new Data(n);
}
T* get() const
{
return dataPtr->n;
}
T* operator->() const
{
return get();
}
SharedPtr& operator=(SharedPtr const& rhs)
{
if ( this != & rhs )
{
dataPtr->useCount--;
if ( dataPtr->useCount == 0 )
{
delete dataPtr;
}
dataPtr = rhs.dataPtr;
dataPtr->useCount++;
}
return *this;
}
struct Data
{
Data(T* in) : n(in), useCount(1) {}
~Data() { if ( n != nullptr ) delete n; }
T* n;
size_t useCount;
};
Data* dataPtr;
};

Related

Singly linked list with unique_ptr

I am trying to use smart pointers (std::unique_ptr) to create a singly linked list. Here is an example of a singly linked list with raw pointer.
struct Node {
int data;
Node *next = nullptr;
Node(int data) : data{data}, next{nullptr} {}
~Node() { std::cout << "Destroy node with data: " << data << '\n'; }
};
void print_list(Node *head) {
while (head != nullptr) {
cout << head->data << " --> ";
head = head->next;
}
cout << "nullptr" << std::endl;
}
void insert(Node *&head, int data) {
Node *new_node = new Node{data};
new_node->next = head;
head = new_node;
}
int main(int argc, char *argv[]) {
Node *head = nullptr;
for (int i = 0; i < 5; ++i) {
insert(head, i);
}
print_list(head);
return 0;
}
The output is:
4 --> 3 --> 2 --> 1 --> 0 --> nullptr
Apparently there is memory leak in the above code (destructor is not called). Now I want to use smart pointer to achieve the same thing:
struct Node {
int data = 0;
std::unique_ptr<Node> next;
Node(int data) : data{data}, next{nullptr} {}
~Node() { std::cout << "Destroy node with data: " << data << '\n'; }
};
void print_list(std::unique_ptr<Node> head) {
while (head != nullptr) {
std::cout << head->data << " --> ";
head = std::move(head->next);
}
std::cout << "nullptr" << std::endl;
}
void insert(std::unique_ptr<Node> &&head, int data) {
std::unique_ptr<Node> new_node{std::make_unique<Node>(data)};
new_node->next = std::move(head);
head = std::move(new_node);
}
// g++ -std=c++17 -Wall 2_1.cpp && ./a.out
int main(int argc, char *argv[]) {
std::unique_ptr<Node> head{nullptr};
for (int i = 0; i < 5; ++i) {
insert(std::move(head), i);
}
print_list(std::move(head));
return 0;
}
The output is:
4 --> Destroy node with data: 4
3 --> Destroy node with data: 3
2 --> Destroy node with data: 2
1 --> Destroy node with data: 1
0 --> Destroy node with data: 0
nullptr
We can observe that the life time of new_node ends when insert() returns. I would like to know if it's possible to use smart pointers to achieve singly linked list and retains the functions interface as above.
First thing, there is a problem with your print_list implementation(for both version for unique_ptr only). With your print_list, every time you assign head with a different uniq_ptr, you are actually deallocating the only Node in head, which is not desired. Instead, in your print_list, you should first create a temporary pointer pointing to head, then only iterate on the temporary pointer.
Now onto your unique_ptr version, you don't have to pass a unique_ptr as rvalue reference, you can also pass it as lvalue reference. Instead, your function signature would probably look like:
void print_list(const std::unique_ptr<Node>& head);
void insert(std::unique_ptr<Node> &head, int data);
This allow you to call them without using std::move in your main.
Now on to definitions. For your insertion, what you have is you first create a new Node with the given value, then you assign the old head to new node's next, and make the new node as the new head:
void insert(std::unique_ptr<Node> &head, int data)
{
// Use `auto` to avoid typing `....<Node>` twice
auto new_node = std::make_unique<Node>(data);
new_node->next = std::move(head);
head = std::move(new_node);
}
Alternatively, you can also add one more parameter to Node's constructor:
Node(int data, std::unique_ptr<Node>&& next = nullptr)
: data{data}, next{std::move(next)}
{}
Now you can simply create new_node like:
void insert(std::unique_ptr<Node> &head, int data)
{
// No need to assign `Node::next` separately
auto new_node = std::make_unique<Node>(data, std::move(head));
head = std::move(new_node);
}
Or even assign the new node to head directly:
void insert(std::unique_ptr<Node> &head, int data)
{
head = std::make_unique<Node>(data, std::move(head));
}
For print_list, we should first create a temporary pointer that points to the underlying object of head, then iterate the list by assigning the temporary pointer to its next object's underlying object:
void print_list(const std::unique_ptr<Node>& head)
{
// Create a pointing to the underlying object
// You can use `.get()` to get the underlying pointer
auto current = head.get();
// No need to explicit compare pointer types to `nullptr`
while (current) {
std::cout << current->data << " --> ";
// Make `current` point to the next underlying object
current = current->next.get();
}
std::cout << "nullptr" << std::endl;
}
Now your main would look like:
int main(int, char *[]) {
std::unique_ptr<Node> head;
for (int i = 0; i < 5; ++i) {
insert(head, i);
}
print_list(head);
return 0;
}
Demo

C++ - linked list - copy constructor

I am trying to implement copy constructor and I have strange problem.
Could you point what I am doing wrong?
I get:
double free or corruption (out): 0x08936a48
Wrong output:
Constructor called...
MyList:
10 --> 20 --> 30 --> 40 -->
MyList2:
10 --> 20 --> 30 --> 40 -->
Destructor called...
Code:
#include <iostream>
template <typename T>
class SingleLinkedList{
protected:
struct Node{
T data;
Node * next;
Node() : next(nullptr) {}
Node(const T num) : data(num), next(nullptr) {}
};
private:
Node * head;
Node * tail;
public:
SingleLinkedList(); // constructor
~SingleLinkedList(); // destructor
SingleLinkedList(const SingleLinkedList &object); // copy constructor
SingleLinkedList& operator=(const SingleLinkedList &object); // copy assignment
void insert(T const& value);
void displayList(std::ostream& stream = std::cout) const;
template <typename T>
SingleLinkedList<T>::SingleLinkedList() : head(nullptr), tail(nullptr){
std::cout << "Constructor called..." << std::endl;
}
template <typename T>
SingleLinkedList<T>::~SingleLinkedList(){
std::cout << "Destructor called..." << std::endl;
int index = 1;
Node * temp = nullptr;
while(head!=nullptr){
temp = head;
head = head->next;
delete temp;
//std::cout << "Node number: " << index << " destroyed" << std::endl;
index++;
}
}
template <typename T>
SingleLinkedList<T>::SingleLinkedList(const SingleLinkedList<T> &oldList){
SingleLinkedList<T> * newList = new SingleLinkedList<T>();
// is it necessary? my constructor by default initializes head and tail with nulls
head = nullptr;
tail = nullptr;
Node * temp = nullptr;
temp = oldList.head;
while(temp!=nullptr){
newList->insert(temp->data);
temp = temp->next;
}
}
template <typename T>
void SingleLinkedList<T>::insert(T const& value){
Node * temp = new Node(value);
//temp->data = value;
//temp->next = nullptr;
if(head==nullptr){
head = temp;
tail = temp;
}
else{
tail->next = temp;
tail = temp;
}
}
template <typename T>
void SingleLinkedList<T>::displayList(std::ostream& stream) const{
Node * temp = nullptr;
temp = head;
while(temp!=nullptr){
stream << temp->data << " --> ";
temp = temp->next;
}
stream << std::endl;
}
int main(){
SingleLinkedList<int> * myList = new SingleLinkedList<int>();
SingleLinkedList<int> * myList2 = myList;
myList->insert(10);
myList->insert(20);
myList->insert(30);
myList2->insert(40);
std::cout << "MyList:" << std::endl;
myList->displayList();
std::cout << "MyList2:" << std::endl;
myList2->displayList();
delete myList;
delete myList2;
return 0;
}
My "algorithm":
1. Create new list.
2. For each node of old list get data and insert it to new list.
I don't understand how using two different list I am deallocating the same part of memory.
I am a student, not pro. I am asking for your understanding.
Your copy ctor is really strange. Instead of adding elements to the list being constructed, you create a new list (why?) and then add elements to it. After that, you simply exit function. The new list created is left on the heap unreachable, i.e. leaked, and the list constructed remains empty.
Can you simply insert copied list's elements, not in a some newList, but in this one?
Double deletion happens for another reason: in your main you declare two pointers, myList and myList2, that both point to the same list in memory, and later try to delete them both. You can quickfix that by properly constructing myList2:
SingleLinkedList<int> * myList2{new SingleLinkedList<int>(*myList)};
but I suggest you get rid of pointers at all in your main:
SingleLinkedList<int> myList;
SingleLinkedList<int> myList2(myList);
(And don't forget to change all ->s into .s below afterwards.)
This is not Java after all, not every lifetime starts with new.

Template classes in c++, list example

i'm trying to make a template class for a list in c++. This is something new for me, and i'm stuck. I've written add(T item) method and write() to write whole list on console, but i have random int as output.
Here's my code, if someone could tell me where my mistake is, i will be grateful.
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
template <class T> class Node {
private:
Node<T> * next;
Node<T> * prev;
T key;
public:
Node(T k) {
next =(Node *) malloc(sizeof(Node));
prev = (Node *)malloc(sizeof(Node));
key = k;
}
Node(T * n, T * p, T k) {
next = n;
prev = p;
key = k;
}
void setNext(Node<T> * n) {
next = n;
}
void setPrev(Node<T> * p) {
prev = p;
}
void show() {
cout << "key= " << key << endl;
}
};
template <class T> class List {
private:
Node<T> * head;
Node<T> * tail;
public:
List() {
head = nullptr;
tail = nullptr;
cout << "list created!" << endl;
}
void add(T item) {
Node<T> node(item);
node.setNext(head);
node.setPrev(nullptr);
if (head != nullptr)
head = &node;
else {
tail = &node;
}
head = &node;
}
void write() {
head->show();
}
};
int main()
{
List<int> lista;
lista.add(8);
lista.write();
return 0;
}
Your add() add a pointer to a Note<T> (node) in the list; but node is destroied when add() ends the execution.
So, when you call write(), that use show(), the pointed memory in undefined (random value).
To avoid this problem, you have to allocate the variable (with new! avoid malloc() with classes), so
Node<T> * nodePnt = new Node<T>(item);
and
head = nodePnt;
tail = nodePnt;
But remeber to delete it.

Traversing custom made list

I've been given a class declaration (create a list with nodes) in C++ that I need to define and I'm having trouble with one of the member functions: void print() const;
Question: How can I go about traversing and printing out the first->value's without removing const in the function declaration i.e. altering first? The function below yields an error: expression must be a modifiable lvalue.
Class declaration (only details of relevance)
class List {
public:
.
.
.
void print() const;
int size();
void add(int d);
private:
int sz = 0;
struct Node {
int value;
Node* next;
Node(int v, Node* n) : value(v), next(n) {}
};
Node* first; // pointer to the first node
};
Class definition (only details of relevance)
void List::print() const {
while (first != NULL) {
cout << first->value << endl;
first = first->next;
}
}
int List::size() const {
return sz;
}
void List::add(int d) {
if (size == 0)
first = new Node(d, NULL), sz++;
else {
Node* newnode = new Node(first->value, first->next);
first = new Node(d, newnode);
sz++;
}
}
Thanks for your time
The trick is to make a copy of first and only modify the copy: (not tested)
Node* firstCopy = first;
while (firstCopy != NULL) {
cout << firstCopy->value << endl;
firstCopy = firstCopy->next;
}

C++: Copy constructor is deleting nodes in original object

I have implemented a singly linked list using a template class and attempted to create a working copy constructor. When the copy constructor is called, it accurately duplicates the list. However, it deletes nodes from the original.
Here is the class implementation, the constructors, and the destructors:
template<class L>
class LinkedList
{
public:
LinkedList();
LinkedList(const LinkedList<L> &og);
~LinkedList();
Node<L>* AddToEnd(L object);
Node<L>* AddToMiddle(L object);
Node<L>* DeleteNode(L deleteItem);
Node<L>* ReverseList();
void Display();
int Size();
private:
Node<L>* head;
Node<L>* tail;
int size;
};
template<class L>
LinkedList<L>::LinkedList()
{
head = NULL;
tail = NULL;
size = 0;
}
template<class L>
LinkedList<L>::LinkedList(const LinkedList<L> &og)
{
cout << "\nCopy constructor has been called.\n\n";
head = new Node<L>;
*head = *og.head;
tail = new Node<L>;
*tail = *og.tail;
size = og.size;
}
template<class L>
LinkedList<L>::~LinkedList()
{
delete head;
delete tail;
}
And main.cpp:
#include "Header.h"
int main()
{
int int1 = 1;
int int2 = 2;
int int3 = 3;
int int4 = 4;
int int5 = 5;
cout << "Creating the first integer list..." << endl;
LinkedList<int> intList1;
intList1.AddToEnd(int1);
intList1.AddToEnd(int2);
intList1.AddToEnd(int3);
intList1.AddToEnd(int4);
intList1.AddToEnd(int5);
intList1.Display();
cout << endl << "Cloning and reversing..." << endl;
LinkedList<int> intList2(intList1);
intList2.ReverseList();
cout << "Original list: " << endl;
intList1.Display();
cout << "Reversed list: " << endl;
intList2.Display();
return 0;
}
The output looks like this:
Creating the first integer list...
1
2
3
4
5
Cloning and reversing...
Copy constructor has been called.
Original list:
1
2
1
Reversed list:
5
4
3
2
1
Your copy constructor is totally wrong. You should iterate through the linked list and copy each element of that list. Also your tail should point to the last element of the list.
So the code would be something like this.
template<class L>
LinkedList<L>::LinkedList(const LinkedList<L> &og)
{
cout << "\nCopy constructor has been called.\n\n";
head = new Node<L>;
*head = *og.head;
Node *p = og.head->next;
Node *i = head;
while (p != NULL) {
i->next = new Node<L>;
*(i->next) = *p;
p = p->next;
i = i->next;
}
tail = i;
size = og.size;
}
Your copy constructor definition needs to do more than what it is doing now.
Right now what you are doing is just duplicating the head and tail pointers, which is not enough. This way, your cloned list is essentially the same as first list. What you need to do is duplicate every node, something like:
for (Node<L>* n = og.first(); n != NULL ; n = n->next()) {
this->AddToEnd(n->value());
}
Additionally, your destructor is not cleaning up properly. You probably want to delete all the nodes you may have added.
Have your copy-constructor iterate through the nodes in og's list and append them to your list:
template<class L>
LinkedList<L>::LinkedList(const LinkedList<L> &og)
: head(NULL)
, tail(NULL)
{
for (Node* p(og.head); p != NULL; p = p->next)
{
AddToEnd(p->value);
}
}
Where value is the datum that a Node contains.
Your destructor is also incorrect. It should iterate through the list and delete the nodes one by one. Deleting only head and tail will cause the entire list to be lost if there are more elements:
template<class L>
LinkedList<L>::~LinkedList()
{
while (head)
{
Node<L>* temp(head);
head = head->next;
delete temp;
}
}