i make a function to print an BTree in level order none recursive way.
and i have a problem to find my mistake.. the following problem showing up.
Run-Time Check Failure #2 - Stack around the variable 'pq' was corrupted.
if some one can tell where is the problem is, or how i can find it by my self next time...?
i add the full project if is needed.
enter link description here
void PrintTreeLevelOrder(bstree tree){ //The problem some where here.....
queue *pq = (queue*)malloc(sizeof(queue)); // is struct of : *front, *rear
node *current;// is struct of : root
create_queue(&pq);//create queue- items_num = 0,front = NULL,rear = NULL
if (tree.root == NULL) {
printf("Your Tree Is Empty:\n");
return;
}
current = tree.root;
enqueue(current, &pq);
printf("Your Tree Displayed As Queue:\n");
while ((size_of_queue(&pq) )!=0) {
current = pq->front;
printf("%d ", current->data);
if (current->left != NULL)
enqueue(current->left, &pq);
if (current->right)
enqueue(current->right, &pq);
dequeue(&pq, ¤t);
}
}
First of all, I want to say that your algorithm is correct, please read the below.
Your code has multiple mistakes that should take care of
You used the pq functions in a wrong way, you passed a pointer to a pointer instead of the original pointer, so you overwrote the code
Create_queue should allocate unless you call it init but that's not the main issue
You should check if create_queue succeeded
You are saving addresses in the queue which are queue* as int which is wrong and not portable for an architecture different than 32bit
you are assigning current which is a node (node tree struct) a queue_element element pointer struct, which is also not correct because they are different types and architectures
Please work on these points, if you want more details please contact me
I would be happy to help
Related
I'm trying to implement my own version of malloc() function in c.
I decided to keep track of my allocated blocks using a linked list of meta-data objects that would store some information about the allocated chunk and and place it right before the chunk.
Now long story short while debugging I came across the fact that my linked list is behaving very strangely.
here's a piece of the code to help understanding the problem.
typedef struct meta_data
{
size_t size;
int free;
struct meta_data* next;
}meta_data;
meta_data* global_base;
void *mymalloc(size_t size)
{
if(size > 0)
{
meta_data block_meta;
void* pointer = sbrk(size + block_size);
block_meta.size = size;
block_meta.next = NULL;
block_meta.free = 0;
if(!global_base) //first allocation
{
global_base = &block_meta;
}
else
{
block_meta.next = global_base;
}
return pointer;
}
else
{
return NULL;
}
}
I wrote this code which I assume will append a new item to the tail of my global_base (linked list) every time I call mymalloc(<some_size>);
however when I tried to debug and make sure that my linked list is in order by calling mymalloc() couple of times and check is my linked list is being populated properly
void printList()
{
meta_data * node = global_base;
while (node->next != NULL)
{
printf("%zu", node->size);
printf(" -> ");
node = node->next;
}
printf(" \n ");
}
int main()
{
mymalloc(10);
mymalloc(8);
mymalloc(4);
printList();
return 0;
}
I expected my output to be
10 -> 8 -> 4 however it was 4 -> 4 -> 4 -> 4 -> 4 ..... and goes into an infinite loop
any idea where am I going wrong with this code.
I'm a little new to programming with C so my only guess is that I'm making use of reference & and pointer * improperly.
furthermore I have seen tones of code where the assignment of struct's attribute is happening with the use of -> but I could only use . to make it (could this be the problem anyhow)?
help is appreciated thanks guys
There are multiple problems with your approach:
the meta_data block_meta; is a local variable. You cannot use that to link the blocks. Local variables are reclaimed when the function exits. You should use global memory retrieved from the system with sbrk, pointed to by pointer.
the print loop is incorrect: you should write while (node != NULL) to print all blocks.
Your code has dozens of issues which I will address.
Now the problem with your code, in fact the biggest issue with it is that the myalloc function doesn't create a new block_meta node. It just declares a block_meta variable (which will end up on the stack and even worse is a recipe for disastrous bugs I believe the infinite loop is a result of this). You should you use the sbrk function to create a meta_data node before doing anything like so:
...
meta_data *block_meta = sbrk(sizeof(meta_data));
block_meta->size = size;
block_meta->next = NULL;
block_meta->free = 0;
if(!global_base)
{
global_base = block_meta;
}
The myalloc function checks to see if global_base has been assigned, that is if there is a root node in the linked list. If there is one it should simply tell the current variable to link itself to the global_base that is point it's next variable at global_base, this is a big error. Firstly, the global_base is the root node and it makes no sense to tell the current node to link itself to the root of the linked list, it's supposed to link itself to the next node not the root. Secondly, the reference to the previous node is lost which means it's not a linked list anymore. A proper solution would be saving the current node in a variable using a static variable which prevents it from getting lost when the myalloc function exits:
...
static meta_data *curr;
then right before returning the pointer to the newly allocated block you add this line to hold the node that had been newly created:
...
curr = block_meta;
return pointer;
now return to the erring else statement and change that to to ensure that the previous node points to the current node:
...
else
{
curr->next = block_meta;
}
I'm working on a program that checks whether or not a graph given from an input file has some specific criteria (e.g. it's connected etc).
Although yesterday I made it work, I'm trying to tweak it a bit so it runs faster, but that leads me to the well-known segmentation fault error.
What I'm findind really frustrating is that, after tried debugging of my own, I realised that I get the error after allocating the memory I need for the graph and only when the graph gets really big, for example over 500000 nodes and edges. (I'm using a linked list for the graph).
I've been writing in C for some years and I know (or at least I think I do) that "segmentation fault" pops up when the process tries to access memory that is not supposed to, but I can't understand why it's happening in that case.
GDB gave me the below info:
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554b28 in checkConnectivity (hd=<error reading variable: Cannot access memory at address 0x7fffff7feff8>, currentNode=<error reading variable: Cannot access memory at address 0x7fffff7feff0>, pointerToNode=<error reading variable: Cannot access memory at address 0x7fffff7fefe8>) at test.c:140
140 void checkConnectivity(node *hd, node *currentNode, node *pointerToNode[N])
checkConnectivity is a function that, using DFS, tries to check if the graph is connected or not. It has 3 arguments, hd the head pointer of my linked list, currentNode the node I am right now and pointerToNode, an array of pointers for getting to nodes faster (this is the tweak I wrote before about).
As you can tell hd and pointerToNode never change. I also call recursively the function after testing that I've not been yet to currentNode. So why i get this kind of error after calling it over again and again?
Any help/ideas would be much appreciated.
PS: I know that providing some code would be way more enlightening,
but my code is too long to include it in the question.
/edit/
void *safeMalloc(size_t size) {
void *p;
if((p = malloc(size)) == NULL) {
printf("Error 1 at safeMalloc.\nTerminating the program...\n");
exit(0);
}
return p;
}
typedef struct node {
long int id;
long int numOfNeighbors;
int visited;
struct neighbor *nextNeighbor;
struct node *nextNode;
} node;
typedef struct neighbor {
long int id;
struct neighbor *nextNeighbor;
} neighbor;
void checkConnectivity(node *hd, node *currentNode, node *pointerToNode[N]) {
//Mark our current node as visited.
currentNode->visited = 1;
//Find its first unvisited neighbor and call the function recursively.
if (currentNode->nextNeighbor == NULL) {
//No neighbors, return.
return;
} else {
neighbor *currentNeighbor = currentNode->nextNeighbor;
while (1) {
//If we haven't visited this neighbor yet...
if (pointerToNode[currentNeighbor->id - 1]->visited == 0) {
//Visit it.
checkConnectivity(hd, pointerToNode[currentNeighbor->id - 1], pointerToNode);
}
//Find the next neighbor of our node.
if (currentNeighbor->nextNeighbor != NULL) {
currentNeighbor = currentNeighbor->nextNeighbor;
} else {
return;
}
}
}
}
I think that the code above is enough to give you some idea of what I'm trying to do.
Node struct is for every node of my graph and every node points to every one of its neighbors (that's what neighbor struct is for), besides the next (numerically) node of the graph. Note that a link between two nodes struct doesn't mean an edge between them. This whole idea of representing a graph is taken from this article, but the code is mine.
Hope this helps! Thanks for your time.
Seemingly simple C code is seemingly not allowing me to remove the first element from a linked list. I can, however, successfully remove any other individual element and can successfully delete the whole linked list.
typedef struct list{
int data;
struct list * next;
} list;
void remove_element(list * node, unsigned int index){
if (node == NULL)
exit(-1);
list *currElem = node;
if (index == 0) {
node = node->next;
currElem->next = NULL;
free(currElem);
return;
}
Produces the follwing:
"free(): invalid pointer: 0xbfabb964"
I've followed the same format for all of my other manipulation functions with no issues. Similar threads on forums don't seem to be dealing with this particular problem.
You can read the explanation in this pdf on the Push function which explains it:
http://cslibrary.stanford.edu/103/
This is where c gets funky pschologically. You instinctively want to label a pointer as a pointer, which it is. But it is a pointer value, not a pointer reference. It's like the holy spirit of the C divinty. The triumvirate. C passed arguments to functions by value, not by address/reference. So, what do you do to pass a variable by reference? Remember, the solution is so obvious, it really didn't make sense to me for a week, I swear to god.
I declared a linked list implemented in C as follows:
struct node_List {
int i;
char * name;
struct node_List* next;
};
typedef struct node_List nodeList;
Then I declared the list head globally as:
nodeList list; // head of the list - does not contain relevant data
Finally, I have a function id(char * s) with a string s as th only argument.
nodeType id(char *s)
{
nodeType *p; // another List type
if ((p = malloc(sizeof(nodeType))) == NULL) {
// error: out of memory;
}
nodeList * node = &list;
// printf(" ");
while (node->next != NULL){
node = node->next;
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
}
// error: not found;
}
The problem is, when i run this program and call foo("somestring") the program executes the error: not found part and aborts execution, despite the string somestring being in the list.
I tried executing the very same program by inserting some printf() for debugging purposes, and it works perfectly, except it prints additional characters along with the output.
This happens each time I add some print lines, e.g. if I uncomment the two printf()s which I wrote in the example above (one of them or both, i get the same successful result). It doesn't work though if the printf is called with no arguments or with an empty string "".
I can't figure out what's happening, I double-checked the list creation and population functions and I am totally sure they work correctly. I tried changing the while break condition, but that didn't work, too. I have observed a similar behaviour on both Linux (with gcc) and Windows (using CodeBlocks editor's integrated compiler)
How could a printf directive affect a program so much?
EDIT: This code is part of a syntax analyzer written in Yacc. The whole code can be found below. It's a long read, and it is not completed, but the code above was tested and used to work as explained.
lexer: http://pastebin.com/1TEzzHie
parser: http://pastebin.com/vwCtMhX4
When looking in the provided source code, the algorithm to explore the linked list has two ways to miss node in the while-loop comparison.
Way 1 - starting only from the second node of the list.
Placing node = node->next; before the comparison will force the first comparison to be &(list)->next instead of &(list).
To start from the first node, simply place node = node->next; after
the comparison.
Way 2 - never ending to the last node of the list.
Using (node->next != NULL) in the while condition will force to exit from the loop before comparing the last node => node->next = NULL;.
To end by the last node, simply change the while condition to (node != NULL).
Solution:
while (node != NULL){ // end from the last node
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
node = node->next; // explore link after comparison
}
The actual error is a wrong type declaration of a variable returned by the function:
nodeType* createPoint(char* l){
nodeList* p;
if((p=malloc(sizeof(nodeList))) == NULL){
yyerror("out of memory");
} else {
// do stuff with p
}
return p;
}
The function return value was a nodeType* and p was instantiated as nodeList*.
The declaration of those two types was pretty simple, that's why the program could work.
the working code can be found here.
The strange behaviour with printf() was probably caused by the heap space needed for printf's arguments: since this function accepts an arbitrary number of parameters, it saves them in a list. This list is instantiated in the heap, there overwriting the old data left there from the wrong implementation of createPoint.
FINAL EDIT
My function that frees the memory works properly, and as milevyo has suggested, the problem lies in node creation, which I had fixed. I now have a separate problem where the program segfaults when run normally, but it cannot be reproduced in gdb or valgrind. However, that is a separate question altogether.
I have since found out that this segfault happened because I did not check for the EOF character properly. As per Cliff B's answer in this question, the check for EOF happens only after the last character in the file. As a result, in my function that loads the dictionary file, I had assigned the last character of the file to some i (which in this case was -1 according to a printf call), and tried to create and access a child node if index -1. This caused a segmentation fault, and also caused problems with my unload function, which would not unload the very last node I created.
As to why the segmentation fault does not appear when I run the program in gdb or valgrind, I have no idea.
EDIT 3
While stepping through my load function where the node creation happens, I notice an unexpected behaviour. I believe the problem lies somewhere in these lines of code, which are embedded within a for loop. The casting to (node*) is just to be safe, though it does not affect the running of the code to my knowledge.
// if node doesnt exist, calloc one, go to node
if (current_node->children[i] == NULL)
{
current_node->children[i] = (node*) calloc(1, sizeof(node));
nodes++;
}
current_node = current_node->children[i];
While stepping through the load function, I see that my current_node->children[i] seem to be calloc'ed properly (all children set to NULL), but the moment I step into current_node->children[i] and examine its children (see image below), I see that the addresses get screwed up. Specifically, the i'th child in the children node gets set to 0x0 for some reason. While 0x0 is supposed to be equal to NULL (correct me if I'm wrong), my free_all function seems to want to go into the 0x0 pointer, which of course results in a segfault. Can anyone shed light on how this might happen?
Values of children[i]
EDIT 2: I'm using calloc to create my nodes
root = calloc(1, sizeof(node));
For my child nodes, they are created within a for loop where I iterate over characters of the dictionary file I'm reading in.
if (current_node->children[i] == NULL)
{
current_node->children[i] = calloc(1, sizeof(node));
nodes++;
}
c in this case represents the character of the word being read in. I get i using the following:
if (c == '\'')
i = 26;
else if (isalpha(c))
i = c - 97;
EDIT: I'm thinking that something in my node creation is faulty, as milevyo suggested. This is because if I print out the addresses, it goes from 0x603250 to 0x603340 to 0x603430 to 0x603520, then finally to (nil), before it segfaults. I have verified that the root node gets passed in correctly by printing out its value in gdb. I'll try to figure it out.
ORIGINAL QUESTION
I'm running into a segfault when trying to free a recursive struct, but cannot figure out why, and would like some help.
My struct is defined as follows:
typedef struct node
{
bool is_word;
struct node* children[27];
}
node;
This is meant to implement a trie structure in which to load a dictionary into, for purposes of a spellcheck. After the spellcheck is done, I need to free the memory that I've allocated to the trie.
This is my current function which should free the trie when passed the root node, but it segfaults when doing so, though not immediately:
void free_all(node* curs)
{
int i;
// recursive case (go to end of trie)
for (i = 0; i < 27; i++)
{
if (curs->children[i] != NULL)
{
free_all(curs->children[i]);
}
}
// base case
free(curs);
}
Where could I have gone wrong? If more information is needed, please let me know.
i think, root node is faulty ( maybe it is null). if not, look elsewhere. in node creation for example.
void free_all(node* curs)
{
int i;
if(!curs) return; // safe guard including root node.
// recursive case (go to end of trie)
for (i = 0; i < 27; i++)
free_all(curs->children[i]);
// base case
free(curs);
}
The free_all function is ok. You have to check you set to NULL all children not allocated. This includes nodes that are not leaves, but don't have all the 27 children.
If that is ok, or fixing it doesn't fix the segfault, you have to debug.