Julien Lafaye wrote:
Hello,
i callocated a pointer to a user-defined struct. The value of the pointer is
something like 0x0000002aaaaa (can't remember actually, I don't have the
computer running the code with me). Then I perform some stuff on the
allocated structure which must be buggy since after its execution the value
of the pointer is something like 0xffffff2aaaaa, i.e. same lsb, different
msb. I don't know where to start to debug this. Obviously, when I run the
programm I get a SIGSEGV when deferencing the pointer and valgrind shows no
indication of invalid memory access. Do you have any clue on how to start
debugging this. Below is the template of my code.
Unfortunately, the key section of your code is missing, namely, what do
you do with the pointer between the time you allocate it and free it.
Your description of the behavior (above) suggests that you are doing
ill-advised assignments of a pointer to some integer type and suffering
from sign extension, then storing the sign-extended value back into the
pointer. But your code below cannot be doing that, because you are
_not_ using calloc to store a value in a pointer.
static int do_stuff()
{
obj_t res = *calloc((size_t)1, sizeof(obj_t));
The above points to one of the problems of typing from dim memories.
res is not a pointer to obj_t but an obj_t. It is hard to imagine
scenarios in which the above has any advantage over a simple.
obj_t res;
In fact, you lose the pointer value calloc returned creating a memory leak.
Further, the above does not check that calloc succeeded before
dereferencing a possibly null pointer.
It almost always is better to avoid typenames in allocations. It may
not appear so here, where the allocation is an initializer, but use of
malloc, calloc, and realloc is more often separated from declaration.
You will find that a form like
obj_t *res = calloc(1, sizeof *res);
will do quite as well. Note that in this line res is a pointer. You
still need to check that res is not null before dereferencing it.
Note also that the cast in "(size_t)1" is nothing more than typing
exercise. Whenever you use a cast, make sure it is needed. Unneeded
casts are often incorrect casts, and the occurance of casts, while
sometimes appropriate, are more often signs of poor design or inadequate
understanding.
// res is 0x000000..
^^^^^^^^
1) res almost certainly does not have any such value. res is a obj-t,
which you have told us is a struct.
2) Your comment suggests that res is all zeros. If res were a pointer,
that would be a null pointer which should not be dereferenced. Yes, I
understand that you didn't care to retype 0x0000002aaaaa from the text
above, but comments ought not be misleading.
obj_iterate(res);
// res is 0xffffff..
do_other_stuff(res->fied); <-- SIGSEGV
And the above hides any other errors, but one thing is clear if you
have correctly represented your code: res is not a pointer, so res->fied
is meaningless.
}
Julien
PS: my architecture is X86_64, Linux, gcc-4; code is compiled without
optimization, debugging symbols activated
That shouldn't matter, and if it did, your post would almost certainly
be off-topic here and belong in some newsgroup for Linux, gcc, or X86.