Please help me spot the difference

A

Andreas Vinther

I have a small piece of code that compiles but does not perform like I
want it to.

This code works:
----------------

void *y0;
void *y1;
void *y2;
void *y3;
void *y4;

y0 = ssGetOutputPortSignal(S,0);
y1 = ssGetOutputPortSignal(S,1);
y2 = ssGetOutputPortSignal(S,2);
y3 = ssGetOutputPortSignal(S,3);
y4 = ssGetOutputPortSignal(S,4);


This code doesn't work:
-----------------------

void **y;
int i = 0;

*y = malloc(5 * sizeof(void*));

while (i < 5)
{
*(y+i) = ssGetOutputPortSignal(S,i);
i++;
}


I've also tried to use *y and *(y) instead of *(y+i). They all
compile, but does also violate my segments :]

Can anyone tell me why i get segmentation violation?
To me i seems like the code should perform somewhat similar, but I
regulary mess up when using pointers and pointers-to-pointers.

I know I have to use free(*y) later on. I also know that I ought to
check if malloc returns NULL. But neither seems to generate my problem.

I beg of all of you C gurus out there, please help poor little stupid
me. I know that some of you hardcore C guys probably lived inside a
computercabinet since birth and dream dreams in scrolling green symbols,
which sometimes fork()'s into severel parallel dream-threads.


Andreas
 
C

Christian MOENNE-LOCCOZ

and with y = malloc(5 * sizeof(void*)); ?
(instead of *y = )


Andreas Vinther a écrit :
 
I

Ico

Andreas Vinther said:
I have a small piece of code that compiles but does not perform like I
want it to.

This code doesn't work:
-----------------------

void **y;
int i = 0;

*y = malloc(5 * sizeof(void*));

Think about what you are doing with the result of malloc() here, where
does it get stored to ?
I beg of all of you C gurus out there, please help poor little stupid
me. I know that some of you hardcore C guys probably lived inside a
computercabinet since birth and dream dreams in scrolling green symbols,
which sometimes fork()'s into severel parallel dream-threads.

No, you won't find these people here; both fork() and threads are not
part of ansi C. Try again comp.os.unix.programmer.
 
P

Papastefanos Serafeim

Andreas Vinther said:
I have a small piece of code that compiles but does not perform like I want
it to.

This code works:
----------------

void *y0;
void *y1;
void *y2;
void *y3;
void *y4;

y0 = ssGetOutputPortSignal(S,0);
y1 = ssGetOutputPortSignal(S,1);
y2 = ssGetOutputPortSignal(S,2);
y3 = ssGetOutputPortSignal(S,3);
y4 = ssGetOutputPortSignal(S,4);


This code doesn't work:
-----------------------

void **y;
int i = 0;

*y = malloc(5 * sizeof(void*));

while (i < 5)
{
*(y+i) = ssGetOutputPortSignal(S,i);
i++;
}


I've also tried to use *y and *(y) instead of *(y+i). They all
compile, but does also violate my segments :]

Can anyone tell me why i get segmentation violation?
To me i seems like the code should perform somewhat similar, but I
regulary mess up when using pointers and pointers-to-pointers.

I know I have to use free(*y) later on. I also know that I ought to check
if malloc returns NULL. But neither seems to generate my problem.

I beg of all of you C gurus out there, please help poor little stupid me.
I know that some of you hardcore C guys probably lived inside a
computercabinet since birth and dream dreams in scrolling green symbols,
which sometimes fork()'s into severel parallel dream-threads.


Andreas


Instead of
*y = malloc(5 * sizeof(void*));
try this
y = (void **)malloc(5 * sizeof(void*));

I think that the typecast is not really needed in C
(but is needed in C++) so I've added it anyway.

Serafeim
 
J

Jens Thoms Toerring

Andreas Vinther said:
I have a small piece of code that compiles but does not perform like I
want it to.
void **y;
int i = 0;
*y = malloc(5 * sizeof(void*));

You assign to something 'y' is pointing to, but since 'y' isn't
initialized things go badly wrong. Moreover, you try to assign to
a void pointer something that points to a set of 5 void pointers -
that might give you a hint that something isn't correct here. Make
that

