segmentation fault on calloc

L

laberth

I've got a segmentation fault on a calloc and I don'tunderstand why?
Here is what I use :

typedef struct noeud {
int val;
struct noeud *fgauche;
struct noeud *fdroit;
} *arbre; //for those who don't speak french arbre means tree.


An this is the fonction where I use the calloc :

arbre CreerNoeud(int valeur, arbre fg, arbre fd){
arbre A;
A=(arbre)calloc(1,sizeof(struct noeud)); //segmentation fault just
here.
A->val=valeur;
A->fgauche=fg;
A->fdroit=fd;
return A;
}

I also tried A=(arbre)calloc(1,sizeof(struct noeud));
and
A=(arbre*)calloc(1,sizeof(struct noeud));

but it doesn't work. Help me please !
 
H

Hallvard B Furuseth

laberth said:
I've got a segmentation fault on a calloc and I don'tunderstand why?

The simplest explanation I can think of is that you
may have forgotten '#include <stdlib.h>' which declares calloc().

Which reminds me:
A=(arbre)calloc(1,sizeof(struct noeud)); //segmentation fault just

In C programs, don't cast the result of malloc, calloc & co. It is not
necessary, and hides bugs like forgetting to declare calloc.


Anyway, if stdlib.h did not fix the problem, maybe the problem is
elsewhere - e.g., you modify some freed memory, which can corrupt
malloc's internal structures. If so, the following program should not
segfault, and you'll have to look for the problem elsewhere. A malloc
debugger like the commercial Purify or the free Elecetric Fence
(ftp://ftp.perens.com/pub/ElectricFence/) may detect the problem for
you.

#include <stdlib.h>

typedef struct noeud {
int val;
struct noeud *fgauche;
struct noeud *fdroit;
} *arbre;

arbre CreerNoeud(int valeur, arbre fg, arbre fd) {
arbre A;
A=calloc(1,sizeof(struct noeud));
A->val=valeur;
A->fgauche=fg;
A->fdroit=fd;
return A;
}

int main() {
(void) CreerNoeud(0, NULL, NULL);
return 0;
}
 
P

Peter Nilsson

I've got a segmentation fault on a calloc and I don'tunderstand why?
Here is what I use :

typedef struct noeud {
int val;
struct noeud *fgauche;
struct noeud *fdroit;
} *arbre; //for those who don't speak french arbre means tree.

It's generally not considered good form to typedef pointers this way. Just
typedef the struct, leave the pointer (*) for the readability in the
subsequent declarations of struct noeud objects.

I.E. prefer...

arbre *A;

....over...

arbre A;
An this is the fonction where I use the calloc :

arbre CreerNoeud(int valeur, arbre fg, arbre fd){
arbre A;
A=(arbre)calloc(1,sizeof(struct noeud)); //segmentation fault just
here.

A->val=valeur;
A->fgauche=fg;
A->fdroit=fd;

Not that calloc will properly initialise pointers to null anyway (at least
not portably), but since you clobber the zero-ed contents, why bother with
calloc? Why not just use...

A = malloc(sizeof *A);

If this fails to compile, then my guess was likely correct.
 
C

Christopher Benson-Manica

Peter Nilsson said:
Not that calloc will properly initialise pointers to null anyway (at least
^not

Just in case anyone was confused, although the rest of your sentence
indicates that you were not.
 
K

Kevin Goodsell

Christopher said:
^not

Just in case anyone was confused, although the rest of your sentence
indicates that you were not.

I think he had it right, but it's a little confusing to see that idiom
written rather than spoken. In conversational English, I might say
something like, "Not that it will work, but you could try..." implying
that it may not work.

-Kevin
 
C

Christopher Benson-Manica

Kevin Goodsell said:
I think he had it right, but it's a little confusing to see that idiom
written rather than spoken. In conversational English, I might say
something like, "Not that it will work, but you could try..." implying
that it may not work.

Curses, foil'd again ;( You're quite right, of course...
 
C

CBFalconer

I've got a segmentation fault on a calloc and I don'tunderstand why?
Here is what I use :

typedef struct noeud {
int val;
struct noeud *fgauche;
struct noeud *fdroit;
} *arbre; //for those who don't speak french arbre means tree.

An this is the fonction where I use the calloc :

arbre CreerNoeud(int valeur, arbre fg, arbre fd){
arbre A;
A=(arbre)calloc(1,sizeof(struct noeud)); //segmentation fault just

Don't use // comments in newsgroups, they don't wrap well!

Don't cast the result of malloc. It hides the error of failing to
#include <stdlib.h>

At any rate, by the time you get here there is no such thing as
"sizeof struct noeud". You never defined such. If you had used
the better and simpler form:

A = calloc(1, sizeof *A);

the problem would not arise.

WARNING: my guess is that you are using calloc to try to
initialize the gauche et droit pointers to NULL. This is NOT
valid. You should use explicit discrete initialization. You
should also test the allocation result. Thus the sequence would
become:

if (A = malloc(sizeof *A)) {
A->gauche = NULL; A->droit = NULL;
/* whatever */
}
else {
/* lack of memory action */
}
 
J

Jared Dykstra

Hallvard B Furuseth said:
The simplest explanation I can think of is that you
may have forgotten '#include <stdlib.h>' which declares calloc().


Failure to #include something is only going to confuse the compiler.
The linker doesn't care, and of course has no effect at runtime being
a preprocessor directive. A segmentation fault indicates a runtime
error.

Runtime errors are common on the C memory management API when the heap
was mismanaged in previous calls. free()ing a pointer twice is very
likely to cause a failure in the next malloc/calloc/realloc/etc call
because the call to free() is likely to (but may not) the heap in an
invalid state.

Many tools exist for debugging memory management. Start with Electric
Fence if you're still boggled by the failure. It will pinpoint the
location where the an over/underrun was made--before it segfaults
 
M

Martin Dickopp

Failure to #include something is only going to confuse the compiler.
The linker doesn't care, and of course has no effect at runtime being
a preprocessor directive. A segmentation fault indicates a runtime
error.

Failure to #include <stdlib.h> makes the compiler believe that `calloc'
returns `int', while in fact it returns `void *'. Normally the compiler
would emit a diagnostic when an `int' is assigned to a pointer, however
the OP prevented this by casting the return value of `calloc'. The result
is undefined behavior, which may well cause a runtime error.

Martin
 
J

Jared Dykstra

Martin Dickopp said:
Failure to #include <stdlib.h> makes the compiler believe that `calloc'
returns `int', while in fact it returns `void *'. Normally the compiler
would emit a diagnostic when an `int' is assigned to a pointer, however
the OP prevented this by casting the return value of `calloc'. The result
is undefined behavior, which may well cause a runtime error.

Martin

True, but only if sizeof(int) != sizeof(void *). This is, of course,
entirely possible.

Given that the original poster said:
"I also tried A=(arbre)calloc(1,sizeof(struct noeud));
and
A=(arbre*)calloc(1,sizeof(struct noeud));"

It is clear he is not too familiar with calloc() and/or dynamic memory
management.
 
M

Martin Dickopp

(e-mail address removed) (Jared Dykstra) writes:

R> Martin Dickopp said:
True, but only if sizeof(int) != sizeof(void *).

No, even if sizeof(int) == sizeof(void *), the behavior remains undefined.
For example, return values of type `int' might be returned in a different
register than return values of pointer type.

Martin
 
K

Kevin Goodsell

Jared said:
True, but only if sizeof(int) != sizeof(void *).

Chapter and Verse, please.
This is, of course,
entirely possible.

Indeed, but to the best of my knowledge this is not the only thing that
could cause a program containing the construct in question to fail - it
just happens to be the most likely thing.

-Kevin
 
K

Keith Thompson

I've got a segmentation fault on a calloc and I don'tunderstand why?
Here is what I use :

typedef struct noeud {
int val;
struct noeud *fgauche;
struct noeud *fdroit;
} *arbre; //for those who don't speak french arbre means tree.


An this is the fonction where I use the calloc :

arbre CreerNoeud(int valeur, arbre fg, arbre fd){
arbre A;
A=(arbre)calloc(1,sizeof(struct noeud)); //segmentation fault just
here.
A->val=valeur;
A->fgauche=fg;
A->fdroit=fd;
return A;
}

I also tried A=(arbre)calloc(1,sizeof(struct noeud));
and
A=(arbre*)calloc(1,sizeof(struct noeud));

but it doesn't work. Help me please !

Others have pointed out several errors (casting the result of
calloc(), possibly omitting "#include <stdlib.h>"), as well as some
style issues, but none of those is likely to cause a segmentation
fault on the calloc() call.

Failing to include <stdlib.h> will probably make the compiler assume
that calloc() returns an int rather than a void*; casting the result
to type arbre (a pointer to struct noeud) forces the phony int to be
converted to a pointer. This invokes undefined behavior, but the
effect is most likely to be one of two things. If an int and a struct
pointer happen to be the same size, and happen to be returned from
functions in the same way (this is fairly common), the call will
likely work as expected. If the types are of different sizes, or are
returned differently (in different registers, for example), you'll
probably assign a garbage value to A, but you're unlikely to get a
segmentation fault until you try to use the value.

Add "#include <stdlib.h>" to the top of your program if you haven't
already. Use malloc() rather than calloc() (since you assign values
to all the members of the struct, there's no need to zero it when you
allocate it). Check the value returned by malloc(); if you're running
out of memory, it will return a null pointer. Don't cast the value
returned by malloc().

Fix the problems that have been pointed out and try again. If you're
still having problems, post a small self-contained program that
exhibits the problem, and we'll take another look at it. Don't post a
program fragment; you're likely to delete the code that's actually
causing the problem. Cut-and-paste the exact code that you compiled;
if you try to re-type it into your news client, any typos could mask
the actual problem.

There's a good chance that going through this exercise will lead you
to fix the problem yourself. If not, we'll be glad to help.
 
T

The Real OS/2 Guy

True, but only if sizeof(int) != sizeof(void *). This is, of course,
entirely possible.

Hm, there is nothing that forbids a compiler to define a calling
interace such as:

return int type in R6
return floating point type in G0
return pointer type in RY

That defines 3 different memory locations. So when the compiler misses
the prototype of malloc/calloc.... it sees 'function returns result in
R6, so get content of R6, convert it to pointer and assign it to dest.

But R6 contains something bot not a valid pointer!
 
T

The Real OS/2 Guy

It's generally not considered good form to typedef pointers this way. Just
typedef the struct, leave the pointer (*) for the readability in the
subsequent declarations of struct noeud objects.

Yes, no. A more common practise is to write user defined types in
uppercase only to destinict them clearly from natural types.
I.E. prefer...

arbre *A;

...over...

arbre A;

ARBE a; /* a struct, type is only defined */
/* if there is a need to define */
/* a struct statically */
PARBRE pa; /* a pointer to a struct */
 
T

The Real OS/2 Guy

I've got a segmentation fault on a calloc and I don'tunderstand why?
Here is what I use :

typedef struct noeud {
int val;
struct noeud *fgauche;
struct noeud *fdroit;
} *arbre; //for those who don't speak french arbre means tree.


An this is the fonction where I use the calloc :

arbre CreerNoeud(int valeur, arbre fg, arbre fd){
arbre A;
A=(arbre)calloc(1,sizeof(struct noeud)); //segmentation fault just
here.

2 possible errors:

1. You've forgotten to #include <stdlib.h>. This causes undefined
behavior

2. some kind of UB before you enters the function that causes the
fault.
In special: somewhere in your program you've written into memory that
is owned by the malloc management itsef; You've destroyed the memory
allocation management data.


At least malloc(), calloc() can fail every time because it is unable
to return the required amount of memory. This is flagged as returnin a
NULL pointer. You're obligeted to test for this in any case.
A->val=valeur;
A->fgauche=fg;
A->fdroit=fd;
return A;
}

I also tried A=(arbre)calloc(1,sizeof(struct noeud));
and
A=(arbre*)calloc(1,sizeof(struct noeud));

but it doesn't work. Help me please !

All sayed above.
 
H

Hallvard B Furuseth

The said:
Yes, no. A more common practise is to write user defined types in
uppercase only to destinict them clearly from natural types.

That's another subject. It's one common practice, certainly.
Another is to give them an uppercase initial letter.

But - preferably as typedefs for a struct or something, not for a
pointer to a struct. Code which uses pointer typedefs is often harder
to read than other code. E.g. a function argument declaration will have
no '*', so one cannot see that the argument is a pointer argument and
thus a 'read/write' argument, it looks like a read-only argument.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,129
Messages
2,570,770
Members
47,329
Latest member
FidelRauch

Latest Threads

Top