Not sure what is going on with my code. Was implementing a simple binary search tree and got everything to work - had no problem inserting a bunch of elements. Then, while trying to add some file IO functionalities, all of the sudden my program was crashing. I thought perhaps I had messed something up with the file pointers and writing (though that doesn't really make sense either, since it leaves the rest of the code untouched), so I pulled up an archived version of the code, and BAM - crashing after 2 inputs even though it was fully working the last time I tried it!
Adding a bunch of debug print statements (sorry still need to learn to use the debugger), it seems the crash most often occurs at my malloc - but sometimes it randomly crashes at different points if I keep rerunning the program too.
I'm really confused by this. How is it that I was able to insert ~10 elements and now I somehow cant even insert 3? Task manager says I have ~4Gb of RAM free, and it's not like I'm doing some massive amount of inputs - this should cost memory absolutely nothing. Also how is it crashing in different places even though I'm running the exact same code?
I'd be very grateful for any insights. Running Windows 10, Codeblocks as the IDE. Code for the main and the function in question below. In most of my runs, the program crashes before the third insert reaches "Space Allocated", but sometimes it manages to insert it - and then the program crashes anyways, for no apparent reason.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node *BSTREE;
struct node
{
int data;
BSTREE left;
BSTREE right;
};
BSTREE insert(BSTREE root, int number);
BSTREE find(BSTREE root, int number);
void inOrderTraversal(BSTREE subtree);
int main(){
BSTREE root = NULL;
root = (insert(root, 2));
insert(root, 4);
insert(root, 1);
}
BSTREE insert(BSTREE root, int number)
{
printf("\n\nInside insert");
BSTREE temp = NULL;
if(!(root)){
printf("\nInside empty root");
temp = (BSTREE*)malloc(sizeof(BSTREE));
printf("\nSpace allocated");
temp->left = NULL;
temp->right = NULL;
printf("\nleft and right set to null");
temp->data = number;
printf("\n data set to number");
root = temp;
printf("\nroot is now temp; Before returning root");
printf("\n node data: %d %d %d", root->data, root->left, root->right);
return root;
}
if(number < root->data){
root->left = (insert(root->left, number));
}
else if(number > root->data){
root->right = (insert(root->right, number));
}
else if(number == root->data){
return root;
}
}
The line:
temp = (BSTREE*)malloc(sizeof(BSTREE));
is an excellent example of why Is it a good idea to typedef pointers? recommends 'No'.
You have two problems:
You're allocating a pointer to a pointer to a struct node to a pointer to a struct node — you don't need the * in the cast (and there are those who'd argue you don't need to cast the result of malloc()).
You're only allocating enough space for a pointer but you're using it as if it was big enough to hold a struct node; it isn't.
The basic fix is one of these lines:
temp = (BSTREE)malloc(sizeof(struct node));
temp = malloc(sizeof(*temp));
There isn't a way to use BSTREE in the first sizeof operator that I can think of. The second is actually a sound technique; it remains valid even if the type of temp changes. You can create various hybrids too.
I'd recommend using:
typedef struct BSTree BSTree;
struct BSTree
{
int data;
BSTree *left;
BSTree *right;
};
and then you'd write:
BSTree *temp;
temp = (BSTree *)malloc(sizeof(BSTree));
temp = malloc(sizeof(*temp));
You might note that the second alternative hasn't changed.
It seems as you are not returning the memory that you reserve with malloc. When using dynamic memory, it's important to release it again, otherwise you'll have a so called memory leak and the size will just increase until program crashes.
Function for releasing (freeing) memory is free();
A call should look something like free(temp);
I can not try it to make sure because I don't have your library used so I can't guarantee it works, but I hope it solves it.
Related
I tried searching for this problem, and couldn't find any answers. I wrote a program that implements a stack, and its operations, with linked lists. The program compiles and runs perfectly on a C Web IDE.
When I run the program in Visual Studio, it fails and gives me the following error:
Debug Error!
Program: C:\Users... my file path
HEAP CORRUPTION DETECTED: after Normal block (#78) at 0x011058C8.
CRT detected that the application wrote to memory after end of heap buffer.
As my code runs fine elsewhere, this must be some issue with how I am using Visual Studio. Any ideas? I am new to Visual Studio, and am afraid this might be something stupid, but I can't seem to figure it out.
I have included my code below, note that the failure is caused by the pop() function in Visual Studio.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
struct Node* top = NULL; //initialize head
void push(int x);
void push(int x) {
struct Node* add = (struct Node*)malloc(sizeof(struct Node*));
add->data = x;
add->next = top; //make add point to what top (head) points to (old 1st)
top = add; //make top point to add (new 1st)
}
void pop();
void pop() {
if (top == NULL) return;
struct Node* temp = top;
top = top->next;
free(temp);
}
int topp();
int topp() {
return top->data;
}
int exist();
int exist() {
if (top->next) {
return 1;
}
else {
return 0;
}
}
void PrintIt();
void PrintIt() {
struct Node* temp = top;
while (temp!= NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
push(1); PrintIt();
push(44); PrintIt();
push(23); PrintIt();
pop(); PrintIt();
push(9); PrintIt();
return 0;
}
If you are doing something that is undefined behaviour (dynamic memory allocation is a real hot-bed of these issues), one of the undefined things that may happen is that it will work just fine.
That by no means indicates that you're doing the right thing, UB is something that should be avoided since it may act differently on another system, another compiler, or even next Tuesday at 3:05 pm :-)
A couple of things I will mention:
you don't need all those function declarations (the prototypes) immeditely before the definitions. A definition acts as a declaration if it hasn't already been declared.
your exist() function is likely to crash for an empty list since it dereferences top. If your intent is to detect a non-empty list, you can just use return (top != NULL);.
you shouldn't explicitly cast the return value of malloc in C, it can cause certain subtle errors.
And, in fact, while looking at that last bullet point, there's your error (not specifically to do with casting, just that it's on that particular line):
struct Node* add = (struct Node*)malloc(sizeof(struct Node*));
// ^
// oops!
The size of struct Node* is the size of a pointer to your structure, commonly (but not necessarily) four or eight octets. Given your actual structure has an integer and a pointer, that size is not going to be big enough.
It may work on some systems that provide a minimum dynamic memory allocation but it's definitely not advised. You should be doing:
struct Node *add = malloc(sizeof(struct Node));
// ^^^^^^^^^^^
// size of the node, not pointer
That line has both the cast removed, and the correct size.
I can't seem for the life of me figure out what the is wrong with my code in the deletion of a whole BST.
I figure since there doesn't seem to be a problem with this:
void emptyTree(BST **root){
if((*root)!=NULL){
emptyTree(&(*root)->left);
emptyTree(&(*root)->right);
free(*root);
}
}
Then the whole problem lies with the initial entry of each node in the tree. Can anyone point out what's wrong here?
void insertNode(BST **root, BST *temp){
if((*root)!=NULL){
temp->parent = *root;
if(((*root)->value) < (temp->value))
insertNode(&(*root)->right,temp);
else if(((*root)->value) > (temp->value))
insertNode(&(*root)->left,temp);
else if(((*root)->value) == (temp->value)){
printf("The number %i is already in the tree.\n",temp->value);
return;
}
} else {
*root = temp;
printf("%i was added to the tree.\n",temp->value);
return;
}
}
void newNode(BST **root, int x){
BST *newnode;
newnode = (BST *)malloc(sizeof(BST));
newnode->value = x;
newnode->left = newnode->right = newnode->parent = NULL;
insertNode(root,newnode);
}
It compiles, it runs, it does absolutely every function right(including one that deletes one node at a time). Except the 'Delete All'(emptyTree) one. It doesn't delete everything(?). It doesn't even show an error when I run through the emptyTree function. It only errors when I printf the whole tree.
The error occurs because you do free all data, but forget to indicate that your elements no longer contain valid data.
That is, after deleting, all elements' left and right members, and your own root itself still contain a value; they still contain the original values, but these no longer point to valid, allocated, memory.
The error does not directly occur within emptyTree because this works from the end nodes up to the top, and there is no reason to check "down". But as soon as you attempt to print root (and its descendants), you are accessing unallocated memory.
Insert
*root = NULL;
in your emptyTree function after
free(*root);
to fix it inside the emptyTree function, or set root to NULL after calling emptyTree.
Personally, I prefer the former, even though it's a minor overhead. That way, you only have a single function to delete a tree, instead of the recursive one plus a wrapper that also sets the root to NULL.
I have posted the link to my BST code on ideone: http://ideone.com/P7850n
In the main function I am getting an error when I read values in the while loop and insert into BST, but it works fine if I use a for loop. What could be the possible explanation for this error which occurs only with the while loop ?
#include <stdio.h>
#include <stdlib.h>
//data struct for BST node
typedef struct BST
{
int data;
struct BST *left;
struct BST *right;
}node;
//make node from given data
node* makeNode(int data)
{
node *n=(node*)malloc(sizeof(node));
n->data=data;
n->left=NULL;
n->right=NULL;
return n;
}
//insert node in BST
node* insert(node* root,int key)
{
if(root==NULL)
return makeNode(key);
if(key < root->data)
root->left=insert(root->left,key);
else
root->right=insert(root->right,key);
return root;
}
//inorder printing prints in sorted order
void inorder(node* root)
{
if(root==NULL)
return;
inorder(root->left);
printf("%d ",root->data);
inorder(root->right);
}
//driver function
int main(void) {
// your code goes here
node *root;
int s,i,key;
scanf("%d",&s);
while(s--)
//for(i=0;i<s;i++)
{
scanf("%d",&key);
root=insert(root,key);
}
inorder(root);
return 0;
}
Most probably this is an uninitialized variable root.
The compiler re-uses the same memory for variables, either declared in your program or used internally, after they are not anymore needed, so that other variables later occupy the same memory. In C (unlike, say, Perl), when memory is assigned to a variable, it is not automatically cleared: you should do it yourself, which is called initialization: typically as soon as you declare a variable, you should assign it some value: int year = 2014;. If you use a variable before you assign it a value, it's value will be whatever happens to be in memory that it occupies, left from other variables or even other running programs.
In your case, when you initialize the for loop with i=0, this 0 probably uses the memory later used for root, so accidentally it works. When you initialize the while loop with non-zero s, root uses memory that happens to be non-zero.
The solution is to initialize root = NULL;, and in general it's a good habit to always initialize all variables.
Without node *root = NULL; you are trying to access undefined memory address as root will contain any random data. So you can get valid behavior or any other behavior including crash.
As root is not initialized in inser() function if(root==NULL) may or may not be true and hence you will get different behavior.
This has nothing to do with for or while loop.
its always to initialize any memory variable to NULL or any other variable to 0,while writing any piece of code,otherwise you will always get any unpredictable crash or result.
like in this case,do like this below:
node *root;
int s,i,key;
to
node *root = NULL;
int s =0;
int i = 0;
int key= 0;
When I compile a source file I receive a segmentation fault: 11 error. I have been able to narrow it down, and I know that the error is coming from this function:
struct drecord { /* use this struct for double-linked lists */
int value;
struct drecord *previous;
struct drecord *next;
};
void sort()
{
struct drecord *currentNode;
struct drecord *end;
for(end=head->previous; end!=NULL && end!=head; end=end->previous)
{
for(currentNode = head; currentNode != NULL && currentNode != end; currentNode = currentNode->next)
{
if (currentNode->value > currentNode->next->value)
{
swap(currentNode, currentNode->next);
}
currentNode = currentNode->next;
}
}
printf("\n");
printf("%d", numElements);
while(numElements > 0)
{
currentNode = head;
printf("Sorted elements: %d", currentNode->value);
delete(currentNode->value);
numElements = numElements - 1;
}
}
void swap(struct drecord *drecord1, struct drecord *drecord2)
{
int aux = drecord1->value;
drecord1->value = drecord2->value;
drecord2->value = aux;
}
Even more specifically, I think that it is coming from the part of the code after printf("\n"), because printf("\n") works but nothing past it does. I had thought that it was a problem with the variable numElements, but I have this same exact code in another source file and it works perfectly. numElements is a global variable. What is wrong?
There are a few issues with your code, but let's focus on the one likely to cause the crash you're seeing:
You call delete(currentNode->value); but isn't value an int? At least, that's how you treat it in your implementation of swap. If it is an int, then what exactly are you deleting?
Perhaps your intent was to delete currentNode, instead. But even that is wrong: please note that that while that will successfully delete currentNode (assuming that it was allocated with new of course), it won't change the head pointer. It will continue to point to where it pointed before: the memory you just called delete on.
So, either way, you're screwed and you should rethink what you're doing in that loop.
As a postscript: while this kind of bug is trivial to find even without a debugger by casual inspection of the code, please invest the time to learn how to use a debugger. It's a critical skill for anyone who wants to program and it will pay dividends: not only will it help you track bugs down, but it will give you a deeper understanding of what is happening and make you a better programmer in the process.
This might seem like a silly question to some of you and I know that I get things mixed up quite often but I need to understand the code so I can stop obsessing about it and focus on the real matter of why I need to use it.
So, in the code I see several assignments like this:
struct bst_node** node = root;
node = &(*node)->left;
node = &(*node)->right;
is there an invisible parenthesis here?
node = &((*node)->right);
This example is taken from literateprograms.org.
So to me it seems &(*node) is unnecessary and I might as well just write node->left instead, but the code seems to work where I can't make sense of it and I'm wondering if it's because I'm misunderstanding what's happening at those lines. Particularly, at one place in the code where it is deleting a node by constantly moving the "deleted" data to the bottom of the tree to safely remove the node without having to "break things", I'm lost because I don't get how
old_node = *node;
if ((*node)->left == NULL) {
*node = (*node)->right;
free_node(old_node);
else if ((*node)->right == NULL) {
*node = (*node)->left;
free_node(old_node);
} else {
struct bst_node **pred = &(*node)->left;
while ((*pred)->right != NULL) {
pred = &(*pred)->right;
}
psudo-code: swap values of *pred and *node when the
bottom-right of the left tree of old_node has been found.
recursive call with pred;
}
can keep the tree structure intact. I don't understand how this makes sure the structure is intact and would appreciate some help from somebody who knows what's going on. I interpret node being a local variable on the stack, created at the function call. Since it is a double pointer it points to a location in the stack (I assume this, since they did &(*node) previously to the function call), of either it's own stack or the function before, which then points to said node on the heap.
In the example code above what I think it is supposed to do is switch either left or right, since one of them is NULL, and then switch the one that isn't (assuming the other one isn't NULL?) As I said, I'm not sure about how this would work. My question mostly relates to the fact that I think &(*node) <=> node but I want to know if that's not the case etc.
node = &(*node)->right;
is there an invisible parenthesis here?
node = &((*node)->right);
Yes. It is taking the address of the right member of *node. The -> takes precedence over &; see C++ Operator Precedence (-> is 2 and & is 3 in that list) (it's the same general precedence as C).
So to me it seems &(*node) is unnecessary and I might as well just write node->left instead,
Your premise is off. There is no expression &(*node), as explained above, the & applies to the entire (*node)->left, not (*node).
In that code the double pointers are just that, a pointer to a pointer. Just as this works:
int x = 0;
int *xptr = &x;
*xptr = 5;
assert(x == 5);
This is the same, it changes the value of the pointer x:
int someint;
int *x = &someint;
int **xptr = &x;
*xptr = NULL;
assert(x == NULL);
In that code snippet you posted, assigning a pointer to *node changes the value of the pointer that node points to. So, e.g. (pseudo-ish code):
typedef struct bst_node_ {
struct bst_node_ *left;
struct bst_node_ *right;
} bst_node;
bst_node * construct_node () {
return a pointer to a new bst_node;
}
void create_node (bst_node ** destination_ptr) {
*destination_ptr = construct_node();
}
void somewhere () {
bst_node *n = construct_node();
create_node(&n->left); // after this, n->left points to a new node
create_node(&n->right); // after this, n->right points to a new node
}
Noting again that &n->left is the same as &(n->left) because of precedence rules. I hope that helps.
In C++ you can pass arguments to a function by reference, which is essentially the same as passing a pointer except syntactically it leads to code that is a bit easier to read.
That is useful
&(*node)->left <=>&((*node)->left)
The variable edited by this code is *node. I need the context fo this code to give more info