Why does this function give me a segmentation fault? - c++

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

Related

How to delete a node pointer

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

C++ Where is the seg fault?

I am currently tackling this assignment for my computer science class:
Make your own dynamic array template. It should allow creating contiguous arrays (filled with things of the same type) which you can extend without worrying about running out of space.
Do one version using malloc and free.
Do one version using new and delete.
My version using new and delete works flawlessly; however, in trying to convert my new/delete code to using malloc/free, I keep getting a seg fault. I have narrowed down the segfault (I think), to being in a single function: addData. Take a look at the code in my main I used to test this:
Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3->addData(7);
testArray4->printArray();
return 0;
This gives a seg fault; however, when I change it to this:
Array2<int> *testArray3 = new Array2<int>(5);
Array2<int> *testArray4;
testArray3->initArray();
testArray3->printArray();
testArray4 = testArray3; //->addData(7);
testArray4->printArray();
return 0;
There is no seg fault. This makes me believe the issue is in my addData function. Here is the code for that:
Array2<T> *addData(T dataToAdd){
Array2 <T> *tmp;
tmp->data = this->getData();
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
free(tmp->data);
free(this->data);
return newData;
};
I am new to programming as a whole and have not completely wrapped my head around pointers and memory allocation, etc. Any advice you could give me would be greatly appreciated! In case you need to see the rest of the code, here is the entire file I coded my template in. Thank you so much for your time!
#include <iostream>
#include <string>
#include <cstdlib>
#include <sstream>
using namespace std;
template<typename T>
class Array2{
public:
Array2(int size){
this->size = size;
data = (T *) malloc(sizeof(T)*size);
};
Array2<T> *addData(T dataToAdd){
Array2 <T> *tmp;
tmp->data = this->getData();
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
free(tmp->data);
free(this->data);
return newData;
};
~Array2(){
free(this->data);
};
void initArray(){
for (int i = 0; i < this->size; ++i){
//this->data[i] = i;
this->setData(i, i);
}
};
void printArray(){
//ostringstream oss;
string answer = "";
for (int i = 0; i < this->size; ++i){
//oss << this->data[i] + " ";
cout << this->data[i] << " ";
}
//answer = oss.str();
cout << answer << endl;
};
T* getData(){
return this->data;
}
int getSize(){
return this->size;
}
void setData(T data, int index){
this->getData()[index] = data;
}
private:
int size;
T* data;
};
Array2 <T> *tmp;
Allocates a pointer. This does not point the pointer at anything or allocate any storage for the pointer to point at. What it points at without being explicitly assigned is undefined. If you are lucky, and you are this time, tmp points at an invalid location and the program crashes. If you are unlucky, tmp points at some usable region of program memory and lets you write over it, destroying whatever information was there.
tmp->data = this->getData();
Attempts to access the data member at tmp, but fortunately for you the access is in invalid memory and the program comes to a halt. It also has tmp's data pointing at this's data, and that's a dangerous position to be in. Changes to one will happen to the other because they both use the same storage. Also think about what will happen to this->data if you free tmp->data.
Or perhaps I'm wrong and the halt is here for the same reason:
Array2 <T> *newData;
newData->data = (T *) malloc(sizeof(T)*(this->size + 1));
Both need to be fixed. tmp doesn't have to live long, so we can make it a temporary local variable.
Array2 <T> tmp;
Typically this will be created on the stack and destroyed when the function ends and tmp goes out of scope.
But this will not work because Array2's constructor requires a size so it can allocate the array's storage. You need to find out how big to make it. Probably something along the lines of:
Array2 <T> tmp(this->size + 1);
But frankly I don't think you need tmp at all. You should be able to copy the dataToAdd directly into newData without using tmp as an intermediary.
newData is eventually going to be returned to the caller, so it needs a longer scope. Time to use new.
Array2 <T> *newData = new Array2 <T>(this->size + 1);
And through the magic of the constructor... Wait a sec. Can't use new. That makes this hard. malloc doesn't call constructors, so while malloc will allocate resources for newData, it doesn't do the grunt work to set newData up properly. Rule of thumb is Never malloc An Object. There will be exceptions I'm sure, but you shouldn't be asked for this. I recommend using new here and politely telling the instructor they are on crack if they complain.
Anyway, new Array2 <T>(this->size + 1) will allocate the data storage for you with it's constructor.
There is an easier way to do this next bit
for (int i = 0; i < tmp->getSize() + 1; ++i){
if (i < tmp->getSize()){
//newData->data[i] = tmp->data[i];
newData->setData(tmp->getData()[i], i);
}
else{
//newData->data[i] = dataToAdd;
newData->setData(dataToAdd, i);
}
}
Try:
for (int i = 0; i < tmp->size; ++i){
newData->data[i] = tmp->data[i]; // you were right here
}
newData->data[tmp->size] = dataToAdd;
And back to something I hinted at earlier:
free(tmp->data);
free(this->data);
Both tmp->data and this->data point to the same memory. To be honest I'm not sure what happens if you free the same memory twice, but I doubt it's good. Regardless, I don't think you want to free it. That would leave this in a broken state.
Recap and fixes
Array2<T> *addData(T dataToAdd)
{
Array2 <T> *newData = new Array2 <T>(this->size + 1);
for (int i = 0; i < this->size; ++i)
{
newData->data[i] = this->data[i];
}
newData->data[this->size] = dataToAdd;
return newData;
};
This version leaves this intact and returns a newData that is one bigger than this. What it doesn't do is add anything to this. Which is goofy for a method named addData.
It also leads to stuff like this:
mydata = myData->addData(data);
which leaks memory. The original mydata is lost without deletion, resulting in a memory leak.
What I think you really need is a lot simpler:
Array2<T> & addData(T dataToAdd)
{
this->data = realloc(this->data, this->size + 1);
this->data[this->size] = dataToAdd;
this->size++;
return *this;
};
realloc effectively allocates a new buffer, copies the old buffer into the new one, and frees the old buffer all in one fell swoop. Groovy.
We then add the new element and increment the count of elements stored.
Finally we return a reference to the object so it can be used in a chain.
Usage can be
myData.addData(data);
myData.addData(data).addData(moredata);
myData.addData(data).printArray();
and if you have operator << support written
std::cout << myData.addData(data) << std::endl;
I'd go back over the new version of Array if I were you. Most of the bugs picked off here are conceptual errors and also apply to it. You might just be getting unlucky and it merely looks like it works. I just read C++ Calling Template Function Error. The posted solutions fixed the immediate problem, but did not touch the underlying memory management problems.
As for the rest of your class, I advice following the link and answering What is The Rule of Three? Because Array2 violates the heck out of it.