y = malloc(5 * sizeof(void*));

or, even better,

y = malloc(5 * sizeof *y);

to be not dependent on what type 'y' actually has.
while (i < 5)
{
*(y+i) = ssGetOutputPortSignal(S,i);

The "*(y+i)" bit can also be written as "y", both forms are
identical.
I've also tried to use *y and *(y) instead of *(y+i). They all
compile, but does also violate my segments :]


You probably will get some compiler warnings for these attempts if
you raise its warning level - if 'y' is a pointer-to-pointer to void,
then y is of type pointer to void, and thus assigning to *y or
*(y) (which is the same, the [] binds more tightly than the de-
reference operator *) would mean you try to assign a value to a void,
which of course isn't allowed.
Regards, Jens
 
R

Richard Bos

Instead of
*y = malloc(5 * sizeof(void*));
try this
y = (void **)malloc(5 * sizeof(void*));

I think that the typecast is not really needed in C

The cast is a Bad Thing in C, and shouldn't be there. For example, one
of the parts of the code Mr. Vinther did not show us is the bit where he
#includes his standard headers. If he forgot to #include <stdlib.h>,
that's a significant error which might have an impact on his problem,
and the compiler should warn him of this if its error level is set high
enough - but with your cast, it probably never will.

Richard
 
A

Andreas

Jens Thoms Toerring skrev:
You assign to something 'y' is pointing to, but since 'y' isn't
initialized things go badly wrong. Moreover, you try to assign to
a void pointer something that points to a set of 5 void pointers -

That is what I want it to do. I want a void pointer that points to 5
other void pointers.

Ofcourse...that's it.. Stupid me I haven't initialised it yet. So if I add:
void *x
y = &x;
to my original code it should work.

I'm not at my own computer right now, but I think that's it.
I't not beautifull but it I think it'll work.

I'll try I as soon as I get home... Thanks a lot y'all (especially you Jens)

----- snip ------
You probably will get some compiler warnings for these attempts if
you raise its warning level - if 'y' is a pointer-to-pointer to void,
then y is of type pointer to void, and thus assigning to *y or
*(y) (which is the same, the [] binds more tightly than the de-
reference operator *) would mean you try to assign a value to a void,
which of course isn't allowed.


I'm aware of that... but I intend to typecast my void pointers to other
pointers... But at this stage in the code I do not yet know what
datatype the pointer wil point to. An example could be:

*((double *)y) = double_value; //if it's of type double

I think that is a legal aproach

--- snip -----

I'll let you all know how it went when I get home.


Andreas Vinther
 
J

Jens Thoms Toerring

Andreas said:
Jens Thoms Toerring skrev:
That is what I want it to do. I want a void pointer that points to 5
other void pointers.

Mmmm, you might think so, but if you really think about it again you may
find that you don't want that. And you may be misled a bit by the malloc()
returning a void pointer and the automatic conversion from void pointers
to any other types of pointers. But you better think about the problem not
in terms of void pointers etc. but instead of some "real" data type. Let's
say you want an array of int pointers. Then you would have

int **x;
x = malloc(5 * sizeof *x); /* or x = malloc(5 * sizeof(int *)); */

and probably wouldn't come up with the idea that 'x' should be an int
pointer but that it must be a pointer-to-pointer to int. I.e. the thing
on the left hand side of the assignment must be a pointer to what you
want allocate memory for, so if you want to allocate memory for a set
of pointers to int you need a pointer-to-pointer to int. And in exactly
the same way you should go about dealing with void pointers and poin-
ters-to-pointers to void. While those may look indistinguishable at the
first glance they are of different type.
Ofcourse...that's it.. Stupid me I haven't initialised it yet. So if I add:
void *x
y = &x;
to my original code it should work.

It might work but all for the wrong reasons;-) If you need memory
for a set of values (I avoid the word 'array' here, since an array is
a bit more than just a collection of consecutive values in memory),
be ints, doubles or pointers, the type of a pointer to this "set" is
pointer to the type of the elements of this set. So if you want a set
of void pointers than a pointer to this (what you get from malloc())
must be of type pointer-to-pointer to void, not just void pointer. And
hat's why using

