[c++]The importance of dynamic allocation [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I wrote a doubly linked list, and trying to add an append()(insert at the end)and len()(caculate the number of member in the list). I just don't understand why it doesn't work now. Here is the simplest code:
#include<iostream>
using namespace std;
class linkedList{
private:
struct node{
node* last;
node* next;
char* str;
};
node sentinel;
public:
linkedList();
~linkedList();
int len();
void append(char*);
};
linkedList::linkedList(){
sentinel.last=&sentinel;
sentinel.next=&sentinel;
sentinel.str="I am sentinel!!";
};
linkedList::~linkedList(){};
int linkedList::len(){
node* currentNode=&sentinel;
int count=0;
while ((*currentNode).next!=&sentinel){
count++;
currentNode=(*currentNode).next;
cout<<(*currentNode).str<<endl;
}
return count;
}
void linkedList::append(char* str){
node newNode;
newNode.str=str;
newNode.last=sentinel.last;
(*sentinel.last).next=&newNode;
sentinel.last=&newNode;
newNode.next=&sentinel;
}
int main(){
linkedList myList;
myList.append("Hello");
myList.append("World");
int length=myList.len();
cout<<length<<endl;
return 0;
}
What I am doing is just add two new nodes into the linked list, and caculate the total number of my nodes. it should return 2. but why it doesn't work?

newNode in your code below will go out of scope as soon as append is finished executing. Assigning it's memory address as a pointer to more global member is likely going to end in a segfault.
void linkedList::append(char* str){
node newNode;
newNode.str=str;
newNode.last=sentinel.last;
(*sentinel.last).next=&newNode;
sentinel.last=&newNode;
newNode.next=&sentinel;
}
Try allocating your node on the heap using new node, possibly using a shared_ptr to make memory management a bit simpler.
void linkedList::append(char* str){
node *newNode = new node;
newNode->str=str;
newNode->last=sentinel.last;
(*sentinel.last).next=newNode;
sentinel.last=newNode;
newNode->next=&sentinel;
}
With this approach, be sure to cleanup the nodes when destructing your linkedlist, via the delete operator on each node.
Alternatively, look into using shared_ptr's to a Node instead of raw pointers, which will always call delete when the linkedlist (and nobody else) is pointing to the node.

Use the new keyword to allocate a new node:
void linkedList::append(char* str){
node *newNode = new node();
newNode->str=str;
newNode->last=sentinel.last;
(*sentinel.last).next=newNode;
sentinel.last=newNode;
newNode->next=&sentinel;
}

Related

C++ Linked list unit test returns segment fault [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
My algorithm for implementing a linked-list as follows
Function to add a new node and returns location pointer.
One core function to handle adding a node front,end operations.
linkedList.hpp
#include <cstddef>
class LinkedList{
public:
int value {0};
LinkedList* nextNode {NULL};
};
LinkedList* addNewNode(int nodeVal){
LinkedList *newNode;
newNode->value = nodeVal;
newNode->nextNode = nullptr;
return newNode;
}
Below googletest unit-test checks whether
Returned node's pointer is not null.
Returned node has a value.
Returned node's next node value is set to NULL.
linkedListTest.cpp
#include <gtest/gtest.h>
#include "../linkedList.hpp"
int main(int argc, char **argv){
::testing::InitGoogleTest(&argc,argv);
return RUN_ALL_TESTS();
}
class LinkedListTest : public ::testing::Test{
public:
LinkedList *linkedlist = new LinkedList();
virtual void SetUp(){
}
virtual void TearDown(){
delete linkedlist;
}
};
TEST_F(LinkedListTest,addNewNodeReturnsItsNodePointer){
// act
linkedlist = addNewNode(5);
EXPECT_TRUE(linkedlist != nullptr);
ASSERT_EQ(linkedlist->value,5);
EXPECT_TRUE(linkedlist->nextNode != nullptr);
}
When I run this code,tests pass but I get
Segmentation fault
What did I miss here?
newNode in addNewNode was never initialized, so it's a pointer to nowhere:
LinkedList* addNewNode(int nodeVal) {
LinkedList *newNode; // Uninitialized, so undefined
newNode->value = nodeVal; // `->` dereferences the pointer, but it goes nowhere!
One way to initialize it is using heap allocation, i.e., operator new - but remember that you need to manage resources in C++, so you'll need to free it after your done using it.
LinkedList* addNewNode(int nodeVal) {
LinkedList *newNode = new LinkedList();
newNode->value = nodeVal;
newNode->nextNode = nullptr;
Later, to free the memory, you can do something like this:
if (myNode->nextNode != nullptr) {
delete myNode->nextNode;
myNode.nextNode = nullptr;
}
But if you want to delete the whole LinkedList, you'll first have to walk to its end and start deleting from there. If you delete a node before deleting its successor, you create a memory leak bc. you no longer have a pointer to free that memory.
Also make sure to turn your compiler warnings up! Default settings are way too lenient. E.g., for GCC you can use -Wall. Which tells me:
<source>: In function 'LinkedList* addNewNode(int)':
<source>:12:18: warning: 'newNode' is used uninitialized [-Wuninitialized]
12 | newNode->value = nodeVal;
| ~~~~~~~~~~~~~~~^~~~~~~~~
And when you get a segmentation fault (segfault), you should compile your program in debug mode and run it in a debugger. It can tell you where the error happened:
gcc -g -Og -o myprog myprog.c
gdb ./myprog
run
(segfault)
backtrace

Segmentation Fault with declared variables C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am trying to create a node class. The node class has two variables: an int, and a pointer to another node. Here are my node constructors. I found on another stack overflow that in order to allocate memory for values, you need to include a "new ... " phrase.
Node::Node() {
next = new Node;
}
Node::Node(int new_num) {
num = new_num;
next = new Node;
}
I am using a method called AssignArray which takes an array of ints and turns that into a linked list of nodes. Parts of it work, except when I try to use the setNext method on my node. The setNext method is just a regular setter.
void Node::setNext(Node* new_next) {
next = new_next;
}
Node* Node::AssignArray(int list[], int i, int size) {
if (i == size) {
return NULL;
}
else {
Node new_node(list[i]);
i++;
new_node.setNext(new_node.AssignArray(list, i , size));
return &new_node;
}
}
Here is my main function so far:
int main() {
int nums1[] = {1,2,3,4,5};
int nums2[] = {1,3,5,7,9};
Node node1 = Node();
int nums1_size = sizeof(nums1)/sizeof(nums1[0]);
node1.AssignArray(nums1, 0, nums1_size);
The main issue is that you're calling setNext with the return value from AssignArray, which you return as &new_node, which is a pointer to a local Node that you allocated on the stack. As soon as the function returns, the stack unwinds and that Node instance ceases to exist, leaving the pointer dangling.
At the very least you should be doing:
Node* new_node = new Node(list[i]);
...
return new_node;
But I also feel like we're missing some things here. It would be nice to see the definition of Node. And how is this constructor not producing a stack overflow?
Node::Node() {
next = new Node;
}
In the constructor you do new Node which will call this same constructor again... which will call the constructor again...
Hmm.
I think new node added on constructor while infinite loop through itself.
Node::Node() {
next = new Node;
}
It will be better to avoid this type of calling.

Can anyone tell me why my program is going in infinite Loop? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Why my code is giving an Infinite loop and i have checked my code many times and I don't know where the mistake is but my output is 34 in an infinite loop and it is a code for doubly linked list!
So please tell me where the mistake is as well as why my loop is showing 34 instead of 77 in my code and is there any problem in my print function?
#include<iostream>
using namespace std;
struct Node
{
int data;
Node *next;
Node *prev;
};
class Linked
{
public:
Node *head;
Node *tail;
Linked()
{
head=NULL;
tail=NULL;
}
void add(int data,int position)
{
Node *n=new Node;
Node *n1=new Node;
n->data=data;
n->next=NULL;
n->prev=NULL;
if(head==NULL)
{
head=n;
tail=n;
cout<<"Linked list formed"<<endl;
}
if(position==0)
{
head->prev=n;
n->next=head;
head=n;
cout<<"Linked list created"<<endl;
}
else
{
n1=head;
int posi=position;
while(posi>1)
{
n1=n1->next;
posi--;
}
n->next=n1->next;
n->next->prev=n;
n1->next=n;
n->prev=n1;
}
}
void print()
{
Node *n=new Node;
n=head;
while(n!=NULL)
{
cout<<n->data<<endl;
n=n->next;
}
}
};
int main()
{
Linked l;
l.add(34,0);
l.add(77,0);
// l.add(44,1);
// l.add(90,2);
l.print();
return 0;
}
add (data,position) has 2 problems.
For the very first node in Doubly Linked List , once head and tail are pointed to the same node, we are done. Position do not matter, when there is no node.
So stop add logic after "Linked List Formed". Add Else and move rest all code inside, It works as expected.
Code should be able to assert Head-> Prev and Tail-> next to be null.
Also while adding a single new node, you do not want to allocate memory for 2x Nodes.
Do not call new Node () for n1.

Why did my C++mprogram stop working after being compiled? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm a computer science student and have been coding with Java for the past year. Now I'm interested in learning C++. The first program that I wanted to code with C++ is an implementation of stack using linked list, which I have coded before using java. I pretty much have no idea what I'm doing and basically just writing what I thought was right until I got no compile error. So I finally did it, my program got no compile error, but when I ran it, a pop-up appeared saying that my 'Stack.exe has stopped working'
Here's my code:`
#include <iostream>
using namespace std;
class Stack;
class Node;
class Node
{
public:
string element;
Node *next;
Node(string, Node);
};
Node::Node(string element, Node next)
{
this -> element = element;
*(this -> next) = next;
}
class Stack
{
private:
Node *tos;
public:
Stack()
{
tos = NULL;
}
void push(string str)
{
tos = new Node(str, *tos);
}
string peek()
{
return tos->element;
}
string pop()
{
string temp = tos->element;
tos = (tos->next);
return temp;
}
};
int main(void)
{
Stack bob;
bob.push("Wow");
bob.push("Wiw");
cout << bob.peek();
return 0;
}
Can someone tell me what I did wrong? I did it like this because this was how I did it with Java.
Thank you :D
You're dereferencing null or undefined pointers in a couple places. First let's look at your Node constructor:
*(this -> next) = next;
Since next hasn't been defined yet, dereferencing it leads to undefined behavior. In practice, next will point to some random place in memory that you probably don't own, so writing to it will cause a program crash. Your Node constructor should take a pointer to Node as its second parameter instead of taking a Node by value:
Node::Node(string element, Node* next)
: element{element},
next{next}
{}
Note that I've also initialized Node's members instead of default-initializing them and then assigning to them in the constructor's body.
After fixing Node's constructor, you'll also need to fix Stack::push to pass a pointer instead of an object:
void push(string str)
{
tos = new Node(str, tos);
}
Note that even after fixing the crashing problem, you'll still leak memory when you pop from your Stack (or when a Stack is destroyed). You need to delete anything you new, or better yet use std::shared_ptr<Node> instead of raw Node*s.

Why can't i print binary tree? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I created a class binary search tree.
but the problem is when i print the tree it crashes.
i think it can be an endless recursion in function print().
Here is my code
struct node{
node *l,*r;
int data;
};
class BinTree
{
private: node *root;
public:
BinTree(){ root=NULL; }
void add(int a){ add_node(a,root); };
void add_node(int a, node *rot)
{ node *curr; curr=rot;
if(curr==NULL)
{
curr=new node;
curr->data=a;
curr->l=NULL;
curr->r=NULL;
return;
}
if(a>=curr->data) curr=curr->r,add_node(a,curr);
if(a<curr->data) curr=curr->l,add_node(a,curr);
}
void print(){ inorder(root); }
void inorder(node *curr)
{
if(curr->l!=NULL) inorder(curr->l);
cout<<curr->data<<" ";
if(curr->r!=NULL) inorder(curr->r);
}
};
Can anyone help me?
In your add_node method, you never actually assign a value to the root. It should be something like this:
if(curr==NULL)
{
curr=new node;
curr->data=a;
curr->l=NULL;
curr->r=NULL;
root = curr;
return;
}
But, for the future, I have the same advice as Basile - use your compiler and your debugger to your advantange.
Your add_node is broken. If curr is NULL, it creates a new node but it never actually adds it to the existing tree. Thus all additions you make are effectively ignored and the tree stays empty.
The inorder function dereferences curr without checking whether it is NULL, and print calls it without checking whether root is NULL. Thus, your crash most likely is caused by tryin to print out an empty tree and then dereferencing a null pointer.
Learn how to use a debugger. Enable all warnings in the compiler.
On Linux, this means compile with g++ -Wall -g and debug with gdb