Segmentation Error C++

I am fairly new to the C++ language and I am trying to write a recursive method to traverse a tree. I have a traverse method but there is one line of code that causes a segmentation fault. I have tested this by commenting and uncommenting the line, compiling and executing. I have researched why segmentation errors are caused and do not see why any of what I am doing is causing a problem with the memory. Can someone give me advice about what I am doing wrong?
map<int, Node> theNodes;
void initialize()
{
// first we read the data
while (inStream.hasNext())
{
string nextLine = inStream.nextLine();
Node newNode = Node(nextLine);
this->theNodes[newNode.getSequence()] = newNode;
}
}
Code for getDownLinks() and getSequence
vector<int> downLinks;
int sequence;
vector<int> Node::getDownLinks() const
{
return this->downLinks; //
}
int Node::getSequence() const
{
return this->sequence;
}
Traversal Class Code
int totalPayoff;
Node headNode;
int Traversal::traverse()
{
Node headNode = theNodes[0];
std::vector<int> downLinks = headNode.getDownLinks();
for(int i = 0; i < downLinks.size(); i++)
{
int a = 0;
Node currentNode = theNodes[downLinks[i]];
traverseInner(a, currentNode);
}
return this->totalPayoff;
}
Here is the traverseInner function
int Traversal::traverseInner(int& level, Node& node)
{
std::vector<int> nodeDownLinks = node.getDownLinks();
if(nodeDownLinks.size() == 0)
{
totalPayoff = totalPayoff + node.getPayoff();
return 0;
}
for(int i = 0; i < nodeDownLinks.size(); i++)
{
int a = 0;
Node currentNode = theNodes[nodeDownLinks[i]]; <-- This causes segmentation error.
traverseInner(a, currentNode);
}
return totalPayoff;
}
Any variables that are not declared here are declared in the header file. The code compiles fine.
I'd also like to mention that I have written this code in many different ways and through my observations have come to the conclusion that any variable that is trying to be accessed in the braces of a nested statement cannot be accessed by the memory. Even the int a variable that is declared right above the problem statement and even hard coded data which is supposed to be there such as nodeDownLinks. If I try to print out through standard output the size of the vector inside one of the nested statements, I also get a segmentation error.
Probably the value inside "nodeDownLinks[i]" it is not initialized, having a memory random value, then you are trying to access this position in the
"theNodes" array and gives to you the segmentation fault.
Please, be sure the values inside "nodeDownLinks" are initialized.
99% it crashes because theNodes has less size, then nodeDownLinks[i] contains index. So nodeDownLinks[i] contains wrong index, u'd better check it and print what goes wrong this way:
int a = 0;
int link = nodeDownLinks[i];
if (theNodes.size() <= link)
std::err << "Wrong link " << link << " in Node" << std::endl;
else
traverseInner(a, theNodes[link]);
It shouldnt crash and you can find wrong index in nodeDownLink easily!

