I've got a console application reading some char-data from the console and then puts in into a structure. This structure is used as linked list, when it's constructed, I keep one pointer pointing to the first list element and one pointer for running through the list.
What happens to me is, when I first run through my list and write its contents into the console, everything works perferctly. When I later want to set my running pointer to the lists last element, it keeps crashing with an c000005 access violation error.
I will give you the interesting parts of my code:
definition of my structure:
struct musikdaten {
char interpret[150];
char titel[150];
struct musikdaten* next;
};
printing the lists content:
while (it != NULL) {
cout << it->interpret << ": " << it->titel << "\n";
cout << "next: " << it->next << "\n";
it = it->next;
}
setting "it" to the lists last element:
while (true) {
if (it->next == NULL) {
cout << "Assigning some memory...\n";
it->next = new musikdaten;
break;
}
else it = it->next;
}
However, this last part keeps crashing when the list contains more than two elements.
Note: When a new list element is added while reading it's content from console, the next pointer is always initialized as NULL.
You should initialize the next member with NULL to indicate the end of the list:
it->next = new musikdaten;
it->next->next = NULL;
Or add a default constructor:
struct musikdaten {
musikdaten() { next = NULL; /*TODO: init other members*/}
char interpret[150];
char titel[150];
struct musikdaten* next;
};
Related
I have started learning c++ (coming from java background) and barely reached pointers and got stuck. When I debug this program it says, program received segmentation fault (SIGSEGV signal) at line
*previous = head;
in the following code.
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *link;
};
int main()
{
cout << "Starting main program \n";
Node head;
head.data = 0;
head.link = NULL;
cout << "After declaring head and initializing values \n";
//Declaring a pointer variable which points to an entity of type struct.
Node *previous;
*previous=head;
cout << "After declaring previous pointer \n";
bool done = false;
int i = 1;
cout << "First while loop\n";
while(!done)
{
cout << i << ": Iteration";
Node temp;
temp.data=i;
temp.link=NULL;
if(i > 2)
{
done = true;
continue;
}
*previous->link=temp;
++i;
*previous = temp;
}
done = false;
cout << "Declaring temp pointer before printing \n";
Node *temp;
*temp = head;
cout << "Second while loop\n";
while (!done)
{
cout << i << ": Iteration";
if(temp == NULL)
{
done = true;
continue;
}
cout << temp->data << "->";
*temp = *temp->link;
}
cout << "NULL";
}
Why is the pointer initialization incorrect ?
First problem:
Node *previous;
*previous=head;
First line declares that previous will hold the address of a Node. It is not initialized, so whatever value happens to be on the stack will be picked up as the bit pattern it holds.
Unfortunately, the 2nd line then dereferences the pointer (which points to garbage) and attempts to copy head into random memory (hence your crash).
In this case you probably want previous to point to head, which is taking head's address and assigning it:
Node* previous = &head; // initialize at the point of declaration
However, you must also be very wary of pointers to variables declared on the stack, because the addresses will soon become invalid when the function returns or the scope exits.
(Usually data structures with pointers are using values allocated on the heap, so the objects outlive the function that declares them.)
Which brings us to the second problem:
while(!done)
{
cout << i << ": Iteration";
Node temp;
Already there's a problem. temp is declared inside the loop on the stack. Each loop iteration, the variable will automatically be destroyed. Therefore it cannot participate in your linked list without corrupting it.
You want your list nodes to be created with new, and when you update previous's next pointer, you want to assign an address TO it, not copy an object THROUGH it.
Something like this:
while(!done)
{
cout << i << ": Iteration";
Node * temp = new Node();
temp->data = i;
temp->link = nullptr; // better than NULL
if(i > 2)
{
break;
}
previous->link = temp;
++i;
previous = temp;
}
The head object should probably also be heap allocated. Of course, now you have to deal with cleaning up the memory by calling delete on all the nodes.
There were some bugs in the code but major ones were :-
you were not allocating memory for the new nodes that you were adding during runtime
you were creating instances of structure but instead you were required to create an pointer pointing to the structure ( instances will be created during runtime ( using new operator )
I have added the comments to the code explaining what exactly are the changes that I have done.
Here is the fix :-
#include <iostream>
using namespace std;
struct Node
{
int data;
Node *link;
};
int main()
{
cout << "Starting main program \n";
// Allocating memory for the new instance of Node and making "head" pointing to it
Node *head = new Node;
head->data = 0;
head->link = NULL;
cout << "After declaring head and initializing values \n";
//Declaring a pointer variable which points to an entity of type struct.
Node *previous;
// As head and previous both are pointers thus can be assigned as it is
previous = head;
cout << "After declaring previous pointer \n";
bool done = false;
int i = 1;
cout << "First while loop\n";
while(!done)
{
cout << i << ": Iteration";
// Allocating memory for the new instance of Node and making temp pointing to it
Node *temp = new Node;
// As temp is a pointer thus using member access ("- >") operator to access the members
temp->data=i;
temp->link=NULL;
if(i > 2)
{
done = true;
continue;
}
previous->link = temp;
++i;
previous = temp;
}
done = false;
cout << "Declaring temp pointer before printing \n";
Node *temp;
temp = head;
cout << "Second while loop\n";
while (!done)
{
cout << i << ": Iteration";
if(temp == NULL)
{
done = true;
continue;
}
cout << temp->data << "->";
temp = temp->link;
}
cout << "NULL";
}
I'm implementing a stack using GList (doubly) but when I assign my stack with the last element using g_list_last(*stack*) the program doesn't print my stack at all
Pointing to the first element using g_list_first(*stack*) works and I can traverse with stack->next pointer
Here's my test program:
#include <iostream>
#include <cstdlib>
#include <glib.h>
using namespace std;
int main()
{
cout << "Enter the no of random data to push: ";
int number = 0;
cin >> number;
GList *stack = nullptr;
for (int i = 0; i < number; i++) {
int data = random() % 10;
stack = g_list_append(stack, GINT_TO_POINTER(data));
cout << "Push: " << data << endl;
}
cout << "Printing the stack forward:\n";
stack = g_list_first(stack);
while (stack != nullptr) {
cout << GPOINTER_TO_INT(stack->data);
cout << "->";
stack = stack->next;
}
cout << "nullptr" << endl;
cout << "Printing the stack backward:\n";
stack = g_list_last(stack);
while (stack != NULL) {
cout << GPOINTER_TO_INT(stack->data);
cout << "->";
stack = stack->prev;
}
cout << "nullptr" << endl;
return 0;
}
Do I have to manually assign the prev link while appending?
First of all, I would not recommend using GLib in a C++ code base; GLib is a C library, full of idiomatic C code and functionality. I'd suggest using the C++ standard library, instead.
GList is a doubly linked list where each element is composed by three pointers:
typedef struct _GList GList;
struct _GList
{
void *data; // untyped pointer data
GList *prev; // pointer to the previous element in the list
GList *next; // pointer to the next element in the list
}
For convenience, all the GList functions accept a NULL as a valid list; in the case of g_list_append(), passing a NULL list as the first argument means that it will allocate a new GList element for the data you're passing and place it at the start of the list.
In your code you're taking the head of the list after populating it, and calling g_list_first(), which is a no-op on the head of the list; then you proceed to consume it by iterating over it, until you hit the end of the list, where you assign nullptr to the stack variable. Since nullptr/NULL is a valid empty GList, you're now calling g_list_last() on a valid, but empty list, which will return NULL, and thus prevent you from iterating backwards. Additionally, you're now leaking the memory allocated to the list.
The solution is to never iterate a GList with the same variable that holds the head of the list:
cout << "Printing the stack forward:\n";
GList *iter = g_list_first(stack);
while (iter != nullptr) {
cout << GPOINTER_TO_INT(iter->data);
cout << "->";
iter = iter->next;
}
cout << "nullptr" << endl;
The code above will consume the iter variable, instead of the stack. Which means that the code below:
cout << "Printing the stack backward:\n";
iter = g_list_last(stack);
while (iter != NULL) {
cout << GPOINTER_TO_INT(iter->data);
cout << "->";
iter = iter->prev;
}
cout << "nullptr" << endl;
will work appropriately, and walk the stack backwards, as the stack variable still points to the head of the list, and you're now consuming a temporary iterator.
Remember to call g_list_free() on the list to release any resources allocated for it—and g_list_free_full() in case you're allocating the contents of the data pointer as well.
I've been trying to write my own implementation of linked list, but the code segfaults when I try to access an the third element or anything after it. Adding elements doesn't segfault, but accessing does. I can't find the pointer error in my get() function.
Each node in the list stores data (of Template t) and a pointer leading to the next node. I have two functions for everything- one for the first element, and one for any subsequent elements. The get() function for the subsequent elements always segfaults. I have some debug messages in the function that spit out results I can't explain. For example, if I run a get() request for the second element, an then the third, the code doesn't segfault, but it does return clearly incorrect results. Debug messages I placed indicate the segfault occurs when the second element calls the function to check the third element, if it occurs at all. Try the code with and without the line cout << newList.get(2) << endl; and you'll get very different results.
One possible cause is the pointer storage- I have the get() function output the pointer of each element (except the first) as it cycles through, and compare them to the pointers outputted by the add() function, and and pointers for element 0 and 1 match, but 2 and beyond do not match, and I can't seem to figure out why that would be.
#include <iostream>
using namespace std;
template <class T> class myLinkedList{
T data;
myLinkedList<T> *next = NULL;
public:
myLinkedList(T input){
data = input;
}
void add(T input){
if(next == NULL){
myLinkedList<T> newItem(input);
next = &newItem;
cout << "adding to list, data is " << input << ", pointer is " << next << endl;
}else{
myLinkedList<T> nextEntry = *next;
nextEntry.add(input);
}
}
T getData(){
return data;
}
//the start of the get function, only used by the first entry in the list
T get(int entry){
int currentPosition = 0;
if(entry == currentPosition){
return getData();
}else{
//defrefrence the pointer anc check the next entry
myLinkedList<T> nextEntry = *next;
return nextEntry.get(entry, ++currentPosition);
}
}
private:
//this vesion is the hidden, private vesion only used by nodes other than the first one
//used to keep track of position in the list
T get(int entry, int currentPosition){
//cout << currentPosition << endl;
if(entry == currentPosition){
return data;
}else{
//derefrence the pointer and check the next entry
cout << next << endl;
myLinkedList<T> nextEntry = *next;
currentPosition++;
T output = nextEntry.get(entry, currentPosition);
return output;
}
}
};
int main(){
myLinkedList<int> newList(3);
newList.add(4);
newList.add(5);
newList.add(7);
newList.add(9);
cout << newList.get(2) << endl;
cout << newList.get(3) << endl;
return 0;
}
Results are clearly erroneous- program should spit oout two macthing sets of pointers, as well as the numbers 5 and 7 ( the list elements)
One of your main problems is here:
if(next == NULL){
myLinkedList<T> newItem(input); // <<<<<<<<<<<<<
next = &newItem;
cout << "adding to list, data is " << input << ", pointer is " << next << endl;
}
you allocate an item on stack inside the if scope. Then you make next to point to this item. But... lifetime of the item is bounded by this scope. As son as you exit the scope, this item does not exist any longer. You need to allocate it dynamically by 'new' or other methods.
I had a breakthrough! Following Serge's solution was helpful, but one more change was needed- rather than create a function reference in the else block of my add function,
eg
myLinkedList<T> nextEntry = *next;
nextEntry.add(input)
i needed to use the pointer directly, as in
next->add(input)
I didn't know my pointer/object syntax
I have a problem with the following linked list code, but i'm not sure what it is. Could someone point me in the right direction? I'm using this code in some larger code where i update records, but it never reaches the "creating new record" section. It is as if the main code is updating the head pointer instead thus always resulting in a favourable comparison.
Thanks in advance. I've been racking my brains out trying to figure out what the problem is.
struct l_list *find_name(const char *name)
{
struct l_list *tmp=0;
if(records==0) { // First record
head=new l_list;
head->name=name;
head->next=0;
tail=head;
records++;
return head;
}
else {
tmp=head;
while(tmp!=0)
{
if(!std::strcmp(tmp->name,name))
{
cout << "Returning existing record with value: " << tmp->number << " name:" << tmp->name << endl;
return tmp;
}
tmp=tmp->next;
}
// No first and no existing records
cout << "Creating new record" << endl;
tail->next=new l_list;
tail=tail->next;
tail->name=name;
tail->next=0;
records++;
return tail;
}
I'm calling this from main with:
struct records *tmp=find_name("Max");
then :
tmp=find_name("Eva");
Once i get the struct i update it like so:
tmp->number=1;
Or even updating the name:
tmp->name="Peter";
So by passing a string to the function it will either create a new record and return it or give an existing record and return that. Problems might not be apparent in the output, but when you put it in a for(;;) loop in main it will
mess up.
The struct is as follows:
struct records {
const char *name;
struct records *next;
}
The relevant program code is:
struct record {
const char *name;
struct record *next;
};
struct record *head;
struct record *tail;
struct record *find_name(const char *name)
{
struct record *tmp=0;
if(record_count==0) { // First record
cout << "Creating first record" << endl;
head=new record;
head->name=name;
head->next=0;
tail=head;
record_count++;
return head;
} else {
tmp=head;
while(tmp!=0) {
if(!std::strcmp(tmp->name,name)) {
cout << "Returning existing record with value: " << "name: " << name << "tmp->name: " << tmp->name << endl;
return tmp;}
tmp=tmp->next;
}
// No first and no existing records
cout << "Creating new record" << endl;
tail->next=new record;
tail=tail->next;
tail->name=name;
tail->next=0;
record_count++;
return tail;
}
}
int main(int argc, const char *argv[])
{
struct record *tmp=0;
if(something is true) {
//Return or create a new user
tmp=find_name("Peter");
} else {
tmp=find_name("Unknown"); // Hold 1 unknown person in database
}
}
I know it's not compilable as-is but i had to extract it from a larger part.
Since you have not told us what the records structure is, there is no way for anyone to give a correct answer. You have made it even more impossible by not giving an example of code that will cause your function to behave incorrectly.
If the name element is a char * pointer then you could easily get this behaviour. For example:
The calling code puts a name into a buffer, and calls find_name.
find_name stores the address of the buffer into the name element of a records object. name therefore points to whatever the buffer happens to contain, now and in the future.
The calling code puts a new name into the same buffer. This automatically means that the name element now points to that new name, since it is pointing to the buffer.
The calling code calls find_name again.
find_name compares the contents of the buffer to the string pointed to by the name element of the first records object. Since the name element contains the address of the buffer passed by the caller (from step 2), this means that it is comparing the buffer to itself. So the result is always "equal".
But it may be that name is not a pointer at all, in which case this entire answer is irrelevant.
First of all do not use the following code formatting
if(record_count==0) { // First record
cout << "Creating first record" << endl;
//...
} else {
tmp=head;
//...
It is difficult to read such a code. It is just a bad style of programming.
The function itself can look the following way
struct l_list * find_name( const char *name )
{
struct l_list *tmp = head;
wjile ( tmp != nullptr && std::strcmp( tmp->name, name ) != 0 ) tmp = tmp->next;
if ( tmp == nullptr )
{
cout << "Creating new record" << endl;
tmp = new l_list;
tmp->name = name;
tmp->next = nullptr;
if ( tail == nullptr )
{
head = tail = tmp;
}
else
{
tail = tail->next = tmp;
}
records++;
}
return tmp;
}
Take into account that the nodes can contain pointers to strings either with the static storage duration as for example string literals or allocated in the heap.
I've got an issue right here, I'm getting a memory violation error (I am handling the memory) and also a wrong input. What I am doing is a pointer managed list.
My code is supposed to do: Update the referenced pointer with multiple entries and print them. It does it partially, let me show you.
Code:
#include "stdafx.h"
#include <string>
#include <iostream>
#include <tuple>
#include <vector>
using namespace std;
struct Lyric
{
Lyric* next;
tuple<int, string> tuple;
};
void Addition(Lyric*& poetry, tuple<int, string> tpl)
{
Lyric* newl = new Lyric;
newl->tuple = tpl;
newl->next = poetry;
poetry = newl;
}
void PrintScr(Lyric*& poetry)
{
if (poetry == NULL)
{
cout << "Empty list !" << endl;
return;
}
else
{
Lyric* prel = poetry;
while (prel != NULL)
{
cout << "Printing the integer: " << get<0>(prel->tuple) << endl;
cout << "Printing the string : " << get<1>(prel->tuple) << endl;
cout << "------------------------------------------" << endl;
prel = prel->next;
}
}
}
void main()
{
string a_str[] = {"test1", "test2"};
Lyric* poetry = new Lyric();
/*
int size = 1;
for (int i = 0; i <= size; i++)
Addition(poetry, i, make_tuple(i, a_str[i]));
*/
Addition(poetry, make_tuple(0, a_str[0]));
Addition(poetry, make_tuple(1, a_str[1]));
PrintScr(poetry);
system("PAUSE");
}
Output:
So it's supposed to print them in the order they've been added . My best bet is that I've screwed something up in the PrintScr method because it prints them in reverse and also prints a non-existing item, but I am not sure what I am doing wrong, I am going through the elements one by one and printing them....
This is how it's supposed to look like :
Printing the integer : 1
Printing the string : test1
-------------------------------
Printing the integer : 2
Printing the string : test2
-------------------------------
This line is the culprit:
Lyric* poetry = new Lyric();
The default constructor of Lyric does not set a sane value to the next_ member. It remains uninitialized and you get undefined behavior when you dereference it.
What you need is:
Lyric* poetry = nullptr;
You are never initializing the next ptr in Lyric to NULL, so when you get to the last item in the list it's some garbage pointer that causes a crash when you try to access the memory it's pointing to.
You can fix this by setting next to NULL in Lyric's constructor or just setting poetry->next = NULL in main.cpp right after you create it.
I should also point our that you're inserting at the front of the list instead of the back of the list inside Addition() which is probably not what you intended.