does dynamically allocation structs in cpp require redefining elements? - c++

Trying to implement the add function in dynamic list, recursively.
The code is self-explanatory:
struct list {
int value;
list* next = NULL; // is this valid?
};
list head;
void add(list* cur, int value) {
if (cur->next) {
add(cur->next, value);
return;
}
cur->next = (list*)(malloc(sizeof(list)));
cur->next->value = value;
cur->next->next = NULL; // withouth this line, the program errors out after two calls to the function add
}
int main() {
for (int i = 0; i < 50; i++)
add(&head, i);
}
After seeing the debugger, I realized that calling malloc wasn't initiating "next" with NULL as specified in the defininition of the list struct.

As noted in comments, malloc does not initialize anything. It simply grabs a chunk of memory big enough for a list struct. Now, that might mean that struct has next set to NULL, or it might not.
That is why you're having to explicitly initialize it to NULL as that prevents undefined behavior when accessing that member.
If you use new to handle dynamic memory allocation, then the next member is initialized to NULL.
cur->next = new list;
Including this use of malloc, your code is very C-ish, and there are numerous improvements C++ will allow you to make.

Related

Declaring any new variable changes pointer address for unknown reason

I am writing an auction program for a class project and one of the features I was trying to implement was a hash table to make searching for auction items by name efficient. I set it up in node format so that you can chain nodes together if their hash value lines up with another item that already exists.
The main problem that I cannot seem to figure out is how some pointer values are changing when I don't think I have done anything to them. I stepped through each line of this program keeping an eye on the Red highlighted areas in the attached screenshots to see when the data changes. In case #1 the data was intact and able to be accessed. However, in case #2 where I simply declare an additional variable (int i = 0;) suddenly the data passed into the function appears to point to a different memory location (0xcccccccc) which from what I understand is another version of null? This is the same no matter what variable type I have tried to declare whether it be an int, const char*, string, etc it all reacts like the second screenshot.
Does anyone know why the program would be doing this? Are there any other troubleshooting tips? Is this a common error and how should I avoid it in the future and for this project?
I can provide a complete code if needed. I appreciate any help you can provide.
Image 1: No additional variable declared, data in tact as expected
Image 2: integer variable declared, data at ->next suddenly changed. This appears to be this way from the start of the function.
Update: I created an MRE as suggested in a comment, the same error can be reproduced using this code.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
class AuctionItemBidsMaxHeap {
string name = "test";
public:
const char * getItemName() {
return name.c_str();
}
};
class AuctionItemHashTable {
private:
struct Node {
AuctionItemBidsMaxHeap* AuctionItem;
Node* next = nullptr;
};
Node* itemArray;
int capacity = 50;
int generateHashKey(string auctionItem) {
return 11;
}
public:
AuctionItemHashTable() {
//Create the array of X amount of different possible storage locations
Node emptyNode;
emptyNode.AuctionItem = nullptr;
emptyNode.next = nullptr;
itemArray = new Node[capacity];
for (int i = 0; i < capacity; i++) {
itemArray[i] = emptyNode;
}
}
~AuctionItemHashTable() {
delete itemArray;
}
void insertItem(AuctionItemBidsMaxHeap* auctionItem) {
//Check to see if this item already exists
int key = generateHashKey(auctionItem->getItemName());
Node newAuctionItem;
newAuctionItem.AuctionItem = auctionItem;
newAuctionItem.next = nullptr;
//Check to see if anything has been inserted there yet
if (itemArray[key].AuctionItem == nullptr) {
itemArray[key] = newAuctionItem;
}
else {
//WE have to make room in the semi-linked list
Node holder;
holder.AuctionItem = itemArray[key].AuctionItem;
holder.next = itemArray[key].next;
newAuctionItem.next = &holder;
itemArray[key] = newAuctionItem;
}
}
AuctionItemBidsMaxHeap* getAuctionItem(const char* itemName) {
int key = generateHashKey(itemName);
//Loop through all items in location
Node* currentNode = &itemArray[key];
if (currentNode == nullptr) {
return nullptr;
}
else {
if (currentNode->AuctionItem->getItemName() == itemName) {
cout << "Match" << endl;
}
while (currentNode->next != nullptr && currentNode->next != (void*)0xcccccccc) {
int i = 0;
if (currentNode->next->AuctionItem->getItemName()[0] == 'M') {
cout << "M Matched" << endl;
}
while (currentNode->next->AuctionItem->getItemName()[0] != 'e') {
//cout << currentNode->next->AuctionItem->getItemName()[i];
}
currentNode = currentNode->next;
}
//There was an item stored at this location, lets see which one it is
//void* p = (void*)0xcccccccc; //Creating a pointer since for some reason my final pointer gets changed to another type of null character upon passing it to a function
//cout << currentNode->AuctionItem->getItemName() << endl;
//while (currentNode->next != nullptr && currentNode->next != p) {
//cout << currentNode->AuctionItem->getItemName() << endl;
//currentNode = currentNode->next;
//}
return currentNode->AuctionItem;
}
}
};
int main()
{
/**Creating MaxHeap of one bid**/
AuctionItemBidsMaxHeap myBidTest;
AuctionItemBidsMaxHeap myBidTest2;
/**Creating Auction Item Hash Table**/
AuctionItemHashTable auctionItems;
auctionItems.insertItem(&myBidTest);
auctionItems.insertItem(&myBidTest2);
const char* myInput = "test";
auctionItems.getAuctionItem(myInput);
}
First a rant: Why is it that classes still teach pointers in C++? There are MUCH better ways to do this than Node*.
Your code contains several errors, but the most important one is here:
//WE have to make room in the semi-linked list
Node holder;
holder.AuctionItem = itemArray[key].AuctionItem;
holder.next = itemArray[key].next;
newAuctionItem.next = &holder; ////<<< ERROR HERE
itemArray[key] = newAuctionItem;
You create a temporary variable on the stack Node holder; This variable will be destroyed as soon as you leave the function.
But you take a pointer to this variable here
newAuctionItem.next = &holder;
IOW: Your list contains pointers to objects that no longer exist.
&holder is the address of the variable holder. As soon as holder goes out of scope, the contents of it will be destroyed. But newAuctionItem.next and as a consequence also itemArray[key].next will still point to the memory, where holder used to be.
This is what is called a dangling pointer.
I stopped reading your example, but it is also pretty dangerous to accept pointers to AuctionItems in your insert method. When you are using pointers here, you MUST MAKE SURE, that the actual objects remain valid for as long as they are in the list.
Or, to put it the other way round: You must remove them from your list before they get destructed. And we humans are not made to "make sure". We make errors, so it is better to write code where you cannot make an error like this (i.e. avoid pointers in the first place).
Another error: You are creating an array with itemArray = new Node[capacity];, but you are deleting it with delete itemArray;. When you are using new to create an array, you must use delete[] itemArray to delete it. See here delete vs delete[] operators in C++
A general note: DO NOT USE POINTERS AT ALL (unless you have to). Pointers are an advanced C++ concept.
You could use shared_ptr<> instead. This will take away the burdon of freeing the memory.
For your itemArray you could use std::vector<> instead of allocating an array with new[]; etc...
There are many good and easy to use classes in the C++ library, which will help you a lot writing safer and cleaner code.
Learning C++ is (at least) as much about learning the std Library as about learning the syntax and statements. std::vector<AuctionItemNodes> IS C++.

