c++ Program won't run properly on Mac but will on Windows - c++

/*********************************************************************************************
* Function: Appends the Node newelement to the end of the List
*********************************************************************************************/
void append(const T &newelement)
{
Node *N = new Node(newelement);
if(first == (Node*)0)
{
first = N;
last = N;
_length = 1;
}
else
{
last->insertNodeAfter(N);
last = N;
_length++;
}
};
/*********************************************************************************************
* Function: Appends the Node newelement to the end of the List
*********************************************************************************************/
void prepend(const T &newelement)
{
Node *N = new Node(newelement);
if(first == (Node*)1)
{
first = N;
last = N;
_length = 1;
}
else
{
first->insertNodeBefore(N);
first = N;
_length++;
}
};
AS PEOPLE have told me off, I've narrowed it down to this code sort of... it breaks when its trying to ADD a node to the List. Giving me access errors and such. (BUT ONLY SOMETIMES)

On first glance, for example first == (Node*)1 (in prepend) is illegal/undefined and will give random behavior. Depending on memory layout of the chip and the OS, this will survive, work sometimes, work always, fail randomly, or fail always. It is not surprising at all that a Mac and a x86 chip behave differently.
There are multiple other assumption in the code, like an int is large enough for things; etc.
All these rules that people tend to gloss over have a reason, and many of these errors you get away with on one architecture,but not on another one.

Before you erroneously removed the relevant parts of your code from the question, the bug was fairly obvious.
DoubleLinkedNode's constructor fails to initialize the nextNode and previousNode class members to NULL. This results in undefined behavior.
Just because a C++ program crashes on a particular line, that doesn't mean that's where the bug is.
You are crashing when you're adding a new node to the list.
But the bug is that insertNodeAfter() is dereferencing an uninitialized pointer. And the bug is because the constructor is failing to initialize them to NULL.

Related

Why is the output of this code always the same?

Why am I getting the same output in the following for loop in c++.
node* nn = (struct node*)malloc(sizeof(struct node));
for(int i=0;i<10;i++)
{
node* n = (struct node*)malloc(sizeof(struct node));
cout<<&n<<endl;
nn->next = n;
nn =n;
}
Because your n variable is local to the loop body, it is created at the beginning of each iteration, and destroyed at the end of each iteration.
Evidently the compiler decided to reuse the same storage for every incarnation of n, which is why all of them have the same memory address.
Note that &n is the address of n, not its contents. You don't even have to initialize it. Your call to malloc is irrelevant.
If you want to see the value of n, you need to remove the &.
You're outputting &n which is the address of n not the content of n which is probably what you wanted.
NB: The question was edited following my answer, but the same problem remains.
Try this:
#include <iostream>
#include <cstdlib>
struct node {
node* next;
};
int main() {
node* nn = (struct node*)malloc(sizeof(struct node));
nn->next=nullptr;//Initialise so we can clean up nicely...
for(int i=0;i<10;i++)
{
node* n = (struct node*)malloc(sizeof(struct node));
n->next=nullptr;//Initialise so we can clean up nicely...
std::cout<<&n<<"=="<<n<<std::endl;
nn->next = n;
nn =n;
}
//Clean up after ourselves. Not relevant to the question but good practice.
while(nn!=nullptr){
node*n=nn;
free(nn);
nn=n;
}
return 0;
}
Typical output:
0x7ffda1be2058==0x55ffb0b9fc20
0x7ffda1be2058==0x55ffb0ba0c50
0x7ffda1be2058==0x55ffb0ba0c70
0x7ffda1be2058==0x55ffb0ba0c90
0x7ffda1be2058==0x55ffb0ba0cb0
0x7ffda1be2058==0x55ffb0ba0cd0
0x7ffda1be2058==0x55ffb0ba0cf0
0x7ffda1be2058==0x55ffb0ba0d10
0x7ffda1be2058==0x55ffb0ba0d30
0x7ffda1be2058==0x55ffb0ba0d50
The actual output may vary and in principle a compiler isn't required to store n at the same address each iteration. I know of no compiler that doesn't. Anyone?
NB: Using malloc() in C++ is very rarely recommended. The direct substitute for malloc() and free() is new and delete. In practice use std::unique_ptr<> or other self managing construct.
This is only an addition to melpomene's answer, responding to the comments:
How do I create n nodes? Use of vectors is prohibited, so I am creating a linked linked list of n nodes, but the problem is I am unable to create n nodes in a loop.
Actually, your code was less incorrect than you thought, solely you missed one important point:
nn->next = n;
With this instruction, you lost the last reference to what nn pointed to originally and you won't ever be able to re-gain it again...
What you yet need is a second pointer to the element created initially, so you don't lose your list head and thus the rest of the list any more:
node* nn = new node(); // this is the C++ way...
node* head = nn; // now you have a second pointer to the head...
for(int i=0;i<10;i++)
/* [...] */
Now you can access all the nodes you created via the head pointer (as long as you do not move it away from...).
Get rid of the loop and simply use struct *n = malloc (sizeof *n * 10); – David C. Rankin
Another variant: creating 10 elements directly... Assuming node looks like this:
struct node
{
Data data;
node* next;
};
Then you get 10 elements of Data simply by
Data* allData = new Data[10]; // again using the C++ way...
The C++ aproach has another advantage: the elements in the array are already initialised as the default constructor gets called (for primitive data types, see here).

