I'm implementing an AVL tree in C. I've posted my tree rotations below, as well as the valgrind errors I get when I try to test them.
Why am I getting these errors? I understand that the valgrind errors stem from the fact that I'm using null pointers, but I can't pinpoint exactly what I'm doing wrong. (I've commented on the lines of the Valgrind errors)
Tree rotateRight(Tree t)
{
Tree temp = t->L;
t->L=temp->R;
temp->R=t;
temp->height=maximum(heightT(temp->L), heightT(temp->R));
t->height=maximum(heightT(t->L), heightT(t->R));
return t;
}
Tree rotateLeft(Tree t)
{
Tree temp = t->R; //This is line 226
t->R=temp->L;
temp->L=t;
temp->height=maximum(heightT(temp->L), heightT(temp->R));
t->height=maximum(heightT(t->L), heightT(t->R));
return t;
}
Tree rotateLeftRight(Tree t)
{
t->L=rotateLeft(t->L); //Line 235
t=rotateRight(t);
return t;
}
Tree rotateRightLeft(Tree t)
{
t->R=rotateRight(t->R);
t=rotateLeft(t);
return t;
}
Valgrind errors(I'm getting the same thing for rotateLeft):
==20073== Invalid read of size 8
==20073== at 0x40196F: rotateLeft (bst.c:226)
==20073== by 0x401A11: rotateLeftRight (bst.c:235)
==20073== by 0x4013A9: insertT (bst.c:69)
==20073== by 0x400E77: addin (Spell13.c:96)
==20073== by 0x400CBE: main (Spell13.c:59)
==20073== Address 0x10 is not stack'd, malloc'd or (recently) free'd
==20073==
==20073==
==20073== Process terminating with default action of signal 11 (SIGSEGV)
Taking the code that you have + the error report, it appears as though Tree would look something like this:
typedef struct Tree_s
{
struct Tree_s *L;
struct Tree_s *R;
} Tree;
It would also appear that Tree->L that was passed to rotateLeftRight was NULL
Related
I'm experimenting with a quadtree implementation found online, but am receiving "pointer being freed was not allocated" errors intermittently as part of the following (stripped down) _node_release function:
static void _node_release(node* node)
{
if(node->subnodes[0])
{
for(size_t i=0;i<4;i++)
{
_node_release(node->subnodes[i]);
free(node->subnodes[i]); // this causes "pointer being freed was not allocated" errors
}
}
// ...
free(node); // the node passed to _node_release is free'd here
}
Would I be correct to assume that node is being incorrectly free'd twice here? The _node_release function free's the node passed to it, but the code is also attempting to free each subsequent subnode after making a recursive call to _node_release.
Yes you are correct with this assumption.
The problem is in your recursive call. Suppose I am a subnode in the recursive call. When I am done calling free on my subnodes, i then execute my last line, free(node) to free myself.
Now i'm the parent of this node. I do the same routine. One of my subnodes, however, was the guy who just freed himself. So when I call free(node->subnodes[i]) I get the error that you see
Yes you are freeing your nodes twice.
1: static void _node_release(node* node)
2: {
3: if(node->subnodes[0])
4: {
5: for(size_t i=0;i<4;i++)
6: {
7: _node_release(node->subnodes[i]);
8: free(node->subnodes[i]); // this causes "pointer being freed was not allocated" errors
9: }
10: }
11: // ...
12:
13: free(node); // the node passed to _node_release is free'd here
14: }
Lets say you have NodeB as a child of NodeA
_free_release(NodeA)
_free_release(NodeB) – line 7
free(NodeB) - line 14
free(NodeB) - line 8
To fix this just remove the free on line 8
static void _node_release(node* node)
{
if(node->subnodes[0])
{
for(size_t i=0;i<4;i++)
{
_node_release(node->subnodes[i]);
}
}
// ...
free(node); // the node passed to _node_release is free'd here
}
I am creating a simple dictionary in C using generic linked lists, thus in the process I am using malloc and free.
Anyway, Valgrind sadly doesn't support OS X 10.9, therefore I am using Xcode's Leaks Instrument. However, I have a bit trouble understanding the feedback this tool is providing me. Simpler, from the data output I can't understand if I have leaks or not.
Here is a screenshot of what the tool is telling me:
link to image
Here is the code that is creating the linked list:
typedef struct Element {
struct Element *next;
void *value;
} TElelemt, *TList, **AList;
typedef void (*PrintF) (void *);
int Insert_Elm(AList list, void *value, size_t dimension) {
TList aux = (TList) malloc(sizeof(TElelemt));
if (!aux) {
printf("Allocation error!\n");
return 0;
}
aux->value = malloc(dimension);
if (!aux->value) {
printf("Allocation error!\n");
return 0;
}
memcpy(aux->value, value, dimension);
aux->next = *list;
*list = aux;
return 1;
}
void Delete_Elm(AList list) {
TList elm = *list;
if (!elm) {
return;
}
free(elm->value);
*list = elm->next;
free(elm);
return;
}
void Delete_List(AList list) {
while (*list) {
Delete_Elm(list);
}
return;
}
// In main() I am doing something like this where TWord cuv is allocated in stack:
for (i = 0; i < 1000000; i++) {
Insert_Elm(&list, &cuv, sizeof(TWord));
}
Delete_List(&list);
What is the tool saying and are there any memory leaks?
Your screenshot is showing no memory leaks. In your screenshot the Allocations instruments has graphed your memory usage in blue. If Instruments had detected any memory leaks, it would show them in the graph for the Leaks instrument. But in your screenshot the graph for the Leaks instrument is blank, which means Instruments detected no memory leaks.
One additional thing, your screenshot is showing the statistics for the Allocations instrument. It's telling you the amount of memory your program allocated. Select the Leaks instrument from the instrument list to see the Leaks instrument's statistics. Selecting the Leaks instrument will also tell you whether or not any memory leaks were detected. If you have any leaks, Instruments will list them in the table below the graphs.
I've been trying to set a pointer to a part of a data structure in C, but valgrind is giving me an error. I recognize this error as one where I'm trying to make a non-pointer into a NULL pointer, but that's not what's happening here. What's wrong?
struct node {
int data;
struct node *before;
struct node *after;
};
struct deque {
struct node *front;
struct node *rear;
};
int createD (Deque *d)
{
printf ("Y\n");
(*d) = malloc(100*sizeof(struct deque));
(*d)->front=NULL;
(*d)->rear=NULL;
return 0;
}
int remD (Deque *d, char **s)
{
struct node *temp;
temp=malloc(100*sizeof(struct node));
int data;
if (isEmptyD(d)==0)
{
printf ("Why?");
return 1;
}
else
{
temp = (*d)->front;
data = temp->data;
(*d)->front=temp->after;
(*d)->front->before=NULL;
if((*d)->front==NULL)
{
(*d)->rear=NULL;
}
(*s)=malloc(100);
(**s)=data;
free(temp);
}
return 0;
}
==30983== Invalid write of size 8
==30983== at 0x4010B5: remD (Deque.c:101)
==30983== by 0x400C98: assign (Merge13.c:134)
==30983== by 0x400BFB: mergesort (Merge13.c:113)
==30983== by 0x400B03: queues (Merge13.c:64)
==30983== by 0x400995: main (Merge13.c:26)
==30983== Address 0x8 is not stack'd, malloc'd or (recently) free'd
==30983==
==30983==
==30983== Process terminating with default action of signal 11 (SIGSEGV)
(The valgrind error is in reference to the line (*d)->front->before=NULL; in remD()).
temp->after is not set to anything useful before you use it. So temp->after->before dereferences garbage.
Initialize *temp before you use it.
You expect temp->after to be not NULL, because the line after (the line valgrind complains about), you assign something to the ->front of it. Are you sure it will never be NULL, but always a valid value?
A question regarding the linked lists in C. Suppose, we have the following structures, that define the nodes in a linked list and a badly written free_list function, that (in my opinion) should cause an error:
typedef struct node *nodeT;
typedef struct node
{
int* elem;
nodeT next;
} *nodeT;
void free_list(nodeT list)
{
nodeT node;
for (node = list; node; node = node->next)
{
free(node->elem);
free(node);
}
}
As you see above, we have defined node as nodeT and a function to free the list free_list. For me, the obvious error is that inside free_list function inside for we do not have a temporary pointer to store the node value.
However, when I compile the code (on Linux), in which I create a linked list with few elements, the program doesn't crash, it seems that everything works fine.
My question is: Is there a simple way to prove that this function (free_list) is badly written? By simple I mean setting up some compiler flags (-Wall doesn't show any errors) or using such tools as Valgrind (used it with memcheck, that didn't help much)?
Update: Test case as requested:
int main()
{
nodeT myType;
nodeT tmpPtr;
myType = malloc(sizeof(nodeT));
myType->item = malloc(sizeof(int));
*(myType->item) = 0;
myType->next = malloc(sizeof(nodeT));
tmpPtr = myType->next;
tmpPtr->item = malloc(sizeof(int));
*(tmpPtr->item) = 1;
tmpPtr->next = malloc(sizeof(nodeT));
tmpPtr = tmpPtr->next;
tmpPtr->item = malloc(sizeof(int));
*(tmpPtr->item) = 2;
tmpPtr->next = malloc(sizeof(nodeT));
tmpPtr = tmpPtr->next;
tmpPtr->item = malloc(sizeof(int));
*(tmpPtr->item) = 3;
tmpPtr->next = NULL;
free_list(myType);
return 0;
}
and here is the Valgrind output:
valgrind --tool=memcheck ./a.out
...
==4318== Invalid read of size 8
==4318== at 0x400579: free_list (in /home/melon/a.out)
==4318== by 0x40069E: main (in /home/melon/a.out)
==4318== Address 0x51f1048 is 0 bytes after a block of size 8 free'd
==4318== at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4318== by 0x400574: free_list (in /home/melon/a.out)
==4318== by 0x40069E: main (in /home/melon/a.out)
...
I'm not sure how you did the test with valgrind, but with default parameters it detects this issue just fine:
==4464== Invalid read of size 8
==4464== at 0x400571: free_list (list.c:15)
==4464== by 0x4005DF: main (list.c:30)
==4464== Address 0x51e0048 is 8 bytes inside a block of size 16 free'd
==4464== at 0x4C2AD3C: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4464== by 0x40056C: free_list (list.c:18)
==4464== by 0x4005DF: main (list.c:30)
I just added this to the program to make it testable:
int main() {
nodeT head = malloc(sizeof(struct node));
nodeT node1 = malloc(sizeof(struct node));
head->next = node1;
head->elem = NULL;
node1->next = NULL;
node1->elem = NULL;
free_list(head);
return 0;
}
You can memset the node to zero before freeing the memory. Then it'll crash for sure.
You don't need any proof other than fact that the code dereferences a pointer to memory that was freed. That's undefined behavior. Invoking undefined behavior is bad.
So there's your proof.
I have a tree structure which I am adding a large amount of nodes too. The number of times this is done (tree cleaned between runs) and the number of nodes is given as a command line argument. For numbers of nodes roughly < 6000 and any number of runs the program performs as expected. However when the number of nodes exceeds this and the number of runs exceeds a low number around 50 the program causes a segmentation fault.
Program received signal SIGSEGV, Segmentation fault.
_int_malloc (av=0x7ffff7201740 <main_arena>, bytes=112) at malloc.c:3570
3570 malloc.c: No such file or directory.
Using backtrace this tracks too
#0 _int_malloc (av=0x7ffff7201740 <main_arena>, bytes=112) at malloc.c:3570
#1 0x00007ffff6ecbfb5 in __GI___libc_malloc (bytes=112) at malloc.c:2924
#2 0x0000000000401a99 in createTreeForQuad (quad=...) at cs257.c:217
#3 0x0000000000401b3a in addQuadsToTree (tree=tree#entry=0x2f965c8) at cs257.c:230
#4 0x0000000000401dec in addBody (tree=tree#entry=0x2f965c8, body=...) at cs257.c:292
#5 0x0000000000402146 in addBodyToCorrectQuad (body=..., tree=tree#entry=0x2f961c8) at cs257.c:245
#6 0x0000000000401eaf in addBody (tree=tree#entry=0x2f961c8, body=...) at cs257.c:296
#7 0x0000000000402146 in addBodyToCorrectQuad (body=..., tree=tree#entry=0x2f95dc8) at cs257.c:245
Note that the addBody -> addBodyToCorrectQuad -> addBody recursion happens a large number of times at high number of nodes. The code with the malloc which fails is below.
Tree *createTreeForQuad(Quad quad) {
Tree *tree;
tree = (Tree *)malloc(sizeof*tree);
if (tree != NULL){
tree->quad = quad;
tree->internal = 0;
tree->bodyEmpty = 1;
return tree;
}else{
printf("\n ------------------------------------ MALLOC FAILED----------------------------------------");
}
}
The code I use to free the tree is as follows, with it being called on the root node and the internal flag being set to 0 when the tree is a leaf.
void cleanTree(Tree **tree) {
if((*tree)->internal == 0) {
free(*tree);
}
else{
cleanTree(&((*tree)->NE));
cleanTree(&((*tree)->SE));
cleanTree(&((*tree)->SW));
cleanTree(&((*tree)->NW));
cleanTree(&((*tree)->NE1));
cleanTree(&((*tree)->NW1));
cleanTree(&((*tree)->SE1));
cleanTree(&((*tree)->SW1));
free(*tree);
}
}
The tree struct looks like this
typedef struct Tree Tree;
struct Tree {
Body body;
Quad quad;
Tree *NE;
Tree *NW;
Tree *SE;
Tree *SW;
Tree *NE1;
Tree *NW1;
Tree *SE1;
Tree *SW1;
int internal;
int bodyEmpty;
};
The code for adding Bodys to the tree is as follows with addBodyToCorrectQuad calling addBody on the quad that the body exists within.
void addBody(Tree **tree, Body body) {
if( (*tree)->bodyEmpty == 1) {
(*tree)->body = body;
(*tree)->bodyEmpty = 0;
}
else {
if((*tree)->internal) {
(*tree)->body = combineBody((*tree)->body, body);
addBodyToCorrectQuad(body, tree);
//printf("B\n");
}
else{
(*tree)->internal = 1; /
addQuadsToTree(tree);
//printf("%f",((*tree)->NW)->quad.x);
addBodyToCorrectQuad((*tree)->body, tree);
(*tree)->body = combineBody((*tree)->body, body);
addBodyToCorrectQuad(body, tree);
//printf("C\n");
}
}
}
You have heap corruption somewhere -- someone is running off the end of an array or dereferencing an invalid pointer or using some object after it has been freed.
Try using valgrind or some other memory debugging tool to narrow down where the problem is.