It give me core dump error after I have create a child in my binary tree, the if condition work perfectly, but when I try to pass the sx child as parameter it give error and I don't know how to fix it.
#include <stdio.h>
#include <stdlib.h>
typedef struct nodes *node;
struct nodes{
int dato;
node sx;
node dx;
};
node build(node n){
printf("Insert the value: ");
scanf("%d",&n->dato );
char s[5];
printf("build a child? ");
scanf("\n%s",s);
if(s[0]=='l')
build(n->sx);
return n;
}
int main(int argc, char const *argv[]) {
system("clear");
node root=(node)malloc(sizeof(node));
root=build(root);
printf("\n\nvalue: %d\n", root->dato);
return 0;
}
Firstly, the problem is in the memory allocation.
node root=(node)malloc(sizeof(node));
which represents
struct nodes * node = (struct nodes *) malloc(sizeof(struct nodes *));
while, it should have been
struct nodes * node = malloc(sizeof(struct nodes));
So, essentially, you're allocating way less memory (just for a pointer) than the expected (a whole variable).
Then, once fixed, at a later point, build(n->sx); will also invoke undefined behavior, as you're trying to pass an unitialized pointer to function, and dereferencing it.
That said, please see this discussion on why not to cast the return value of malloc() and family in C..
Related
Hi guys I'm learning C programming. I wanted to write some codes for learning linked list topic but there is a problem. This code about creating linked list with 5 nodes, writing something into 3rd node, printing them to console.
Here is all of my codes:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
struct node{
char *data;
struct node *next;
};
typedef struct node node;
node *root;
void nodeAdd(node *n, int x)
{
node *iter;
iter=root;
for(int i=0;i<x;i++)
{
iter->next = (node*)malloc(sizeof(node));
iter->next->data="0";
iter->next->next=NULL;
iter=iter->next;
printf("Node created.\n");
}
}
void nodeWrite(node *n,char *string,int x)
{
node *temp;
temp=root;
for(int k=0;k<x;k++)
{
temp=temp->next;
}
strcpy(temp->data,string); //HERE IS ERROR
printf("\n");
printf("%s \n",temp->data);
printf("Node writed.");
}
void nodePrint(node *n)
{
while(root->next!=NULL)
printf("%s\n",root->data);
root=root->next;
}
int main(int argc, const char * argv[])
{
root = (node*)malloc(sizeof(node));
nodeAdd(root,5);
nodeWrite(root,"WTF", 3);
nodePrint(root);
return 0;
}
data is an unintialized pointer variable. Initialize with the address of a valid memory that you allocate. That will solve the problem. Now you have udnefined behavior.
What you can possibly do is
Use char array instead of using pointer.
Allocate dynamically the memory.
In case of 1.
struct node{
char data[MAXSTRINGLEN];
struct node *next;
};
In case of 2:
Initially make the pointers point to NULL. So now you can allocate to it like this
temp->data = malloc(sizeof *temp->data*MAXSTRINGLEN);
if( temp->data == NULL)
{
fprintf(stderr,"Error in malloc");
exit(1);
}
Just one point, free the allocated memory when you are done working with it.
Use of the global variable here is not really required here. You can always pass return pointers from memory and assign it to the struct node*. Or yes you can use double pointers. Use of global variable is not needed here.
Clean up code, that are redundant and not required. That makes things readable and less confusing.
The program initially is designed incorrectly and has undefined behavior..
For example the data member data of the node root was not initialized. So its output in the function nodePrint results in undefined behavior. Moreover the function itself is incorrect.
Neither function uses its parameter node *n.
In this statement
strcpy(temp->data,string);
there is an attempt to change the string literal pointed to by the data member temp->data provided that the data member was initialized (as it was pointed above the data member is not initialized for the node root). You may not change a string literal. Any attempt to modify a string literal leads to undefined behavior.
There is no need to declare the node root as a global variable.
Parameters of the function main are not used in the program. So the function should be declared like
int main( void )
I was writing a program to implement BST and I declareed two structures for that.
struct node
{
int data;
struct node *link[2];
};
struct tree
{
struct node *root;
};
typedef struct node node;
typedef struct tree tree;
And then i wrote a function to insert the elements in it.
void insert_iter(tree *tree, int data);
But in my main() function, I got confused that what thing shoud I initialise as NULL. So, I did this in my main() function.
tree *tree=NULL;
And it gave an error of segmentation fault.
But then I realised that the first condition in my insert_iter() function calls for tree->root, so this error was bound to happen.
But then I am confused about how to initialize this. How to go on for this?
EDIT: I have updated with the required code!!
this is the main() function
int main()
{
tree *tree=NULL; // all the confusion is regarding this
printf("hello"); // for debugging
//*tree->root=NULL; // tried this one but it was wrong
int value,choice;
while(1)
{
printf("enter the element : ");
scanf("%d",&value);
insert_iter(tree,value);
printf("do you want to enter more : 0 or 1 : ");
scanf("%d",&choice);
if(choice==0)
break;
}
return 0;
}
and this is the function that i used to insert the elements
void insert_iter(tree *tree, int data)
{
if(tree->root==NULL)
tree->root=newNode(data); // function to make a new node
else{
node *it=tree->root;
int dir;
while(1)
{
dir=data>it->data;
if(it->link[dir]!=NULL)
it=it->link[dir];
else
{
it->link[dir]=newNode(data);
break;
}
}}}
tree *tree=NULL; // all the confusion is regarding this
// the above is setting a pointer to NULL, which is ok
*tree->root=NULL; // tried this one but it was wrong
// the above is setting a
// (not initialized to point to any specific memory)
// offset in the tree struct variable
// (that offset is not pointing any specific memory)
// to set the first 4 bytes of that memory to NULL
// which should/will cause a seg fault event due to undefined behaviour
// a workable solution might be:
tree *pTree = malloc( sizeof(tree) );
// and then this would work:
tree->root = NULL; // notice no '*' dereference needed
//I would also strongly suggest that the variable names be different
//than the struct names, and not just in the capitalization of the name.
//The use of different names will greatly enhance
//the readability and understandability and clarity of the code
//(and will avoid any misunderstandings by the compiler and future maintainer)
Trying to implement below code for some assignment but getting an error for malloc array generation "[Error] conflicting types for 'stack'" Any Help ??
Thanks in Advance.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
// Trying to create array here
stack=(NODEPTR*)malloc(sizeof(NODEPTR)*20);
int main()
{
printf("YO\n");
return 0;
}
EDIT :
I can't move it to main , as i have to access the stack globally in different functions.
because Stack array gets destroyed when it go to another function.
check here http://ideone.com/5wpZsp ,
When i give static declaration globally it works smoothly, here : http://ideone.com/3vx9fz
You can not call assignment operations at global scope. Try malloc operation in main() instead.
And the type of stack is not a pointer but pointer to pointer. Are you sure about it's declaration ?
Move your initialization of stack to inside of the main method.
EDIT An example showing how the malloc data can persist to other function calls even though malloc is called inside of main.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
void test_stack()
{
printf("%p\n", stack);
printf("%d\n", stack[19]->flag);
}
int main()
{
// Trying to create array here
stack=(NODEPTR*)malloc(sizeof(NODEPTR)*20);
stack[19] = (NODEPTR*)malloc(sizeof(struct treenode));
stack[19]->flag = 42;
test_stack();
return 0;
}
Step 1: Move the declaration of stack inside main. There's no reason it should be declared globally:
int main( void )
{
NODEPTR *stack;
...
Step 2: Move the malloc call inside main (you cannot perform an assignment or a function call outside of a function).
Step 3: Drop the cast; it's unnecessary1 and just adds visual clutter.
Step 4: Use sizeof *stack as opposed to sizeof (NODEPTR) in the argument to malloc:
stack = malloc( sizeof *stack * 20 );
The result is the same, but this is easier to read, and avoids maintenance headaches if you ever change the type of stack.
Step 5: free your stack when you're done. Yeah, for this program it doesn't matter, but it's a good habit to get into.
So after all this, your code should read:
int main( void )
{
NODEPTR *stack;
stack = malloc( sizeof *stack * 20 );
...
free( stack );
return 0;
}
Stylistic nit: Hiding pointer types behind typedefs is bad juju IME. Pointer semantics are important, and if the programmer is ever expected to dereference an object of type NODEPTR (either explicitly, as (*node).info, or implicitly, as node->info), then it's usually best to declare that object using pointer declaration syntax, something like
typedef struct treenode Node;
Node *node;
Node **stack;
...
stack[i]->next = node->next;
etc. so the person using your types knows exactly how many levels of indirection are involved and can write their code accordingly (multiple indirection is not hard). If the type is meant to be truly opaque and never directly dereferenced, but just passed around to an API that handles all that, then hiding the pointerness of that type is okay. Otherwise, leave it exposed.
I tend not to typedef struct types for a similar reason, but I suspect I'm an outlier in that regard.
Ahd who broke the code formatter?!
1 - In C, that is; in C++, the cast is required, but if you're writing C++, you should be using new instead of malloc anyway.
#include<stdio.h>
#include<stdlib.h>
struct treenode
{
char info;
struct treenode *firstchild;
struct treenode *next;
int flag;
};
typedef struct treenode *NODEPTR;
NODEPTR *stack;
int main()
{
stack=malloc(sizeof(NODEPTR)*20);
printf("YO\n");
return 0;
}
This will work.
allocate memory inside(malloc) your main.
There is no need to typecast out put of malloc. for further info see this post
EDIT :
In your comment you mentioned that memory will be destroyed when you move other function.
This is not true. Once you allocate memory using malloc it will not be destroyed until you call free().
So if you want to access the malloc'ed variable in other function pass the variable as argument to other function.
See this example program below
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
char *str;
void passMalloc(char **str);
int main()
{
str = malloc(100 * sizeof(char));
strcpy(str, "GoodMorning");
printf("\nMain before pass : %s\n", str);
passMalloc(&str);
printf("Main after pass : %s\n\n", str);
free(str);
return 0;
}
void passMalloc(char **str)
{
strcpy(*str, "GoodEvening");
printf("Function Def : %s\n", *str);
}
I have a interface documented like this:
typedef struct Tree {
int a;
void* (*Something)(struct Tree* pTree, int size);
};
Then as I understand I need to create instance of it, and use Something method to put the value for 'size'.
So I do
struct Tree *iTree = malloc(sizeof(struct Tree));
iTree->Something(iTree, 128);
But it keeps failing to initialize. Am I doing this right?
Howcome the first member of the Something method is pointer to the very same struct?
Can anyone explain please?
Thanks
You have to set Something to something since it is only a function pointer and not a function. The struct you created with malloc just contains garbage and struct fields need to be set before it is useful.
struct Tree *iTree = malloc(sizeof(struct Tree));
iTree->a = 10; //<-- Not necessary to work but you should set the values.
iTree->Something = SomeFunctionMatchingSomethingSignature;
iTree->Something(iTree, 128);
Update
#include <stdlib.h>
#include <stdio.h>
struct Tree {
int a;
//This is a function pointer
void* (*Something)(struct Tree* pTree, int size);
};
//This is a function that matches Something signature
void * doSomething(struct Tree *pTree, int size)
{
printf("Doing Something: %d\n", size);
return NULL;
}
void someMethod()
{
//Code to create a Tree
struct Tree *iTree = malloc(sizeof(struct Tree));
iTree->Something = doSomething;
iTree->Something(iTree, 128);
free(iTree);
}
This is a poor man's virtual function. The initial parameter is roughly equivalent to C++'s this pointer in a member function. And you must manually set the function pointers before calling them, whereas C++ virtual functions are set up by the compiler.
The member Tree::Something is never initialized. You allocate space for a Tree, but allocation is different from initialization, and your allocated Tree contains only unmeaningful bits.
I wrote a quick generic linked list, simple stuff. But I have a bug and I cannot spot what it is complaining about. Pertinent code:
typedef struct _node {
void *data;
struct _node *next;
} node;
typedef struct _queue {
node *root;
node *last;
unsigned int length;
} queue;
node * find_node(void *data, int size, queue *q)
{
node *n;
for(n=q->root;n;n=n->next)
if(memcmp(data, n->data, size)==0)
return (n);
return (NULL);
}
Testing it:
queue q = {NULL, NULL, 0};
node *n;
int data[QUEUEMAX];
int i;
/* insert bunch of ints into queue */
for(i=0;i<QUEUEMAX;i++) {
data[i] = give_me_a_number();
n = alloc_node();
n->data = data[i];
insert_into(n, &q);
}
printf("list size = %d.\n", q.length);
/* print out, make sure they're there */
for(n=q.root;n;n=n->next)
printf("data = %d\n", (int)n->data); //*(int *)n->data didn't work, segfault?
/* find a specific node */
node *nd = find_node(&data[10], sizeof(int), &q);
/* remove it */
rm_node(nd, &q);
Running it:
$ ./test
list size = 256.
data = 10
data = 11
data = 12
data = 13
data = 14
data = 15
data = 16
... blah blah (256 lines)
Segmentation Fault
gdb says the problem is the memcmp() in find_node(). I think gcc is whining about the n->data being passed to memcmp(). Any ideas? Also, I was getting a segfault trying to do int x = *(int *)n->data but this seems valid to me, non?
In this code:
n->data = data[i];
You are currently setting the void* data pointer to be data[i] but you really want to set it to the address of data[i] so you need to do:
n->data = &data[i];
That is also why you got a segfault on your cast.
Segmentation Fault happens when you try to dereference NULL pointer. If you know the line where it happens verify that there no NULL there, example int x = *(int *)n->data will generate SEGFAULT if n is NULL or n->data is NULL
Assuming that your memory allocation functions are working, most likely n->data is NULL, and therefore you can't access it. Also, why are you passing the data array as &data[10]? Why not just use data since the identifier of an array is a pointer to its first location?
It looks like you are being inconsistent in whether your data is a pointer or if its a pointer thats being casted to an int. You are passing a int (since the pointer is basically a int cause of the cast).
memcpy naturally wants a void *, not an int.
So the solution really is to pass a pointer to your int in data and make everything else work with that.
Also, the memcmp call in find_node will sometimes compare too much data. You're using memcmp with the size of the data you're searching for. If the data in the current node is shorter than that, memcmp will go beyond it, into forbidden territory. (The test code you posted won't usually trip this bug, because most of the data fields have the same length.) You need to add a length field to each node, and use the minimum of both lengths in memcmp.
You're assigning an int variable
n->data = data[i];
To what it is supposed to be a pointer
typedef struct _node {
void *data;
struct _node *next;
} node;