Search code examples
c++linked-liststack-smash

C++ stack smashing detected error


I am starting a personal project incorporating a linked list in C++ and I get a stack smashing detected error, however the program always runs all the way through. I don't believe the error has to do with the Account class I created, I did some basic testing and it seems to work fine. The error is most likely with the linked list.

Also I am just beginning to code in C++ so if you notice any coding style things I could improve on feel free to let me know.

Please explain why I am getting the stack smashing error and how to fix it.

Here is the code:

main.cpp-

#include <iostream>
#include <string>
#include "../include/Account.h"
#include "../include/LinkedList.h"

using namespace std;

int main() {
    Account a("Sue Jones", 003, 0.01, 10000);
    Account b("John Smith", 001, 0.01, 5783);
    LinkedList l;
    l.addNode(a);
    l.addNode(b);
    l.printList();
    l.deleteNode(a.getID());
    l.printList();
    l.deleteNode(b.getID());
    l.printList();
    return 0;
}

LinkedList.h-

#ifndef LINKEDLIST_H
#define LINKEDLIST_H

#include "Account.h"

class LinkedList {
    private:
        typedef struct node {
            Account data;
            node *next;
        }* nodePtr;

        nodePtr head;
        nodePtr curr;
        nodePtr temp;

    public:
        LinkedList();
        void addNode(Account add);
        void deleteNode(int delID);
        void printList();
};

#endif

LinkedList.cpp-

#include <iostream>
#include <cstdlib>
#include "../include/LinkedList.h"

using namespace std;

LinkedList::LinkedList() {
    head = NULL;
    curr = NULL;
    temp = NULL;
}

void LinkedList::addNode(Account add) {
    nodePtr n;
    n->next = NULL;
    n->data = add;

    if(head != NULL) {
        curr = head;
        while(curr->next != NULL) {
            curr = curr->next;
        }
        curr->next = n;
    }
    else {
        head = n;
        curr = n;
    }
}

void LinkedList::deleteNode(int delID) {
    temp = head;
    curr = head;
    while(curr != NULL && curr->data.getID() != delID) {
        temp = curr;
        curr = curr->next;
    }
    if(curr != NULL) {
        if(curr == head) {
            curr = curr->next;
            temp->next = curr;
            head = curr;
        }
        else {
            curr = curr->next;
            temp->next = curr;
        }
    }
}

void LinkedList::printList() {
    curr = head;
    cout << "The linked list:" << endl;
    while(curr != NULL) {
        cout << curr->data.toString();
        cout << " --> " << endl;
        curr = curr->next;
    }
    cout << "NULL" << "\n" << endl;
}

Account.h-

#ifndef ACCOUNT_H
#define ACCOUNT_H

#include <string>

/**
 * Account class for bankSimulator project.
 */
class Account {
    private:
        std::string name;
        int id;
        double interestRate;
        double value;
    public:
        Account(std::string name, int id, double interestRate, double value);
        std::string getName();
        int getID();
        double getInterestRate();
        double getValue();
        void accumulateInterest(double years);
        std::string toString();
};

#endif

Account.cpp-

#include "../include/Account.h"
#include <iostream>
#include <string>

using namespace std;

/**
 * Constructor for an account object.
 * @param name: the name of the account holder
 * @param id: the id for the account
 * @param interestRate: the interest rate of the account as a decimal
 * @param value: the current value of the account
 */
Account::Account(string name, int id, double interestRate, double value)
    :name(name), id(id), interestRate(interestRate), value(value) {

}

/**
 * Getter for the account name.
 * @return: the name of the account holder
 */
string Account::getName() {
    return name;
}

/**
 * Getter for the account ID.
 * @return: the ID of the account
 */
int Account::getID() {
    return id;
}

/**
 * Getter for the interest rate.
 * @return: the interest rate of the account
 */
double Account::getInterestRate() {
    return interestRate;
}

/**
 * Getter for the value of the account.
 * @return: the value of the account
 */
double Account::getValue() {
    return value;
}

/**
 * Addes the interest for the number of years annually.
 * @param years: the number of years
 */
void Account::accumulateInterest(double years) {
    while(years > 0) {
        if(years >= 1) {
            value += value*interestRate;
            years--;
        }
        else {
            value += value*interestRate*years;
            break;
        }
    }
}

/**
 * Creates a string representation of an Account.
 * @return: the string of the Account
 */
string Account::toString() {
    string output;
    output.append("Name: ");
    output.append(name);
    output.append("\nID: ");
    output.append(to_string(id));
    output.append("\nInterestRate: ");
    output.append(to_string(interestRate));
    output.append("\nValue: ");
    output.append(to_string(value));
    output.append("\n");
    return output;
}

Edited:

Here is the output-

./bin/main
The linked list:
Name: Sue Jones
ID: 3
InterestRate: 0.010000
Value: 10000.000000
 --> 
Name: John Smith
ID: 1
InterestRate: 0.010000
Value: 5783.000000
 --> 
NULL

The linked list:
Name: John Smith
ID: 1
InterestRate: 0.010000
Value: 5783.000000
 --> 
NULL

The linked list:
NULL

*** stack smashing detected ***: ./bin/main terminated
Makefile:18: recipe for target 'run' failed
make: *** [run] Aborted (core dumped)

Solution

  • You forgot to allocate the memory for the node. Better

    void LinkedList::addNode(Account add) {
        nodePtr n = new node;    /// allocate memory for the node
        n->next = NULL;
        n->data = add;
    
        if(head != NULL) {
            curr = head;
            while(curr->next != NULL) {
                curr = curr->next;
            }
            curr->next = n;
        }
        else {
            head = n;
            curr = n;
        }
    }
    

    And then you must also delete the node,

    void LinkedList::deleteNode(int delID) {
        temp = head;
        curr = head;
        while(curr != NULL && curr->data.getID() != delID) {
            temp = curr;
            curr = curr->next;
        }
        if(curr != NULL) {
            if(curr == head) {
                curr = curr->next;
                temp->next = curr;
                delete head;         /// delete node
                head = curr;
            }
            else {
                temp->next = curr->next;
                delete curr;         /// delete node
            }
        }
    }
    

    I reckon this is an exercise in learning basic programming skills. Otherwise, better use std::list.