Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm trying to make an own list-class which is of a fixed size and can store integers. Just for learning purposes.

This is how I do it: I have a struct called Item which holds the data (the integer to store), and a pointer to the next item in the list. When the list gets initialized I first add x amount of empty Items to the list.

The address of item declared in iteration (n-1) is stored in a buffer, so that the address of the item in iteration n, can be set as next for the item in the previous iteration (n-1). This to chain all items to each other.

And the address of the very first item is also saved, as the access point for the whole list later in the code.

But it's not really working; this is my code:

#include <iostream>

class List {
    public:
    //Item-object needed to store
    //elements
    struct Item {
        int data = 0;
        Item* next = nullptr;
    };

    //Constructor
    //creates a list of fixed size
    List(int size) {
        //Filling up with empty items
        for (int i = 0; i < size; i++) {
            Item item;

            //Storing iterator in item (just for testing purposes)
            item.data = i;

            //If first item,
            //store start-address
            //set buffer to start address
            if (i == 0) 
                this->start = &item;

            //Setting current item as nextptr
            //for previous item in buffer 
            if (i > 0)
                this->buffer->next = &item;

            //Storing current address in buffer
            this->buffer = &item;

            //Outputting address and value (just for testing purposes)
            //std::cout << "Address: " << &item << " -> " << item.data << std::endl;
        }
    }

    Item* getFirstItemAddress() {
        return this->start;
    }

    private:
    //Holding address of first item
    Item* start = nullptr;

    //Buffer holding temporary address
    Item* buffer = nullptr;

};

int main() {
    List list(5);

    //Printing out
    List::Item* current = list.getFirstItemAddress();
    while (current->next) {
        std::cout << current->data << std::endl;
        current = current->next;
    }

    return 0;
}

This is the output:

Testing output:
1168769696
-1064971727
Segmentation fault

However, when I uncomment testing-line 37 this is the output:

Address: 0x7ffe54015cf0 -> 0
Address: 0x7ffe54015cf0 -> 1
Address: 0x7ffe54015cf0 -> 2
Address: 0x7ffe54015cf0 -> 3
Address: 0x7ffe54015cf0 -> 4

Testing output:
1648675776
1648572376
1646105840
1226279756
Segmentation fault

I don't understand in the first place how outputting can change the output of 'Testing output' this drastically...

Anyway, segmentation fault info:

(gdb) run
Starting program: /home/niel/Desktop/listTest/main 
Address: 0x7fffffffe0a0 -> 0
Address: 0x7fffffffe0a0 -> 1
Address: 0x7fffffffe0a0 -> 2
Address: 0x7fffffffe0a0 -> 3
Address: 0x7fffffffe0a0 -> 4

Testing output:
-136467520
-136570920
-139037456
1226279756

Program received signal SIGSEGV, Segmentation fault.
0x000000000040092e in main () at main.cpp:62
62              std::cout << current->data << std::endl;

No idea why current->data gives the segmentation fault, as I gave data to each element!

But what bothers me most, is this:

 Address: 0x7fffffffe0a0 -> 0
    Address: 0x7fffffffe0a0 -> 1
    Address: 0x7fffffffe0a0 -> 2
    Address: 0x7fffffffe0a0 -> 3
    Address: 0x7fffffffe0a0 -> 4

Each item has the same address, of course, this isn't what I meant. Each item created in the iterations should be another item with another address. Has this something to do with Item being declared local, and the object for that reason is stored on the stack and not in free space? I tried using the 'new' keyword, but that didn't work!

TL;DR 1) Why am I getting the segmentation fault 2) How to fix that each Item created in List() has a separate address?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
152 views
Welcome To Ask or Share your Answers For Others

1 Answer

The problem

In your list constructor, you put in your list the address of an object item that is local to the loop and gets destroyed at the end of each iteration.

The solution

You have to create a new object in the free store, so that it survives the iteration and the end of the constructor. As you're learning, i keep it simple and use raw pointers:

List(int size) {
    for (int i = 0; i < size; i++) {
        Item *pitem = new Item;  
        pitem->data = i;  

        if (i == 0) 
            start = pitem;
        if (i > 0)
            buffer->next = pitem;

        //Storing current address in buffer
        buffer = pitem;

        //Outputting address and value (just for testing purposes)
        //std::cout << "Address: " << pitem << " -> " << item->data << std::endl;
    }
}

But then your code will leak memory. If you have such a constructor, you'll also need a copy constructor, an assignment operator and a destructor (rule of 3)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...