Jump to content

Binary tree

- - - - -

  • Please log in to reply
6 replies to this topic

#1
tomy

tomy

    Newbie

  • Members
  • Pip
  • 5 posts
Hi guys! I a have a little problem and I don't know where is the mistake. At function preord() it says segmentation fault. Honestly, I don't know if the reading of my binary tree is good. Could someone help me please?
/*reading and printing a tree*/


#include <stdio.h>

#include <stdlib.h>

#include <assert.h>


struct arb{

	int key;

	struct arb *left;

	sttruct arb *right;

	sttruct arb *prev;

	};


typedef struct arb *Arb;


Arb ab_new(){ return NULL;}


int ab_empty(Arb a){ return a == NULL;}


void create(Arb a)

{

	int val;

	scanf("%d", &val);

	if (val)

	{

		a = (Arb) malloc(sizeof(struct arb));

		a->key = val;

		a->prev = a; // Is it correct? I want to keep the reference to father

		create(a->left);

		create(a->right);

	}

	else

		a = 0 ;

}


void preord(Arb a){

	printf("%d", a->key);

	if (a->left) return preord(a->left);

	if (a->right) return preord(a->right);

}


int main(){

	Arb a;


	create(a);


// here says seg fault

	preord(a);


	return 0;

}



#2
abzero

abzero

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 217 posts
Couple of comments, it's confusing to have Arb and struct arb mean different things. It would be better to either have Arb as a typename for the structure and have pArb as typename for the pointer (or lpArb for microsoftyness) or to ignore the pointer typedef altogether and using the specifiers in the functions (which is clearer.)

You main issue is probably that your not initalising the
Arb a;
variable. When your pass a to your function create your passing a pointer to that structure; this pointer is copied into that function. You then allocate memory for that structure and assign it to the copy of a when you return your original pointer is still pointing to garbage. Try passing a pointer to a pointer ( type ** v), or if your using C++ a reference to a pointer (type *& v)

#3
tomy

tomy

    Newbie

  • Members
  • Pip
  • 5 posts
I tried to make the changes you told me, but it didn't work or maybe I misunderstood what you said (the compiler says something about structures and incompatible pointer type * and **):

void create(Arb* a)

{

	int val;

	scanf("%d", &val);

	if (val)

	{

		*a = (Arb*) malloc(sizeof(struct Arb));

		(*a)->key = val;

		(*a)->prev = a; // Is it correct? I want to keep the reference to father

		create((*a)->left);

		create((*a)->right);

	}

	else

		*a = 0 ;

}


and in the main function:

int main(){

	Arb a = NULL;


	create(&a);


// here says seg fault

	preord(a);


	return 0;

}



#4
Groogy

Groogy

    Programmer

  • Members
  • PipPipPipPip
  • 183 posts
Haven't looked around in your code yet but I can simply state that SEGMENTATION FAULT is encountered whenever you try dereference invalid memory addresses like NULL. So I can give you the tip to add breakpoints whenever you are dereferencing a value that might be NULL and check if it is. You can also just do simple output(If the output is 0x0 or simply 0 then it's NULL).
My Code Blog - My Github - Ascension Project - Madness Script Project - Simple-Garbage-Collector Project
There is bound to be something useful somewhere.

#5
abzero

abzero

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 217 posts
For the pointer-to-pointer. Here's an example of how to allocate memory for a point in another function; you should be able to translate it into your code:

void init(char ** ptpData)
{
    *ptpData = (char *)malloc(sizeof(char)*10);
    fill(ptpData,10);
}

int main(int,char**)
{
    char * a_pointer;
 
    init(&a_pointer);

    printf("Data:%s\n", a_pointer);
    free(a_pointer);
}

Note how the malloc line works.

#6
tomy

tomy

    Newbie

  • Members
  • Pip
  • 5 posts

abzero said:

For the pointer-to-pointer. Here's an example of how to allocate memory for a point in another function; you should be able to translate it into your code:


void init(char ** ptpData)

{

    *ptpData = (char *)malloc(sizeof(char)*10);

    fill(ptpData,10);

}


int main(int,char**)

{

    char * a_pointer;

 

    init(&a_pointer);


    printf("Data:%s\n", a_pointer);

    free(a_pointer);

}


Note how the malloc line works.

If my a is already an address why should I use a pointer-to-pointer?
If I have the following data: 1, 2, 3, 4, 5, 6; could you explain me please how the function works? I don't think I've understood recursivity yet :(

#7
abzero

abzero

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 217 posts
Ok, it's a bit subtle.

Take this like:
int *p;

This states that the variable p (which is stored on the stack) is an address to an integer. Now when you pass this into a function:
...
func(p);
...

void func(int *p1)
{
}
The parameter p1 in func is a copy of that address. p1 is an interly different variable, which happens to point to the same data as p did in the previous function.

Now if you allocate memory and assign it to p1, p1 will point to a different block of memory; but p is still pointing to the same data as before. (Since p&p1 are seperate an assignment to the memory address it holds, will not affect the other.)

The pointer-to-pointer method solves this as what your passing in is an address of a location which holds an address to an int. When you allocate the memory you update at the location pointed to by p1, which is the base memory of p. When you return p now points to the new memory given in the alloc and not the old memory.

In this case, you could also return a pointer from the function, like:
    struct *p = createStructure();
....

struct * createStructure ( ) {
    struct *p = (struct *p)malloc(sizeof(struct p));
    ....

    return p;
}





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users