How to delete linked list using free

i've got these structures:
typedef struct tStimulus_tc
{
short Key;
struct tStimulus_tc *Next;
}Stimulus_tc;
struct Frame_tc
{
int ID; // Frame ID (0..MAX)
int Count; // Felt Count
short sSize; // Stimulus List Size
Stimulus_tc *sList; // Stimulus List
};
if i want to free a "struct Frame_tc" is this enough?
void freeFrame (Frame_tc *fTemp)
{
free(fTemp);
}
or i need to run throught it's stimulus and free 1 by 1?
what's the proper way to free a variable?
free() takes a previously allocated block and releases it for reuse. It doesn't know nor care about the contents of the buffer.
While you could write a compiler that recursively frees pointers, this isn't a good idea:
static Stimulus_tc stim;
Frame_tc *fTemp = malloc(sizeof *fTemp);
fTemp->sList = &stim;
fTemp->sSize = 1;
free(fTemp); // if this recursively freed pointers, we would free a static object
Only you know how your structure is constructed, therefore you shoud be the one destructing it. In your case that means walking the linked list and freeing each member.
In C++, it's advisable to use higher level mechanisms, like using a std::vector<Stimulus_tc> or std::list<Stimulus_tc>.
In cases where pointer use is inevitable (your case isn't one), consider using smart pointers. And if you absolutely must manage memory the old way, use type-safe new[]/delete[].
In C, if your Stimulus_tc list within the struct Frame_tc wrapper is not a traditional head/tail list (e.g. with the final ->Next = NULL), but with the number of nodes contained in list->sSize, you could do something similar to the following:
/* free all nodes in struct Frame_tc->Stimulus_tc list */
void free_list (struct Frame_tc *list)
{
Stimulus_tc *iter = list->sList; /* pointer to iterate list */
Stimulus_tc *victim = NULL; /* pointer to node to delete */
int n = list->sSize; /* number of nodes to delete */
if (iter == NULL) {
fprintf (stderr,"print_list() warning: empty list.\n");
return;
}
while (n--) { /* free n nodes */
victim = iter;
iter = iter->Next;
free (victim);
}
}
If you set the final Next pointer to NULL, you can eliminate int n = list->sSize; and simply iterate over the list with while (iter) { ...
If there were additional pointer elements within each node that were allocated, you would simply free those values before free (victim);
Look it over and let me know if you have any questions.

why does "a->content" give me a address instead of a value?

now i have been making games for a few years using the gm:s engine(tho i assure you i aint some newbie who uses drag and drop, as is all to often the case), and i have decided to start to learn to use c++ on its own, you know expand my knowledge and all that good stuff =D
while doing this, i have been attempting to make a list class as a practice project, you know, have a set of nodes linked together, then loop threw those nodes to get a value at a index, well here is my code, and i ask as the code has a single major issue that i struggle to understand
template<class type>
class ListNode
{
public:
type content;
ListNode<type>* next;
ListNode<type>* prev;
ListNode(type content) : content(content), next(NULL), prev(NULL) {}
protected:
private:
};
template<class type>
class List
{
public:
List() : SIZE(0), start(NULL), last(NULL) {}
unsigned int Add(type value)
{
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
else
{
ListNode<type> a(value);
this->last->next = &a;
a.prev = this->last;
this->last = &a;
}
this->SIZE++;
return (this->SIZE - 1);
}
type Find(unsigned int pos)
{
ListNode<type>* a = this->start;
for(unsigned int i = 0; i<this->SIZE; i++)
{
if (i < pos)
{
a = a->next;
continue;
}
else
{
return (*a).content;
}
continue;
}
}
protected:
private:
unsigned int SIZE;
ListNode<type>* start;
ListNode<type>* last;
};
regardless, to me at least, this code looks fine, and it works in that i am able to create a new list without crashing, as well as being able to add elements to this list with it returning the proper index of those elements from within the list, however, beyond that the problem arises when getting the value of a element from the list itself, as when i ran the following test code, it didn't give me what it was built to give me
List<int> a;
unsigned int b = a.Add(313);
unsigned int c = a.Add(433);
print<unsigned int>(b);
print<int>(a.Find(b));
print<unsigned int>(c);
print<int>(a.Find(c));
now this code i expected to give me
0
313
1
433
as that's what is been told to do, however, it only half does this, giving me
0
2686684
1
2686584
now, this i am at a lost, i assume that the values provided are some kind of pointer address, but i simply don't understand what those are meant to be for, or what is causing the value to become that, or why
hence i ask the internet, wtf is causing these values to be given, as i am quite confused at this point
my apologies if that was a tad long and rambling, i tend to write such things often =D
thanks =D
You have lots of undefined behaviors in your code, when you store pointers to local variables and later dereference those pointers. Local variables are destructed once the scope they were declared in ends.
Example:
if (this->SIZE == 0)
{
ListNode<type> a(value);
this->start = &a;
this->last = &a;
}
Once the closing brace is reached the scope of the if body ends, and the variable a is destructed. The pointer to this variable is now a so called stray pointer and using it in any way will lead to undefined behavior.
The solution is to allocate the objects dynamically using new:
auto* a = new ListNode<type>(value);
Or if you don't have a C++11 capable compiler
ListNode<type>* a = new ListNode<type>(value);
First suggestion: use valgrind or a similar memory checker to execute this program. You will probably find there are many memory errors caused by dereferencing stack pointers that are out of scope.
Second suggestion: learn about the difference between objects on the stack and objects on the heap. (Hint: you want to use heap objects here.)
Third suggestion: learn about the concept of "ownership" of pointers. Usually you want to be very clear which pointer variable should be used to delete an object. The best way to do this is to use the std::unique_ptr smart pointer. For example, you could decide that each ListNode is owned by its predecessor:
std::unique_ptr<ListNode<type>> next;
ListNode<type>* prev;
and that the List container owns the head node of the list
std::unique_ptr<ListNode<type>> start;
ListNode<type>* last;
This way the compiler will do a lot of your work for you at compile-time, and you wont have to depend so much on using valgrind at runtime.

new dynamic allocation vs normal allocation

what's the difference between these two methods?
Method(CustomClass t)
{
CustomClass *temp = &t;
}
called like this
Method(CustomClass(1,2,3));
and
Method(CustomClass* t)
{
CustomClass *temp = t;
}
called like this
Method(new CustomClass(1,2,3));
i haven't coded in c++ for a few years now and am having some trouble remembering. I'm coming from c# where every class need to be dynamically allocated with 'new'. The thing is that i don't undertand the difference between alocating an object dynamically with 'new' and calling it normally. How does temp differ in the 2 examples?
More specific example: I was creating a linked list and for my list i had this method:
void List::AddNew(TestClass node)
{
if (!first)
{
first = &node;
}
else
{
bool setFirst = false;
if (!last)
setFirst = true;
TestClass *temp;
temp = last;
last = &node;
if (temp)
temp->next = last;
if (setFirst)
first->next = last;
}
}
where first and last are TestClass *; the list wasn't initialized correctly (first and last pointed to the same value) and i had no idea why, so i changed the method to this:
void List::AddNew(TestClass* node)
{
if (!first)
{
first = node;
}
else
{
bool setFirst = false;
if (!last)
setFirst = true;
TestClass *temp;
temp = last;
last = node;
if (temp)
temp->next = last;
if (setFirst)
first->next = last;
}
}
and now it works. I'm missing a basic principle for pointers and i can't seem to guess that it is.
Here is TestClass also:
class TestClass
{
public:
int x, y;
TestClass *next;
TestClass *prev;
TestClass();
TestClass(int,int);
~TestClass();
};
what's the difference between these two methods?
One of them is using stack (automatic) allocation, while the other is using heap (dynamic) allocation.
Method(CustomClass(1,2,3)); // stack based
Method(new CustomClass(1,2,3)); // heap based
If you're going to use new you need to make sure you delete that reference also. Otherwise, you'll have a memory leak.
yes, i know this but what's the real defference between the
allocations and when should i use one or the other?
Object lifetime. If you put something on the stack, you will only be able to use it within a particular function, and any functions below it will need it passed as a parameter. If you put it on the heap, you can return a reference to it and use it wherever you want. You can't return a reference / address to a stack variable since it's life ends when the function returns.
I think you're most confused about when to use dynamic-allocation vs when to use stack-allocation. The only thing to know is that you should use stack-based allocation when there is no need for dynamic-based allocation. When is dynamic- (or heap) allocation needed you ask? Well, normally you would use it when you need an object to exist beyond the scope in which it was created or when the contents of that dynamically-allocated object rely on a strictly runtime mechanism (like the addition of elements to a vector (the size may not be known at compile-time)). Also, this...
T* t = &t;
Is not heap-allocation. This is simply a pointer with automatic-storage duration (on the stack) pointing to another object on the stack (if t is itself stack-based). Allocation on the heap happens only when new is used.
CustomClass *temp;
temp is only a pointer. It points to NULL(ok, actually it can point everywhere, but you should set it to NULL if no object exists) or to a already existing class.
CustomClass tmp;
Creates a object.
Method(CustomClass* t):
Demands for a already existing Object (t = pointer to existing object).
CustomClass *temp = t;
Assigns the pointer to a new local pointer.
Method(CustomClass t):
Should create a copy of the class you pass (not sure...)
CustomClass *temp = &t;
& = Adress-Operator. Retrieves address of t and saves it to the local pointer temp.
mfg

Pointers and reference issue

I'm creating something similar to structure list. At the beginning of main I declare a null pointer. Then I call insert() function a couple of times, passing reference to that pointer, to add new elements.
However, something seems to be wrong. I can't display the list's element, std::cout just breaks the program, even though it compiler without a warning.
#include <iostream>
struct node {
node *p, *left, *right;
int key;
};
void insert(node *&root, const int key)
{
node newElement = {};
newElement.key = key;
node *y = NULL;
std::cout << root->key; // this line
while(root)
{
if(key == root->key) exit(EXIT_FAILURE);
y = root;
root = (key < root->key) ? root->left : root->right;
}
newElement.p = y;
if(!y) root = &newElement;
else if(key < y->key) y->left = &newElement;
else y->right = &newElement;
}
int main()
{
node *root = NULL;
insert(root, 5);
std::cout << root->key; // works perfectly if I delete cout in insert()
insert(root, 2);
std::cout << root->key; // program breaks before this line
return 0;
}
As you can see, I create new structure element in insert function and save it inside the root pointer. In the first call, while loop isn't even initiated so it works, and I'm able to display root's element in the main function.
But in the second call, while loop already works, and I get the problem I described.
There's something wrong with root->key syntax because it doesn't work even if I place this in the first call.
What's wrong, and what's the reason?
Also, I've always seen inserting new list's elements through pointers like this:
node newElement = new node();
newElement->key = 5;
root->next = newElement;
Is this code equal to:
node newElement = {};
newElement.key = 5;
root->next = &newElement;
? It would be a bit cleaner, and there wouldn't be need to delete memory.
The problem is because you are passing a pointer to a local variable out of a function. Dereferencing such pointers is undefined behavior. You should allocate newElement with new.
This code
node newElement = {};
creates a local variable newElement. Once the function is over, the scope of newElement ends, and its memory gets destroyed. However, you are passing the pointer to that destroyed memory to outside the function. All references to that memory become invalid as soon as the function exits.
This code, on the other hand
node *newElement = new node(); // Don't forget the asterisk
allocates an object on free store. Such objects remain available until you delete them explicitly. That's why you can use them after the function creating them has exited. Of course since newElement is a pointer, you need to use -> to access its members.
The key thing you need to learn here is the difference between stack allocated objects and heap allocated objects. In your insert function your node newElement = {} is stack allocated, which means that its life time is determined by the enclosing scope. In this case that means that when the function exits your object is destroyed. That's not what you want. You want the root of your tree to stored in your node *root pointer. To do that you need to allocate memory from the heap. In C++ that is normally done with the new operator. That allows you to pass the pointer from one function to another without having its life time determined by the scope that it's in. This also means you need to be careful about managing the life time of heap allocated objects.
Well you have got one problem with your Also comment. The second may be cleaner but it is wrong. You have to new memory and delete it. Otherwise you end up with pointers to objects which no longer exist. That's exactly the problem that new solves.
Another problem
void insert(node *&root, const int key)
{
node newElement = {};
newElement.key = key;
node *y = NULL;
std::cout << root->key; // this line
On the first insert root is still NULL, so this code will crash the program.
It's already been explained that you would have to allocate objects dynamically (with new), however doing so is fraught with perils (memory leaks).
There are two (simple) solutions:
Have an ownership scheme.
Use an arena to put your nodes, and keep references to them.
1 Ownership scheme
In C and C++, there are two forms of obtaining memory where to store an object: automatic storage and dynamic storage. Automatic is what you use when you declare a variable within your function, for example, however such objects only live for the duration of the function (and thus you have issues when using them afterward because the memory is probably overwritten by something else). Therefore you often must use dynamic memory allocation.
The issue with dynamic memory allocation is that you have to explicitly give it back to the system, lest it leaks. In C this is pretty difficult and requires rigor. In C++ though it's made easier by the use of smart pointers. So let's use those!
struct Node {
Node(Node* p, int k): parent(p), key(k) {}
Node* parent;
std::unique_ptr<Node> left, right;
int key;
};
// Note: I added a *constructor* to the type to initialize `parent` and `key`
// without proper initialization they would have some garbage value.
Note the different declaration of parent and left ? A parent owns its children (unique_ptr) whereas a child just refers to its parent.
void insert(std::unique_ptr<Node>& root, const int key)
{
if (root.get() == nullptr) {
root.reset(new Node{nullptr, key});
return;
}
Node* parent = root.get();
Node* y = nullptr;
while(parent)
{
if(key == parent->key) exit(EXIT_FAILURE);
y = parent;
parent = (key < parent->key) ? parent->left.get() : parent->right.get();
}
if (key < y->key) { y->left.reset(new Node{y, key}); }
else { y->right.reset(new Node{y, key}); }
}
In case you don't know what unique_ptr is, the get() it just contains an object allocated with new and the get() method returns a pointer to that object. You can also reset its content (in which case it properly disposes of the object it already contained, if any).
I would note I am not too sure about your algorithm, but hey, it's yours :)
2 Arena
If this dealing with memory got your head all mushy, that's pretty normal at first, and that's why sometimes arenas might be easier to use. The idea of using an arena is pretty general; instead of bothering with memory ownership on a piece by piece basis you use "something" to hold onto the memory and then only manipulate references (or pointers) to the pieces. You just have to keep in mind that those references/pointers are only ever alive as long as the arena is.
struct Node {
Node(): parent(nullptr), left(nullptr), right(nullptr), key(0) {}
Node* parent;
Node* left;
Node* right;
int key;
};
void insert(std::list<Node>& arena, Node *&root, const int key)
{
arena.push_back(Node{}); // add a new node
Node& newElement = arena.back(); // get a reference to it.
newElement.key = key;
Node *y = NULL;
while(root)
{
if(key == root->key) exit(EXIT_FAILURE);
y = root;
root = (key < root->key) ? root->left : root->right;
}
newElement.p = y;
if(!y) root = &newElement;
else if(key < y->key) y->left = &newElement;
else y->right = &newElement;
}
Just remember two things:
as soon as your arena dies, all your references/pointers are pointing into the ether, and bad things happen should you try to use them
if you ever only push things into the arena, it'll grow until it consumes all available memory and your program crashes; at some point you need cleanup!