void **y;
y = malloc(5 * sizeof(void *)); /* or y = malloc(5 * sizeof *y); */

is the right way (even if it may be a bit hard to see when you insist
on thinking in terms of void pointers only and not also types).

Moreover, if you would use

void *x;
void **y = &x;
*y = malloc(5 * sizeof(void *));

then using 'y' later is going to be real tricky because 'y' won't be
a pointer-to-pointer to void (as you told in its definition) but a
pointer-to-pointer-to-pointer to void. If you lie to the compiler and
want to get away with it you must know very well what you're doing,
otherwise it will get its revenge;-)
You probably will get some compiler warnings for these attempts if
you raise its warning level - if 'y' is a pointer-to-pointer to void,
then y is of type pointer to void, and thus assigning to *y or
*(y) (which is the same, the [] binds more tightly than the de-
reference operator *) would mean you try to assign a value to a void,
which of course isn't allowed.

I'm aware of that... but I intend to typecast my void pointers to other
pointers... But at this stage in the code I do not yet know what
datatype the pointer wil point to. An example could be:
*((double *)y) = double_value; //if it's of type double

I think that is a legal aproach

While in principle it is (but only if 'y' is really a pointer-to-
pointer to void and not a "triple" pointer) this looks a bit like a
maintenance nightmare in the making. Why insist on using void pointers
etc. when you already know the type of what you're going to store?
Except in special cases I found it to be better for my mental sanity
(as far as any is left;-) to use the correct types wherever possible
and not to obfuscate what's happening by the use of "generic" pointers
and casts. As a rule I try to avoid situations where casts are needed -
often they just show that one hasn't really understood what's going on
and instead of thinking clearly is groping in the dark for some
"solution" that might seems to work (but, alas, often not really does).

Regards, Jens
 
A

Andrew Poelstra

Instead of
*y = malloc(5 * sizeof(void*));
try this
y = (void **)malloc(5 * sizeof(void*));

I think that the typecast is not really needed in C
(but is needed in C++) so I've added it anyway.

Absolutely not. This disguises the fact that you may not have #include'd
<stdlib.h>. (Which, somewhat ironically, may have been the OP's
problem.)
 
A

Andreas Vinther

--- snip ----
I'm aware of that... but I intend to typecast my void pointers to other
pointers... But at this stage in the code I do not yet know what
datatype the pointer wil point to. An example could be:
*((double *)y) = double_value; //if it's of type double

I think that is a legal aproach

While in principle it is (but only if 'y' is really a pointer-to-
pointer to void and not a "triple" pointer) this looks a bit like a
maintenance nightmare in the making. Why insist on using void pointers
etc. when you already know the type of what you're going to store?
Except in special cases I found it to be better for my mental sanity
(as far as any is left;-) to use the correct types wherever possible
and not to obfuscate what's happening by the use of "generic" pointers
and casts. As a rule I try to avoid situations where casts are needed -
often they just show that one hasn't really understood what's going on
and instead of thinking clearly is groping in the dark for some
"solution" that might seems to work (but, alas, often not really does).


I see what you mean and I apreciate your help. Like you, I think it's
always best to use datatype specific pointers. But you wrote that I
insist on using void pointers when I already know the datatype I'm going
to point to. That is just it. I do NOT yet know the datatype, as I've
written almost at the top of the text i left in this post. That's why
I'm forced to use void pointers or make similar code sections for every
possible datatype.

The code snip is from a data-logger. The number of variables and their
datatype is set in runtime and not yet know when the program is
compiled. That's why I allocate memory dynamically and use void
pointers. I need to print the values in real-time, and therefore I can't
just log a big hunk of raw data without knowing the individual values
and their sizes in memory.
In hinesight I should have mentioned this ealier or at least been more
specific.

BTW, the code works great now and I thank you all for your help.


PS: I'm sorry for the late reply, but I've just been 10 days to London
and the hotel we stayed in, only allowed people to use the internet on
the hotels computers. The computers were "locked" to a few select tasks
and were 6£/h. Since I'm still a student on a budget, I found the price
ridiculous, and didn't want to fumble around the internet looking for a
www-interface for usenet.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top