How to manage an array of pointers to a struct

I have the following struct:
struct Item
{
Item* nextPtr;
int intKey;
int intValueLength;
};
Based of such a struct I need to maintain several linked lists, which means I need to keep track of one head pointer for each one. I have thought about using an array (HEADS) which will contain a head pointer for each list. The number of lists is variable and will be calculated at run time so I am defining the array dynamically as follows:
int t = 10;
Item* HEADS = new Item[t];
Firstly, I need to initialize each head pointer to NULL because the linked lists are empty when the program runs. How do I do this initialization?
for (int i = 0; i <= t - 1; i++)
// Initialize each element of HEADS to NULL.
And, of course, I will also need to update each element of HEADS with the proper pointer to a linked list (when inserting and deleting items) and also to get the value of each head pointer to display the elements of each list.
I have seen other posts similar to this one in the forum but I am still confused, that is why I am asking my specific situation.
Is this a good approach?
I will very much appreciate your advice.
Respectfully,
Jorge Maldonado
In C++ the common way to write the initialization for loop would be
for (int i = 0; i < t ; i++)
HEADS[i] = NULL;
Or you could write
for (int i = 0 ; i < t ; HEADS[i++] = NULL);
which is slightly more compact.
As to the question of whether an array of pointers is a good idea or not - if you're going to have a variable number of lists, perhaps you should use a linked list of pointers to other linked lists.
I do wonder about your data structure, though. In it you have a pointer to the next element in the list, a key value, and a the length of the value, but you don't appear to have a reference to a value - unless the "key" is really the value, in which case you have mixed terminology - that is, you refer to something in one place as a "key" and in another as a "value. Perhaps you need a pointer to a "value"? But I don't know what you're trying to do here so I just thought I'd note that issue.
Best of luck.
Good approach? That's a very, very dependent on things. Good for a student starting to learn C, maybe. Good for a real C++ programmer? Absolutely not. If you really want to create a linked-list, you should make a class that encompasses each element of these, and dynamically add elements. This is how std::list, for example, works. (std::list is doubly-linked list, and way more complicated).
Here's a sample class of how this should look like (off the top of my head; haven't compiled it, but should work):
struct LinkedList
{
Item* list;
int size = 0;
LinkedList() //constructor of this class/struct, it's the function that will be called once you create an object of LinkedList
{
list = nullptr; //don't use NULL, it's deprecated (this is for C++11, or change it back to NULL if you insist on using C++98)
}
addItem(const int& key)
{
Item item; //construct a new item
item.intKey = key; //fill the value in the item
Item* newList = new Item[size+1]; //create the new list with one more element
for(int i = 0; i < size; i++) //copy the old list to the new list
{
newList[i] = list[i]; //copy element by element
}
list[size] = item; //fill in the new item
if(size > 0)
{
list[size - 1].nextPtr = &list[size]; //assign "next pointer" for previous element
}
size = size+1; //increase the size of the list
}
~linkedList()
{
if(list != nullptr)
{
delete[] list;
}
}
}
Now this is better, but it's still far from optimal. However, this is how C++ should be used. You create objects and deal with them. What you did above is more like C, not C++.
To my code, you have to call:
LinkedList myList;
myList.addItem(55);
There are many things to do here to make this optimal. I'll mention a few:
In my code, every time you add an item, a new array is allocated. This is bad! std::vector solves this problem by allocating a bigger size than needed (for example, you add 1 item, it reserves 10, but uses only 1, and doesn't tell you that). Once you need more than 10, say 11, it reserves 20, maybe. This optimizes performance.
Try to read my code and understand it. You'll learn so much. Ask questions; I'll try to answer. And my recommendation is: get a C++ book, and start reading.

Problems dereferencing node defined by struct

This is for a homework assignment, so explanations (and not direct code) are what I need.
We recently started learned about copy constructors/assignment = operators and such. In the handout we got in class our professor showed us how if you want to deep copy pointers you have to dereference them and copy the values directly.
Eg: (from handout)
class IntCellFixed {
public:
IntCellFixed(int initialValue = 0) { storedValue = new
int(initialValue); }
//v This bit here v
IntCellFixed(const IntCellFixed &source) {
storedValue = new int();
*storedValue = *source.storedValue;
}
//^ This bit here ^
(...)
private:
int *storedValue;
};
This makes sense to me. You have a pointer, and you want to have the value it points to be equal to the value of the pointer you're copying from. So you do * to have it change the value at the address it's pointing at, and not the address itself. That makes sense to me.
So when we went to apply that in lab, I tried a similar thing, but with linked lists instead of just pointers to an integer. Even with the TA's help (with the TA looking at and tweaking my code until it was the "correct" thing), it still did not work and just gave me a segfault. I did not have a chance to ask what exactly the code was supposed to be, and the solution hasn't been posted yet.
We're doing almost the same thing in our homework. Here is the structure of our node (in a binary search tree):
struct Node {
int data;
int count;
Node *left;
Node *right;
};
In my void BinarySearchTree::insert(Node *node,Node *parent, int value) function, I have this bit of code:
if (node == NULL) {
node = new Node();
*node->data = value;
*node->count = 1;
node->left = NULL;
node->right = NULL;
}
When I try to do this, however, it gives me the error: invalid type argument of unary ‘*’ (have ‘int’).
When I take off the *, it runs fine, but doesn't actually save the data for the node outside of the insert function. (ie: when trying to insert multiple values, it always starts with an empty tree, even after I've supposedly inserted values already).
As far as I understand it, I WOULD need to dereference the node because I don't want the address it's pointing to to change, I want what's AT the address to change.
Am I just completely misunderstanding how/when to dereference? If I am, could somebody explain when I would need to, and why I wouldn't need to in this case? Or, if it's a syntax error, could somebody tell me what the syntax should be?