Frustrating pointer error

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!)

Crash when deleting a pointer

I have an assignment to create a PriorityQueue structure and I'm having trouble with this piece of code. When I compile it on my compilator everything's fine, but I tried submitting it to ideone and I get the following error:
"glibc detected *** ./prog: double free or corruption".
I was able to track the part that was giving me this error and I found out that what causes the crash is me trying to delete a pointer at the destructor of my class. The problem is that I don't know why I cant delete it. I don't know a lot about pointers but I thought that if I used new to allocate memory I had to delete it after using it and I think this is what I'm trying to do. Here is my code:
struct PriorityQueue
{
LinkedList queue; LinkNode *it,*node;
int sz;
PriorityQueue(){
sz=0;
queue.head=NULL;
queue.tail=NULL;
it = NULL;
node=NULL;
}
~PriorityQueue(){
if(node != NULL) //this is causing the error.
delete [] node;
if(it != NULL)
delete [] it;
}
int size(){
return sz;
}
void enqueue(int x){
node = new LinkNode(x,NULL,NULL);
if(sz==0){
queue.insert_head(x);
sz++;
}
else{
if(x <= queue.head->value ){
queue.insert_head(x);
sz++;
}
else if( x>= queue.tail->value ){
queue.insert_tail(x);
sz++;
}
else{
it = queue.head;
for(int k=0;k<sz;k++){
if( (x>= it->value) && (x <= it->next->value) ){
node->next= it->next;
node->previous = it;
it->next->previous = node;
it->next = node;
sz++;
break;
}
it=it->next;
}
}
}
}
int dequeue_min(){
int min = queue.remove_head();
sz--;
return min;
}
int dequeue_max(){
int max= queue.remove_tail();
sz--;
return max;
}
};
int main()
{
PriorityQueue pq;
pq.enqueue(4);
pq.enqueue(2);
pq.enqueue(7);
pq.enqueue(-6);
pq.enqueue(0);
cout << pq.dequeue_min() << endl; // debe imprimir -6
cout << pq.dequeue_min() << endl; // debe imprimir 0
pq.enqueue(3);
cout << pq.dequeue_min() << endl; // debe imprimir 2
cout << pq.dequeue_min() << endl; // debe imprimir 3
return 0;
}
Thanks.
it and node point to objects, not arrays.
You cannot use the array form of delete[] on them.
Using delete[] will try to remove a pointer whose object is an array of some sort. There is another type of delete, that allows for the deletion of pointers to single objects. (Hint: it's pretty intuitive)
You are deleting it and node using delete []. They are not arrays. You can only use delete [] syntax on arrays or arrays of your objects. Remember the rule of thumb to use the similar delete and new commands for the same data types. If you have allocated memory by new, delete by delete. If you have allocated memory by new [], delete it by deete [].
It seems that it and node not only point to objects rather than arrays, as Slaks pointed out, it seems they also potentially point to the same thing. As a side note, you don't need to check for null before calling delete[] p or delete p: If the pointer p is null, this expression will have no effect.
It is unrelated to your question but please also note that your priority queue as O(n) (with n being the size) complexity. Typically, when implementing a priority queue you want to get O(log(n)) complexity. The easiest strategy to implement such a priority queue is a d-heap which, conveniently, lives in an array and is actually easier to maintain than your linked list (I think, at least).