For the life of me, I can't figure out what is going wrong. I know the error is occurring in the function marked displayQueue below, but all the syntax and logic seems correct.
Visual studio is giving me the error: "Unhandled exception at 0x00215A86 in ex11_1.exe: 0xC0000005: Access violation reading location 0xCDCDCDE1." But really, I have no idea what this is referring to...
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
struct QueueNode {
string data;
QueueNode *link;
};
typedef QueueNode* QueueNodePtr;
class Queue {
public:
// Constructors/Destructor.
Queue();
Queue(const Queue& aQueue);
// Accessors.
bool empty() const;
void displayQueue ();
// Mutators.
void add(string item);
string remove(); // This should probably be replaced with pop and top - especially for displayQueue... empty() in functions can be replaced with count == 0. Yes, I will do this.
private:
QueueNodePtr front; // Points to head of linked-list queue.
QueueNodePtr back; // Points to tail of linked-list queue.
size_t count;
};
int main () {
Queue myQueue;
myQueue.add("abc");
myQueue.add("def");
myQueue.add("ghi");
myQueue.displayQueue(); // The error is here somewhere. abc is printed and but nothing else.
system("pause");
return 0;
}
Queue::Queue() {
front = NULL;
back = NULL;
count = 0;
}
Queue::Queue(const Queue& aQueue) {
front = aQueue.front;
back = aQueue.back;
count = aQueue.count;
}
bool Queue::empty() const {
if (count == 0) {
return 1;
} else {
return 0;
}
}
void Queue::displayQueue () {
// There is a problem here somewhere...
QueueNodePtr here = front;
for (int i = 0; i < count; i++) {
cout << here->data << endl;
here = here->link;
}
}
void Queue::add(string item) {
QueueNodePtr newNode;
newNode = new QueueNode;
if (count == 0) {
// If inserted in an empty queue, back and front point to same element.
newNode->data = item;
// newNode->link = NULL; // Not sure this part is even necessary.
back = newNode;
front = back;
} else {
// Otherwise, leave front pointer where it's at.
newNode->data = item;
newNode->link = back->link;
back = newNode;
}
count ++;
}
string Queue::remove() {
string returnString;
if (count == 0) {
return returnString;
} else if (count == 1) {
returnString = front->data;
front = NULL;
back = front;
count--;
return returnString;
} else {
returnString = front->data;
front = front->link;
count--;
return returnString;
}
}
EDIT: If anyone can give me any tips on using the debugger to solve problems like this, or give me a link that might explain this it would be greatly appreciated.
The error is on this line, but for the sake of learning, I won't give the correct version, just a few hints:
newNode->link = back->link;
At the point where this code is being executed, which node does back point to? What does its link point to? Whose node's link do you need to modify?
As for finding this yourself, you could have used the debugger to figure out which line causes the crash; this would have indicated that something is wrong with a link value.
P.S. Your copy constructor doesn't actually copy the linked list; it just creates a new Queue object that points to the same linked list, so if you add an element to the copy, it will show up in the original Queue.
An access violation at address 0xCDCDCDCD means that your program loaded a pointer from uninitialized storage and then dereferenced it. Microsoft's debugging allocator uses this pattern for newly allocated uninitialized storage, and in a suitable compilation mode, also for stack locations. If you treat such uninitialized storage as a pointer variable, the pattern is recognizeable in that pointer. Moreover, it is almost certainly an invalid pointer that will trigger an exception. So the benefit is that the use of the invalid pointer is caught quickly, and the pattern tells you that the cause is quite likely uninitialized storage (though this is not 100% conclusive).
For example:
struct contains_pointer { char *str; } *ptr = malloc(sizeof *ptr);
strcpy(ptr->str, "abc"); // ptr->str is uninitialized
Or:
int *pint;
*pint = 0; // pint is uninitialized
To have the compiler and library overwrite uninitialized storage with a pattern like CDCDCD... can be quite helpful. You should pinpoint the location of the crash with the debugger, and then work backward from there: where did the pointer value originate and why wasn't it initialized.
(A bad pointer to the address CDCDCDCD could result in other ways: sheer fluke (unlikely) or a use-after-free bug: the program frees some memory but continues to keep a pointer to it, without using it for a while. The memory is then re-allocated to some other part of the program, and marked uninitialized, and by chance, the original user of the pointer makes a use of it, loading a pointer value from the memory. At that moment, a CDCDCDCD pointer results, so it looks like a use-before-init bug, when in fact it's a use-after-free bug. Debugging based on "memory poisoning" patterns is not accurate!)
Related
I am currently trying to create a linked list which has two elements, usernames and seconds. It is supposed to read from a file and save it into two vectors.
I'm not sure why, but when I attempt to collect the data and store it into a linked list, I get a segmentation fault.
I'm kind of in a rutt, I feel like this should work.
Here is my code for main.cpp:
// main.cpp
int main() {
//Collect initial leaderboard data into two parallel vectors
cout << "here";
vector<string> playerNames;
vector<unsigned> playerTimes;
collect_data(playerNames, playerTimes);
cout << "here";
//Create a LeaderBoard object based on the data in the parallel vectors
LeaderBoard players(playerNames, playerTimes);
cout << "Initial leaderboard from https://www.speedrun.com/ac#All_Debts\n";
players.display();
cout << endl;
return 0;
}
//Leaderboard.cpp
LeaderBoard :: LeaderBoard(const vector<string>& usernames, const vector<unsigned>& second) //Combines both vectors to linked list;
{
for (int i = 0; i < usernames.size(); i++)
{
nPlayers_ ++;
Player *ptr = new Player;
ptr = nullptr;
ptr->username = usernames[i];
ptr->seconds = second[i];
if (head_ == nullptr)
{
head_ = ptr;
tail_ = ptr;
}
else
{
while (tail_-> next != nullptr)
{
tail_ = tail_ -> next;
}
tail_->next = ptr;
tail_ = ptr;
}
}
}
Can someone help me, or lead me towards the right direction?
In this part
Player *ptr = new Player;
ptr = nullptr;
ptr->username = usernames[i];
ptr->seconds = second[i];
You are overwriting the pointer to newly created object by nullptr, then dereferencing the nullptr. This will lead to memory leak and Segmentation Fault.
The line
ptr = nullptr;
should be removed from here.
Also it seems you forgot to initialize ptr->next.
ptr->next = nullptr;
should be added after that part.
This code presents some issues.
First of all, you might ditch heap allocation on each iteration of the for loop, using only once the allocation, before entering the loop. This prevents errors such as:
Player *ptr = new Player;
ptr = nullptr;
which causes segmentation fault in your code.
Another problem might be that head_ and tail_ might also be nullptr, so you have to check carefully about both.
You are allocating something on the heap, without caring about deleting the data later.
Why don't you use a std::vectorstd::unique_ptr<Player> to collect all the player scores, so at the end of the program, everything will be deleted?
//Assuming there's a vector like this in Leaderboard.h:
#include <memory>
std::vector<std::unique_ptr<Player>> players_{};
//Leaderboard.cpp
LeaderBoard::LeaderBoard(const vector<string>& usernames, const vector<unsigned>& second) //Combines both vectors to a final list;
{
for (int i = 0; i < usernames.size(); i++)
{
Player p{};
p.username = usernames[i];
p.seconds = second[i];
players_.emplace_back(std::move(Player));
}
}
In this way, you ditch tricky pointer handling problems, allocation problems, segmentation fault all together. As nice result, you have a vector that can be used with a broad range of algorithms
I am a beginner at C++ and am have some issues with 2 separate errors. Unable to access memory and stack overflow.
This is my implementation for a Trie Tree, using pointers, of words containing characters a-z. When running tests, I can successfully add several hundred, or even thousands of nodes without issue, until it eventually crashes. Error: Unable to access memory. I more often get this error when I am trying to run a query and use the "isAWord" function. I also get a stack overflow when I try to run the deconstructor. Any help is appreciate, as I've spent 2 days trying to debug with little success.
#include "Trie.h"
#include <iostream>
#include <iterator>
#include <sstream>
using namespace std;
//sets up tree
Trie::Trie()
{
for (int i = 0; i < ALPH; i++)
this->childs[i] = nullptr;
endNode = false;
}
//add 'userInput' string to trie
void Trie::addAWord(std::string userInput)
{
Trie* start = this;
for (int i = 0; i < userInput.length(); i++)
{
int index = userInput[i] - 'a';
if (start->childs[index] == nullptr)
start->childs[index] = new Trie();
start = start->childs[index];
}
start->endNode = true;
}
//returns true if 'wordFind' is in tree
bool Trie::isAWord(std::string wordFind)
{
if (this == nullptr)
return false;
Trie* start = this;
for (int i = 0; i < wordFind.length(); i++)
{
int index = wordFind[i] - 'a';
start = start->childs[index];
if (start == nullptr)
return false;
}
return start->endNode;
}
//returns a vector containing the words in tree with prefix 'prefFind'
vector<std::string> Trie::allWordsStartingWithPrefix(std::string prefFind)
{
string pres = PrefixRec(prefFind,*this);
stringstream preStream(pres);
istream_iterator<std::string> begin(preStream), end;
vector<std::string> stringSet(begin, end);
copy(stringSet.begin(), stringSet.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
return stringSet;
}
//helper method for AllWordsStartingWithPrefix
std::string Trie::PrefixRec(std::string& key, Trie const temp)
{
if (temp.endNode)
return(key + " ");
for (char index = 0; index < ALPH; ++index)
{
index = key[index] - 'a';
Trie const* curChild = temp.childs[index];
if (curChild)
{
key.push_back(index);
PrefixRec(key, *curChild);
key.pop_back();
}
}
}
//copy cons and assignment op
Trie& Trie::operator=(const Trie& other)
{
Trie* newPtr = new Trie(other);
other.~Trie();
return *newPtr;
}
//deconstructor
Trie::~Trie()
{
if (this == nullptr)
return;
for (int i = 0; i < ALPH; i++)
{
if (childs[i] != nullptr)
childs[i]->~Trie();
}
delete this;
return;
}
#include <iostream>
#include <vector>
#include <string>
#define ALPH 26
class Trie
{
public:
bool endNode;
Trie* childs[ALPH];
Trie();
void addAWord(std::string key);
bool isAWord(std::string key);
std::vector<std::string> allWordsStartingWithPrefix(std::string key);
Trie& operator=(const Trie& other);
std::vector<std::string> wordsWithWildcardPrefix(std::string);
std::string PrefixRec(std::string& key, Trie const temp);
~Trie();
};
I also get a stack overflow when I try to run the deconstructor.
This is because of this line:
delete this;
This is what a delete does
The delete expression invokes the destructor (if any) for the object
that's being destroyed,
You can imagine why calling delete from within the destructor would be problematic. (Hint: Infinite recursion)
You don't want any delete this in your code.
Once you get rid of this, there are other issues.(Although you may live just by fixing this). For instance calling the destructor explicitly as you are doing in this line(and several other lines)
other.~Trie();
From iso cpp:
Should I explicitly call a destructor on a local variable?
No!
The destructor will get called again at the close } of the block in which the local was created. This is a guarantee of the language; it happens automagically; there’s no way to stop it from happening. But you can get really bad results from calling a destructor on the same object a second time! Bang! You’re dead!
Replace the explicit destructor calls with delete and let it call the destructor correctly.
I would recommend replace any raw pointers and new and delete with smart pointer. Start with shared_ptr to begin with. (raw_pointers are so 2010 ;))
Footnote: Get rid of these checks. They are non-idiomatic. It's ok and desirable for the caller to burn when calling a member function on a nullptr
if (this == nullptr)
return false;
This is schoolwork. I haven't seen anything that really answers this directly, so I'm having a hard time fixing it. I have to create a linked node implementation of a max heap and I'm having difficulty with the deletion of a node after removing a value.
My Code:
template<class ItemType>
BinaryHeapNode<ItemType>* LinkedMaxHeap<ItemType>::getLastNode()
{
BinaryHeapNode<ItemType>* lastNode = rootPtr->getRightSiblingPtr();
BinaryHeapNode<ItemType>* prevLastNode = rootPtr;
while(lastNode != nullptr)
{
prevLastNode = lastNode;
lastNode = lastNode->getRightSiblingPtr();
}
return prevLastNode;
}
template<class ItemType>
bool LinkedMaxHeap<ItemType>::removeValue(ItemType value)
{
BinaryHeapNode<ItemType>* tempNode = rootPtr;
for (int i = 0; i < itemCount; i++)
{
if(tempNode->getItem() == value)
{
tempNode->setItem(getLastNode()->getItem());//set item
delete getLastNode(); //delete last node
getLastNode() = nullptr; //set last node null
getLastNode()->setRightSiblingPtr(nullptr); //last node should be different
itemCount--; //set it's sibling to null
heapRebuild(tempNode);
}
tempNode = tempNode->getRightSiblingPtr();
}
return true;
}
My issue is with getLastNode() = nullptr. VS is telling me that getLastNode() isn't an lvalue. That doesn't make sense to me because getLastNode is returning a pointer to a BinaryHeapNode, but it can't set that pointer to nullptr?
I thought this might be a problem with my logic of pointers (which is shaky at best) so I thought changing getLastNode() to return just a node would help. That did not. So I tried messing with the & operator and returning an address of the last node. Needless to say I haven't found the solution yet. If anyone can provide some sort of direction it would be appreciated. I'm just not entirely sure why it doesn't work.
EDIT:
Edited the code based on what arynaq mentioned. The errors went away, but now I have a bunch of linker errors I have to fix before I can test it. Will this code do what I want? I feel like it is just going to delete nodeToDelete and not get rid of the node in the heap.
template<class ItemType>
bool LinkedMaxHeap<ItemType>::removeValue(ItemType value)
{
BinaryHeapNode<ItemType>* tempNode = rootPtr;
BinaryHeapNode<ItemType>* nodeToDelete = getLastNode();
for (int i = 0; i < itemCount; i++)
{
if(tempNode->getItem() == value)
{
tempNode->setItem(nodeToDelete->getItem());
delete &nodeToDelete;
nodeToDelete = nullptr;
getLastNode()->setRightSiblingPtr(nullptr);
itemCount--;
heapRebuild(tempNode);
}
tempNode = tempNode->getRightSiblingPtr();
}
return true;
}
Ok, I'll try to help by explaining some things about pointers. Hopefully this will clarify some misconceptions and help you with your assignment.
When you get a copy of the pointer like so: mypointer* p = get_pointer(); and then you delete that, you are deleting the memory. But when you assign nullptr to this local variable, it wont affect the "source" of your pointer.
Here is a detailed example, showing where things can go wrong. If you never set v[0] to nullptr.
#include <iostream>
#include <vector>
struct Object {
~Object() {
std::cout << "Object destructor." << std::endl;
}
int val = 42;
};
struct OtherObj {
int val = 322;
};
void print_vec(const std::vector<Object*>& v) {
for (const auto& x : v) {
std::cout << x << std::endl;
}
}
int main(int, char**) {
// Init vector and print addresses.
std::vector<Object*> v(2);
print_vec(v);
// Init objects in vector and printit.
for (auto& x : v) {
x = new Object();
}
print_vec(v);
// Get a copy of a pointer and delete that. All good so far.
Object* pointer_to_delete = v[0];
delete pointer_to_delete;
// Assign nullptr to the temporary local pointer.
// Does nothing to the pointer in the vector.
pointer_to_delete = nullptr;
// Print the vector to prove it.
print_vec(v);
// On a non debug build, the memory will still have the last value.
// Careful! Cause of headaches here. This should be set to nullptr.
std::cout << v[0]->val << std::endl; // "No problem", certainly not nullptr.
// Now that we allocate a new object, v[0] will be overwritten.
OtherObj* bad_bad_boy = new OtherObj();
// Print the address of the new object, to show it was created at
// the old v[0] address.
std::cout << bad_bad_boy << std::endl;
// Bad things ensue...
std::cout << v[0]->val << std::endl;
return 0;
}
The output on clang is :
0x0
0x0
0x7ffa21c026c0
0x7ffa21c026d0
Object destructor.
0x7ffa21c026c0
0x7ffa21c026d0
42
0x7ffa21c026c0
322
As you can see, setting the local pointer to nullptr is not enough! I hope this clears up some things for you :)
Online version
When trying to answer a question on stackexchange, I tried to review this piece of code:
#include <iostream>
using namespace std;
struct Node {
int key;
Node *leftnode;
Node *rightnode;
string value;
Node(int tkey, const std::string& tvalue) : leftnode(nullptr), rightnode(nullptr), key(tkey), value(tvalue) {}
};
Node root_node(1, "Node #1"); // Binary search tree
string inline query_bst(const int key) {
Node *cur_node = &root_node;
while (cur_node != NULL) {
if (key == cur_node->key) {
return cur_node->value;
}
if (key < cur_node->key) { /* value already returned, no need for else */
cur_node = cur_node->leftnode;
} else {
cur_node = cur_node->rightnode;
}
}
return ""; // Return empty string if not found
}
void inline insert_bst(int key, string value) {
Node *cur_node;
Node *next_node = &root_node;
// Search through bst for key
while (next_node != NULL) {
cur_node = next_node;
if (key < cur_node->key) {
next_node = cur_node->leftnode;
} else {
next_node = cur_node->rightnode;
}
}
Node new_node(key, value);
next_node = &new_node;
if (key < cur_node->key) {
cur_node->leftnode = next_node;
} else {
cur_node->rightnode = next_node;
}
}
int main() {
root_node.key = 1;
insert_bst(2, "Node #3");
insert_bst(3, "Node #4");
cout << query_bst(3) << '\n' << query_bst(4);
}
For me, this program compiles, but crashes. I searched for the cause of this, and deduced (hopefully correctly) that in function "insert_bst()" a variable named "new_node" is created, and later a pointer is assigned this variable's address. However, the new_node var has an automatic duration, thus it is destroyed at the end of the function's execution. Therefore, during the second call of insert_bst(), when the program tries to access the key/value of the inserted node, trash values are retrived (this I confirmed using a debugger), which ruins the program.
Then why would this piece of code work properly on some other platform?
My tests were done on Windows 7 x64, on Code::Blocks 16.01 and CLion, using g++.
The platform on which the code works: Mac OS X Yosemite Clion, also g++
As you deduced correctly the function is creating a local object and adding that to the BST. When the local object is destroyed when the function returns we now have a dangling pointer and using it is undefined behavior.
Since it is undefined behavior that means that the behavior of the program is undefined. It may run, crash, become self aware and name itself Skynet or anything in between.
As MikeCAT pointed out we can get rid of this undefined behavior by using new to make the node persistent and that gets rid of the dangling pointer issue.
I'm decently experienced with Python and Java, but I recently decided to learn C++. I decided to make a quick integer stack implementation, but it has a massive memory leak that I can't understand. When I pop the node, it doesn't seem to be releasing the memory even though I explicitly delete the old node upon poping it. When I run it, it uses 150mb of memory, but doesn't release any of it after I empty the stack. I would appreciate any help since this is my first foray into a language without garbage collection. This was compiled with gcc 4.3 on 64-bit Kubuntu.
//a trivial linked list based stack of integers
#include <iostream>
using namespace std;
class Node
{
private:
int num;
Node * next;
public:
Node(int data, Node * next);
int getData();
Node * getNext();
};
Node::Node(int data, Node * next_node)
{
num = data;
next = next_node;
}
inline int Node::getData()
{
return num;
}
inline Node* Node::getNext()
{
return next;
}
class Stack
{
private:
unsigned long int n;
Node * top;
public:
Stack(int first);
Stack();
void push(int data);
int pop();
int peek();
unsigned long int getSize();
void print();
void empty();
};
Stack::Stack(int first)
{
Node first_top (first, NULL);
top = &first_top;
n = 1;
}
Stack::Stack()
{
top = NULL;
n = 0;
}
void Stack::push(int data)
{
Node* old_top = top;
Node* new_top = new Node(data,old_top);
top = new_top;
n++;
}
int Stack::pop()
{
Node* old_top = top;
int ret_num = old_top->getData();
top = old_top->getNext();
delete old_top;
n--;
return ret_num;
}
inline int Stack::peek()
{
return top->getData();
}
inline unsigned long int Stack::getSize()
{
return n;
}
void Stack::print()
{
Node* current = top;
cout << "Stack: [";
for(unsigned long int i = 0; i<n-1; i++)
{
cout << current->getData() << ", ";
current = current->getNext();
}
cout << current->getData() << "]" << endl;
}
void Stack::empty()
{
unsigned long int upper = n;
for(unsigned long int i = 0; i<upper; i++)
{
this->pop();
}
}
Stack createStackRange(int start, int end, int step = 1)
{
Stack stack = Stack();
for(int i = start; i <= end; i+=step)
{
stack.push(i);
}
return stack;
}
int main()
{
Stack s = createStackRange(0,5e6);
cout << s.peek() << endl;
sleep(1);
cout << "emptying" <<endl;
s.empty();
cout << "emptied" <<endl;
cout << "The size of the stack is " << s.getSize()<<endl;
cout << "waiting..." << endl;
sleep(10);
return 0;
}
How do you KNOW the memory isn't being released? The runtime library will manage allocations and may not release the memory back to the OS until the program terminates. If that's the case, the memory will be available for other allocations within your program during its execution.
However.... you seem to have other problems. My C++ is really rusty since I've been doing Java for 15 years, but in your Stack::Stack constructor you're allocating a Node instance on the system stack and then storing a reference to it in your "Stack". That Node instance goes out of scope when the constructor ends, leaving a dangling pointer.
Stack::Stack(int first)
{
Node first_top (first, NULL);
top = &first_top;
n = 1;
}
This is wrong , you cant assign address of a local object to class member( top ) , since local objects get destroyed when function returns.
Create a node on heap rather than stack , do something like this :
Stack::Stack(int first)
{
top = new Node(first, NULL);
n = 1;
}
And Make the concept of link list clear and use pen and paper if you can do so.
Your Stack::Push(int) operation seems buggy check it out what you have forget to do.
My suggestion is try to implement generic stack with the help of template ,so it will work for all data type .
When createStackRange() returns it'll return a copy of the Stack using the compiler-generated copy constructor which just makes a bitwise copy (i.e., it'll copy the pointer to the first node and the size.)
More seriously, you're missing the destructor for the Stack class. Ideally you'd have it walk the list and call delete on each Node. The Stack object created on the processor stack will automatically be cleaned up automatically when main() exits, but without a destructor, the nodes will still be allocated when the program ends. You probably want something like this for it:
Stack::~Stack()
{
while ( top )
{
Next *next = top->getNext();
delete top;
top = next;
}
}
The way to think of it is that the C++ compiler will automatically generate copy constructors and destructors for you, but they're normally shallow. If you need deep behavior you've got to do it implement it yourself somewhere.
After poring over the code, I couldn't find the leak so I compiled it and ran it in a debugger myself. I agree with Jim Garrision - I think you're seeing an artifact of the runtime rather than an actual leak, because I'm not seeing it on my side. The issues pointed out by NickLarsen and smith are both actual issues that you want to correct, but if you trace the code through, neither should actually be causing the problem you describe. The code smith singles out is never called in your example, and the code Nick singles out would cause other issues, but not the one you're seeing.
Creat a stub to test your code and user Memory Analysis tool like "Valgrind". This will find out memory leaks and corruptions for you.
check man-pages for more information.
Note that you should only roll your own stack for educational purposes. For any real code, you should use the stack implementation that comes with the C++ standard library...