Why is this recursive function to search for an item in a list, causing stack overflow?

I have defined a basic list structure, and a simple insert function, and a search function. The code is below:
////////////////////////////////////////////////
typedef struct list
{
int item;
struct list *next;
}List;
////////////////////////////////////////////////
List * search_list(List * l, int i)
{
if(NULL == l)
return(NULL);
if(i == l->item)
return l;
else
return search_list(l->next, i);
}
////////////////////////////////////////////////
void insert_list(List ** l, int i)
{
List * p = new List();
p->item = i;
p->next = *l;
*l = p;
}
My main loop to test it, looks like this:
int main(int, char* argv[])
{
List * mylist = new List();
for(int i = 0; i < 8000; i++)
{
insert_list(&mylist,i);
}
int val = 2000;
List * s = search_list(mylist, val);
return 0;
}
When val is 4000, the program completes ok. But when val is 2000, i.e. 2000 indexes further down the list, Visual Studio terminates with a stack overflow.
Is the number of recursive calls in search_list() causing a stack overflow? How can I get rid of this error?
Recursive algorithms should only be used if the depth is strictly limited or the algorithm has no more than O(logN) complexity. If that's not the case then you always risk stack overflow. Yours doesn't meet the complexity requirement, it is O(N).
Visual Studio doesn't exactly help avoid the crash when you run your program with default Debug build settings. For one, the tail recursion optimization isn't enabled, that requires Release build settings so the optimizer is turned on. For another, the Edit + Continue feature allocates a bunch of extra stack space for a function. It is available in case you add a local variable to the function while debugging.
You can easily turn that off. Project + Properties, C/C++, General, change the Debug Information Format setting to "Program Database (/Zi)". Your program will no longer crash.
There is one thing your compiler should have told you: This recursive invocation of search_list doesn't return anything. Didn't you get a warning about this? And using recursion here really is a bad idea, better replace it with some kind of loop. One reason of course is excessive stack usage, another one is debugging sucks with that kind of recursion.
Besides your stack overflow error, you should check the following. You are not initializing the values of the first allocated List instance at main(), pointed by mylist.
List * mylist = new List();
What your current code does is it passes an "empty" List instance at the first call, that can have an invalid next value. This will be your last List instance in the linked list.
You should do this instead:
List * mylist = NULL;
This will assure you last List instance in the list has a next with NULL value.

