Two functions, one is to create a link list, the other is to free the link list.
If the Create function return a double pointer to the head node, use this node to free the link list, will encounter a segment error. But if changing the Create function to return a pointer to head node, then free the list, this will be OK.
Anyone who can explain this for me? Here is the code which have the segment errors:
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode{
int m_nValue;
ListNode* m_pNext;
}ListNode;
ListNode** CreateList(int data[], int length){
if(length<=0 || data == NULL)
return NULL;
ListNode *pHead = (ListNode*)malloc(sizeof(ListNode));
ListNode *pNode = pHead;
pNode->m_pNext = NULL;
pNode->m_nValue = data[0];
int i=1;
for(; i<length; i++){
ListNode *temp = (ListNode*)malloc(sizeof(ListNode));
temp->m_nValue = data[i];
temp->m_pNext = NULL;
pNode->m_pNext = temp;
pNode = temp;
}
return &pHead;
}
void FreeList(ListNode **pHead){
ListNode *pNode;
while(pHead!=NULL && *pHead!=NULL){
pNode = *pHead;
*pHead = pNode->m_pNext; // here will encounter an error;
free(pNode);
}
pHead = NULL;
}
int main(){
int data[] = {1,2,3,4,5};
ListNode **pHead = CreateList(data, sizeof(data)/sizeof(int));
FreeList(pHead);
}
But if I change the CreateList's return type to ListNode* CreateList(...), this will work well.
ListNode* CreateList(int data[], int length){
if(length<=0 || data == NULL)
return NULL;
ListNode *pHead = (ListNode*)malloc(sizeof(ListNode));
ListNode *pNode = pHead;
pNode->m_pNext = NULL;
pNode->m_nValue = data[0];
int i=1;
for(; i<length; i++){
ListNode *temp = (ListNode*)malloc(sizeof(ListNode));
temp->m_nValue = data[i];
temp->m_pNext = NULL;
pNode->m_pNext = temp;
pNode = temp;
}
return pHead;
}
int main(){
int data[] = {1,2,3,4,5};
ListNode *pHead = CreateList(data, sizeof(data)/sizeof(int));
FreeList(&pHead);
}
In ListNode** CreateList(int data[], int length) approach you are returning pointer to a local variable, which clearly goes invalid when the function returns.
That is, you declare a pointer variable ListNode* pHead in CreateList function and you return address of the variable pHead. The pointer variable pHead is stored in stack and when the CreateList function returns the stack is unwinded memory used to stored pHead is freed eventhough the memory pointed to by pHead is still availalbe on heap.
Related
I need to make a simple program with linked lists but my code just stops running.
Down below are to codes, first is the main .cpp file, and the second is header where the problematic function is defined. The code stops when it comes to assigning "new_" pointer attributes (marked with arrows). The function, as its name says, need to generate a linked list from an array, and return the head of that list.
I am using dev c++ for compiling, and he is not throwing any error or warning.
<main.cpp>
#include<stdio.h>
#include"LinkedList2.h"
int main(){
node *head;
int A[] = {2,8,12,9,7};
int n = sizeof(A) / sizeof(A[0]);
head = CreateListFromArray(A, n);
PrintList(head);
return 0;
}
<LinkedList2.h>
#include<stdio.h>
typedef struct node_{
int x;
struct node_ *next;
}node;
node* CreateListFromArray(int A[], int n){
node *head = NULL, *tmp = head, *new_;
for(int i = 0; i < n; i++){
new_->next = NULL; // <------
new_->x = A[I]; // <------
tmp->next = new_;
tmp = tmp->next;
}
return head;
}
void PrintList(node *head){
for(node *tmp = head; tmp != NULL; tmp = tmp->next) printf("%d ", tmp->x);
}
you need to allocate memory for each new node
node* CreateListFromArray(int A[], int n){
node *head = NULL, *tmp = head;
for(int i = 0; i < n; i++){
node *new_ = new node():
new_->next = NULL; // <------
new_->x = A[I]; // <------
tmp->next = new_;
tmp = tmp->next;
}
return head;
}
you also dont have a valid head pointer either, i leave that for you to sort out
note in c++ you dont need typedef any more.
you also have to change A[I] to A[i], because I doesn't exist
when I tried to implement a linked list in visual studio 2019 using c it produces heap error.
It was due to the free function.
However, the code works fine on online compilers which use the GCC compiler. https://www.jdoodle.com/c-online-compiler/
I can't able to figure it out..........................
here is the code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node* head = NULL;
void append(int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
(*newNode).data = data;
(*newNode).next = NULL;
if (head == NULL)
{
head = newNode;
return;
}
struct Node* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode;
}
void insertAt(int position, int data)
{
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
newNode->data = data;
newNode->next = NULL;
if (position == 1)
{
newNode->next = head;
head = newNode;
return;
}
struct Node* temp = head;
for (int i = 1; i < position - 1; i++)
{
temp = temp->next;
}
newNode->next = temp->next;
temp->next = newNode;
}
void deleteAt(int position)
{
struct Node* temp = NULL;
if (position == 1)
{
temp = head;
head = temp->next;
free(temp);
return;
}
struct Node* tempHead = head;
for (int i = 1; i < position - 1; i++)
{
tempHead = tempHead->next;
}
temp = tempHead->next;
tempHead->next = temp->next;
free(temp);
}
void print()
{
struct Node* temp = head;
while (temp != NULL)
{
printf("%d\n", temp->data);
temp = temp->next;
}
}
void main()
{
append(3);
append(4);
append(5);
append(6);
insertAt(3, 20);
insertAt(4, 50);
insertAt(2, 70);
deleteAt(4);
deleteAt(3);
print();
}
The sizes you're passing to malloc are wrong. You should pass sizeof(struct Node).
If you're compiling this as C++ you shouldn't be using malloc at all.
As #1201ProgramAlarm answered, the allocation size is wrong. sizeof(struct Node*) is the size of a pointer, not the size of the struct.
Instead of trying to match the type, use the size of the referenced data. Easy to code right, review and maintian.
Cast not needed in C.
// struct Node* newNode = (struct Node*)malloc(sizeof(struct Node*));
// instead...
// ptr = malloc(sizeof *ptr * N);
struct Node* newNode = malloc(sizeof *newNode);
Just try this code once down there .This code is written by me according to my understanding and still if u have any issue with the code you can further ask me .You can try this code out or just cross check it with your's.
Code:
Linked List:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
}*first=NULL;
void create(int A[],int n)
{
int i;
struct Node *t,*last;
first=(struct Node *)malloc(sizeof(struct Node));
first->data=A[0];
first->next=NULL;
last=first;
for(i=1;i<n;i++)
{
t=(struct Node*)malloc(sizeof(struct Node));
t->data=A[i];
t->next=NULL;
last->next=t;
last=t;
}
}
void Display(struct Node *p)
{
while(p!=NULL)
{
printf("%d ",p->data);
p=p->next;
}
}
void RDisplay(struct Node *p)
{
if(p!=NULL)
{
RDisplay(p->next);
printf("%d ",p->data);
}
}
int Delete(struct Node *p,int index)
{
struct Node *q=NULL;
int x=-1,i;
if(index < 1 || index > count(p))
return -1;
if(index==1)
{
q=first;
x=first->data;
first=first->next;
free(q);
return x;
}
else
{
for(i=0;i<index-1;i++)
{
q=p;
p=p->next;
}
q->next=p->next;
x=p->data;
free(p);
return x;
}
}
int main()
{
int A[]={10,20,30,40,50};
create(A,5);
printf(“%d\n",Delete(first),2);
Display(first);
return 0;
}
In main function you can pass the function created int the program and also pass the argument according to you.
I have a linked list in C++, after inserting several nodes now I see that all of them are the same, although I'm using different values to add to node each time, but it's like all of them are the same, even when trying to change a node all of them are changing together or it's the same node that is always being returned, I don't know.
class node
{
public:
int ochance = 3;
string question;
string option1;
int peopleeffectop1;
int courteffectop1;
int treasuryeffectop1;
string option2;
int peopleeffectop2;
int courteffectop2;
int treasuryeffectop2;
node *next;
};
class list
{
private:
node *head, *tail;
public:
list()
{
head=NULL;
tail=NULL;
}
void createnode(int value , string q , string ans1 , int ans1ef1 , int ans1ef2, int ans1ef3 , string ans2, int ans2ef1 , int ans2ef2, int ans2ef3 )
{
node *temp = new node;
temp->ochance = value;
temp->question = q;
temp->option1 = ans1;
temp->peopleeffectop1 = ans1ef1;
temp->courteffectop1 = ans1ef2;
temp->treasuryeffectop1 = ans1ef3;
temp->option2 = ans2;
temp->peopleeffectop2 = ans2ef1;
temp->courteffectop2 = ans2ef2;
temp->treasuryeffectop2 = ans2ef3;
temp->next = NULL;
if(head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
node getnth(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
return *tmp;
}
i++;
tmp = tmp->next;
}
}
int getlen()
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
i++;
tmp = tmp->next;
}
return i;
}
void minus(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
tmp->ochance -=1;
}
i++;
tmp = tmp->next;
}
}
void delete_first()
{
node *temp = new node;
temp = head;
head = head->next;
delete temp;
}
void delete_last()
{
node *current = new node;
node *previous = new node;
current = head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous;
previous->next = NULL;
delete current;
}
void delete_position(int pos)
{
node *current = new node;
node *previous = new node;
current = head;
for(int i = 1; i < pos; i++)
{
previous = current;
current = current->next;
}
previous->next = current->next;
}
};
For starters many member functions has a memory leak as for example in this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
//
At first memory was allocated and its address was stored in the pointer tmp and then the pointer is reassigned. As a result the address of the allocated memory is lost and the memory is not deleted.
These statements
node* tmp = new node;
tmp= head;
must be substituted for this one statement
node* tmp = head;
Moreover this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
int i =0 ;
while(tmp!=NULL){
if (i=pos) {
return *tmp;
}
i++;
tmp = tmp->next;
}
}
has undefined behavior in case when pos is higher than there are nodes in the list. In this case the function returns nothing.
In the function minus there is used the assignment operator instead of the comparison operator
while(tmp!=NULL){
if (i=pos) {
^^^^^
In this function
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
there is no check whether head is equal to NULL and tail is not adjusted if it is point to the first node.
The same problems are also in the function delete_last only that instead of the adjacent of the tail node as in the previous function you have to adjust the head node.
This function delete_position has the same drawbacks as the previous functions but also it has a bug in the loop
for(int i=1;i<pos;i++)
A node at position 1 will never be deleted.
I want to generate the list and print the val by
#include<iostream>
#include<vector>
using namespace std;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
struct ListNode{
int val;
ListNode *next;
ListNode(int x) :val(x), next(NULL){
}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
}
};
ListNode* geneate_list(vector<int> data){
ListNode *p1, *p2;
if (data.size() <= 0){
p1 = (ListNode*)malloc(sizeof(ListNode));
return p1;
}
/*ListNode *p1, *p2;*/
ListNode head(data[0]);
p2 = &head;
for (int i = 1; i < data.size(); i++){
p1 = (ListNode*)malloc(sizeof(ListNode));
p1->val = data[i];
p1->next = NULL;
p2->next = p1;
p2 = p1;
}
return &head;
}
int main(){
vector<int> data = {1,2,3,4,5,6};
ListNode* head = geneate_list(data);
ListNode * g = head;
while (head!=NULL){
cout << head->val;
head = head->next;
}
return 0;
}
then I find ,when cout ,the head's address change totally.
before
after
So,anyone can explain this?thx
The generate_list function is wrong for several reasons:
You return the address of a local variable which yields in undefined behaviour. Google return the address of a local variable for more details.
If you pass an empty vector to generate_list, the content of the head of the newly generated list is not initialized. But anyway as the list is empty, you cannot have a head anyway. What would val contain? Therefore generate_list must return NULL for an empty vector.
You are using malloc for allocating an object with a constructor. The constructor of ListNode will therefore never be called (although this constructor is not very useful here).
You want something like this:
ListNode* geneate_list(vector<int> data) {
ListNode *head = NULL;
ListNode *previous = NULL;
for (int i = 0; i < data.size(); i++) {
ListNode *p = new ListNode(0);
if (i == 0)
head = p;
p->val = data[i];
p->next = NULL;
if (previous)
previous->next = p;
previous = p;
}
return head;
}
Disclaimer: this a more or less a C function as close as possible to the original function. In C++ you would do this differently.
I'm implementing a stack with a linked list for review. My pop function isn't working correctly. I created a test with the nodes in main doing the exact same thing my linkedList function is doing but I'm getting a segmentation fault ever time time. Here is the code.
#include <iostream>
struct Node{
int data;
Node* next;
};
class Stack{
private:
Node head;
int size;
public:
Stack();
~Stack();
int getSize();
void push(int val);
int pop();
void printStack();
};
Stack::Stack(){
head.data = 0;
head.next = NULL;
}
Stack::~Stack(){
}
int Stack::getSize(){
return size;
}
void Stack::push(int val){
Node newNode;
newNode.data = val;
if(size == 0) newNode.next = NULL;
else newNode.next = head.next;
head.next = &newNode;
size++;
}
int Stack::pop(){
int returnVal = head.next->data;
head.next = head.next->next;
return returnVal;
}
}
int main(){
Stack s;
s.push(8);
s.push(30);
s.push(40);
int value = s.pop();
int value2 = s.pop(); //segmentation fault
std::cout<<value<<"\n"<<value2<<"\n";
/* This works correctly
Node head;
head.data = 0;
head.next = NULL;
Node n1;
n1.data = 5;
n1.next = NULL;
head.next = &n1;
Node n2;
n2.data = 8;
n2.next = head.next;
head.next = &n2;
Node n3;
n3.data = 30;
n3.next = head.next;
head.next = &n3;
int value = head.next->data;
std::cout << value << "\n";
head.next = head.next->next;
value = head.next->data;
std::cout << value << "\n";
*/
return 1;
}
The problem is how you create the Node. In your case you create a local variable, which only exists within the scope of the function push(). You could use something like this.
void Stack::push(int val){
Node* newNode = new Node;
newNode->data = val;
/* ... */
}
Edit: added a version of the stack (by no means complete)
#include <iostream>
struct Node{
int data;
Node* next;
};
class Stack {
private:
Node* head;
int size;
public:
Stack();
~Stack();
int getSize();
void push(int val);
int pop();
void printStack();
};
Stack::Stack() : head(0), size(0)
{
}
Stack::~Stack(){
}
int Stack::getSize(){
return size;
}
void Stack::push(int val){
Node* newNode = new Node;
newNode->data = val;
newNode->next = head;
head = newNode;
size++;
}
int Stack::pop(){
if(head != 0)
{
int val = head->data;
Node* tmp = head;
head = head->next;
tmp->next = NULL;
delete tmp;
size--;
return val;
}
else
{
return -1; // what happens if stack is empty ?
}
}
void Stack::push(int val){
Node newNode;
newNode is declared to be a local object in automatic scope of the push() function.
Which means that when push() returns, this object is going to get automatically destroyed. That's what "automatic scope" means.
The code in push() attempts to insert this object into your stack, and assumes that this object will exist after push() returns. This, of course, isn't true, and this ends up corrupting memory, resulting in undefined behavior.
This is not how object lifetime and scope works, fundamentally, in C++.
I think both your push() and pop() methods have problems. You can try using these versions:
// create new node, point it to current head, and then assign it as new head
void Stack::push(int val){
Node* newNode = new Node;
newNode->data = val;
newNode->next = head; // OK even if head == NULL
head = newNode;
size++;
}
// retrieve value from head (if it exists), pop the head and return the value
int Stack::pop(){
if (head == NULL) return -1; // -1 indicates empty stack
int returnVal = head->data; // get popped value
Node* temp = &head;
head = head->next; // pop the top of the stack
delete temp;
size--;
return returnVal;
}
There's a problem in your code for push, actually:
void Stack::push(int val){
Node newNode;
newNode.data = val;
if(size == 0) newNode.next = NULL;
else newNode.next = head.next;
head.next = &newNode;
size++;
}
When you write
Node newNode;
you're declaring the Node object with automatic storage duration (you sometimes hear this called "on the stack"). This Node only exists as long as the push function is running, and as soon as the function returns the node ceases to exist. Trying to use that node later results in undefined behavior, which in practice could be anything from an outright crash to reading back garbage data.
To address this issue, you'll need to use dynamic allocation. Create the node using new Node and store a pointer to it. Objects created this way live until something explicitly destroys them, which means that they'll live after the push call finishes. You'll then need to adjust pop to deallocate the memory.