I started C++ a few hours ago and have been trying to do a simple LinkedList implementation in it to get myself familiar with it, however, I'm stumped as to why this method hasNext() keeps returning true.
#include <iostream>
#include <string>
using namespace std;
struct LinkedNode {
public:
int data;
LinkedNode(int d = 0) {
data = d;
}
void setNext(LinkedNode * linked_node) {
next = linked_node;
}
LinkedNode * getNext() {
return next;
}
bool hasNext() {
return (next != nullptr);
}
private:
LinkedNode * next;
};
int main() {
LinkedNode * linked_list = new LinkedNode(2);
(*linked_list).setNext(new LinkedNode(10));
if (linked_list->getNext()->hasNext()) {
cout << "true";
}
else {
cout << "false";
}
}
This outputs "true", but when I try to access the data since it is supposedly "true" I get the Segmentation fault error, (going to guess it's being raised since I'm trying to get a value that doesn't exist), from linked_list->getNext()->getNext()->data; Can somebody explain why?
The constructor of LinkedNode does not initialise the next member.
That means it is uninitialised. It is not set to zero by default. In fact, accessing its value (before initialising it, or assigning a value to it) gives undefined behaviour.
Set next to be nullptr within the constructor.
You are not initializing next. By default allocating memory just changes a data structure storing information about what memory block is allocated. It does not change the content of this memory block. So you can consider the next pointer be of random data. And since random data is different than null pointer hasNext returns true but when you access the data it is very likely that the random data is interpreted as a pointer into some memory that either does not exist or your application does not has the right to access too. Therefore the result in segmentation / page fault.
To verify this truth just do not initialize data as well, create some nodes and read the data (or even the next pointer). This way you see the randomness which is basically just left overs of content the memory block once hold before it was freed.
PS: Memory blocks are freed and dynamically spliced and combined based on algorithms you can learn. Check out malloc and some other implementations and see the Wikipedia about memory allocation.
You must initialize the value of next to nullptr. By default, the value is undefined (garbage).
Check out member initializer lists:
LinkedNode(int d = 0)
: data( d )
, next( nullptr )
{
}
Or simply assign the values directly in the constructor body:
LinkedNode(int d = 0)
{
data = d;
next = nullptr;
}
Related
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++.
I am currently working on creating a small compiler using C++. I have defined the following objects:
struct ValueNode
{
std::string name;
int value;
};
struct StatementNode
{
StatementType type;
union
{
struct AssignmentStatement * assign_stmt;
struct PrintStatement * print_stmt;
struct IfStatement * if_stmt;
struct GotoStatement * goto_stmt;
};
struct StatementNode * next; // next statement in the list or NULL
};
I have defined a series of functions relating to different types of statements in the language. One of these functions is called parse_assignment_stmt(). The segmentation fault I am experiencing is happening in this function, immediately after attempting to assign a value to recently-allocated memory. Here is that function:
struct StatementNode* parse_assign_stmt() {
//Object to be returned. Holds an object representing a statement
//made within the input program.
struct StatementNode* st = (struct StatementNode*)malloc(sizeof(struct StatementNode));
st->type = ASSIGN_STMT;
//First token should be an ID. Represents memory location we are assigning to.
Token tok = lexer->GetToken();
if(tok.token_type == ID) {
//Second token in an assignment should be an equal sign
Token tok2 = lexer->GetToken();
if (tok2.token_type == EQUAL) {
//This function reads the next token, makes sure it is of type NUM or ID, then creates and returns a ValueNode containing the relevant value.
struct ValueNode* rhs1 = parse_primary();
Token tok3 = lexer->GetToken();
//Assignment format for this logical branch: "x = 5;"
if(tok3.token_type == SEMICOLON) {
//first type
//Allocate memory for objects needed to build StatementNode st
struct AssignmentStatement* assign_stmt = (struct AssignmentStatement*)malloc(sizeof(struct AssignmentStatement));
struct ValueNode* lhs = (struct ValueNode*)malloc( sizeof(struct ValueNode));
printf("Name: %s, Value: %d\n", lhs->name.c_str(), lhs->value);
//PROBLEM ARISES HERE***
//lhs->name = tok.lexeme;
//return the proper structure
return st;
}
else if(tok3.token_type == PLUS || tok3.token_type == MINUS || tok3.token_type == DIV || tok3.token_type == MULT) {
//second type
//TODO
}
else {
printf("Syntax error. Semicolon or operator expected after first primary on RHS of assignment.");
exit(1);
}
}
else {
//not of proper form
printf("Syntax error. EQUAL expected after LHS of assignment.");
exit(1);
}
}
else {
//Not of proper form. Syntax error
printf("Syntax error. ID expected at beginning of assignment.");
exit(1);
}
}
Essentially, I'm allocating memory for a new ValueNode to create the variable lhs. I am printing out the name and value fields immediately to ensure that there isn't anything present. In my compiler output (I'm using g++, by the way), it's telling me that the name is (null) and the value is 0, which is expected. As soon as I uncomment the line
lhs->name = tok.lexeme;
I get a segmentation fault. At this point, I have no idea what could be going wrong. I'm creating the variable, using malloc to allocate memory to the location, making sure that there isn't anything stored there, and then immediately trying to write a value. And it always gives me a segmentation fault.
Here is the input program (.txt file) that is being fed to the program through stdin.
i;
{
i = 42 ;
print i;
}
I have tried using calloc() instead, since that should make sure that the memory is cleared before returning the pointer, but that didn't change anything. Any suggestions would be wonderful. Thank you!
If the problem arises in the line:
lhs->name = tok.lexeme;
then I'd warrant the problem lies with either lhs or tok.lexeme.
Since, prior to that, you appear to have confirmed that lhs is okay with:
printf("Name: %s, Value: %d\n", lhs->name.c_str(), lhs->value);
then the chances that it's an issue with the token structure skyrocket.
However, we shouldn't need to surmise, you should be able to load up the code into a good debugger (or even gdb, in a pinch(a)), set a breakpoint at the offending line, and actually look at the variables to see if they are as expected. Or, at a bare minimum, print out more stuff before trying to use it.
Aside: It's always been a bugbear of mine that the first course taught at university isn't Debugging 101. That's the first thing I taught my son once he started doing Python development.
(a) Pax ducks for cover :-)
After further investigation, I found that when allocating memory (using malloc()) for my ValueNode objects (and for some reason, only these ones), malloc() was returning a pointer to inaccessible memory. The error I received in gdb when trying to print my ValueNode structure was:
{name = <'error reading variable: Cannot access memory at address 0xfffffffe8>, value = 42}
Unfortunately, I was not able to find a way to allocate the memory for this object using malloc(). A workaround that I managed to make happen, however, was to create a constructor within the structure definition of ValueNode, then use "new" to create the object and allocate the memory for me, rather than trying to force malloc() to work. In retrospect, I probably should have used this simpler approach over malloc() to begin with.
When I push a pointer of struct into a std::queue, and then poping the value, the value that I'm getting back would change to zero. I've simplified the actual code to illustrate the problem below. The head pointer in the real code is a class variable and contains other values. If I push head onto the queue, all other values that I get also become uninitialized.
What could be the issue here?
Note: PipePixel *head; is an instance variable declared in the class header file.
Add Head Function:
void LinkedGraph::addHeadPixel(int index) {
PipePixel pixel = {NULL, 433, std::vector<PipePixel*>()};
pixel.index = index;
if (head==NULL) {
pixelMap[index] = &pixel;
head = &pixel;
} else {
printf("Already added head pixel! Px:%d\n", pixelMap[index]->index);
}
}
Print Function: <-- Where problem occurs
std::queue<PipePixel*> printQueue;
printQueue.push(head);
printf("headIndex:%d\n", head->index); // headIndex:433
while (!printQueue.empty()) {
PipePixel *child = printQueue.front();
printf("childIndex:%d\n", child->index); //childIndex:0
printQueue.pop();
if (child == NULL) {
printf("child is null"); // no output
continue;
}
}
PipePixel Struct:
struct PipePixel {
PipePixel *parent;
int index; //pixel index
std::vector<PipePixel*> children;
};
The problem here is that the variable pixel is local inside the LinkedGraph::addHeadPixel function. Once the function returns that object is destructed and the variable ceases to exist. If you have stored a pointer to a local variable, that pointer no longer points to a valid object, and dereferencing the pointer leads to undefined behavior.
My recommendation is to not use pointers at all, but let the compiler handle he object copying. For such small and simple objects its possible performance impact is negligible.
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.
I'm very confused about the following code:
class Tree {
protected:
struct Node {
Node* leftSibling;
Node* rightSibling;
int value;
};
private:
Node* root;
int value;
.....
public:
void addElement(int number) {
if (root == NULL) {
printf("This is the value of the pointer %lld\n",(long long)root);
printf("This is the value of the int %d\n",value);
...
return;
}
printf("NOT NULL\n");
}
};
int main() {
Tree curTree;
srand(time(0));
for(int i = 0;i < 40; ++i) {
curTree.addElement(rand() % 1000);
}
}
The curTree variable is local to the main function so I expected it to not have its members initialized to 0, but they are both initialized.
No, it has unspecified contents. Those contents might be random memory garbage, or they could just happen to be 0, depending on whatever data was left in their memory location beforehand.
It might just happen that due to the way the code was compiled, the particular stack location containing root always has 0 (say, because an earlier local variable occupying that same stack location always ended up as 0). But you cannot rely on this behavior -- you must properly initialize anything before reading it back, otherwise you enter the land of Undefined Behavior.
The actual default value a pointer is implicitly initialized to will depend on the compiler you use.
The Visual C compiler (v2012) will initialize it automatically to __nullptr which is equal to NULL. Have a look at the MSDN doc (see the last example).
I would try to check your compiler manual if you want more information.
You don't initialize root anywhere, proper place to initialize it would be the constructor.