c++ outputting and inputting a single character

I am writing a program in c++ which implements a doubly-linked list that holds a single character in each node. I am inserting characters via the append function:
doubly_linked_list adam;
adam.append('a');
This function is implemented as follows:
//Append node
node* append(const item c){
//If the list is not empty...
if(length){
//maintain pointers to end nodes
node* old_last_node = last;
node* new_last_node = new node;
//re-assign the double link and exit link
old_last_node->next = new_last_node;
new_last_node->back = old_last_node;
new_last_node->next = NULL;
//re-assign the last pointer
last = new_last_node;
}
//If this is the first node
else{
//assign first and last to the new node
last = first = new node;
//assign nulls to the pointers on new node
first->next = first->back = NULL;
}
//increase length and exit
++length;
return last;
}
However, I think there is an issue, perhaps with the way C++ handles characters. When I go to print my list, somehow I never get the characters to print which I have appended to my list. This is what I'm using to print:
//Friendly output function
friend std::ostream& operator << (std::ostream& out_s, const doubly_linked_list& source_list){
//create iteration node pointer
node* traverse_position = source_list.first;
//iterate through, reading from start
for(int i = 1; i <= source_list.length; ++i){
//print the character
out_s << (traverse_position->data);
traverse_position = traverse_position->next;
}
//return the output stream
return out_s;
}
I just get crap when I print it. It prints characters that I never appended to my list - you know, just characters just from somewhere in the memory. What could possibly be causing this?
Where are you assigning the value c in the append() function? I fear you may have concentrated too much on the doubly-linked-list part and not enough on the storing-data part. :)
As others have already mentioned, you forgot to store the characters you were supposedly appending. It's a reasonable mistake to make. To avoid it in the future, you can let the compiler help you.
Most compilers offer warnings about things that are technically OK, but probably aren't what you really want to do. In your case, you declared the parameter c, but you never used it. With warnings enabled, your compiler could have noticed that and told you that you hadn't used it. That would probably have been enough of a reminder for you that you weren't finished writing that function.
GCC's option to enable common warnings is -Wall. (That's "W" for "warning," plus "all"; it has nothing to do with walls. But it's not really all warnings, either.) For example:
g++ -Wall list-program.cpp
Other compilers have similar options. Check your compiler's documentation for details.
No where in your append method do you actually place the item into the new node. When you go to print, it just prints whatever value happens to be in that memory location (some random value).