Type-casting problems

Discussion in 'C Programming' started by Ramon, Mar 20, 2008.

  1. Ramon

    Ramon Guest

    I have a pointer (result) of type void, which is passed (via parameter)
    to another function named preocessResult().

    At processResult() a pointer of type int (res) is malloced and data is
    stored in the allocated space. res is type-casted to void * and
    returned as result.


    Everything seems to be ok, but when I run valgrind it gives the
    following warnings:

    ==3186== Invalid read of size 1
    ==3186== at 0x401EB8C: memcpy (mc_replace_strmem.c:406)
    ==3186== by 0x804844A: foo (test.c:43)
    ==3186== by 0x8048462: main (test.c:54)
    ==3186== Address 0x416408B is not stack'd, malloc'd or (recently) free'd
    ==3186==
    ==3186== Invalid read of size 1
    ==3186== at 0x401EB91: memcpy (mc_replace_strmem.c:406)
    ==3186== by 0x804844A: foo (test.c:43)
    ==3186== by 0x8048462: main (test.c:54)
    ==3186== Address 0x416408A is not stack'd, malloc'd or (recently) free'd
    ==3186==
    ==3186== Invalid read of size 1
    ==3186== at 0x401EB98: memcpy (mc_replace_strmem.c:406)
    ==3186== by 0x804844A: foo (test.c:43)
    ==3186== by 0x8048462: main (test.c:54)
    ==3186== Address 0x4164089 is not stack'd, malloc'd or (recently) free'd
    ==3186==
    ==3186== Invalid read of size 1
    ==3186== at 0x401EB9F: memcpy (mc_replace_strmem.c:406)
    ==3186== by 0x804844A: foo (test.c:43)
    ==3186== by 0x8048462: main (test.c:54)
    ==3186== Address 0x4164088 is not stack'd, malloc'd or (recently) free'd


    Can any one figures out where is the mistake(s) please?
    Here is my code:



    void processResult(void **result)
    {
    int *res = (int *) malloc(sizeof(int));

    *res = 505;
    *result = res;
    }



    void foo()
    {
    void *result = NULL;
    struct mytask mtask;


    processResult(&result);

    if (result == NULL)
    bzero( &mtask, sizeof(struct mytask) );
    else
    mtask = *((struct mytask *) result);
    }
    Ramon, Mar 20, 2008
    #1
    1. Advertising

  2. Ramon

    santosh Guest

    Ramon wrote:

    > I have a pointer (result) of type void, which is passed (via
    > parameter) to another function named preocessResult().
    >
    > At processResult() a pointer of type int (res) is malloced and data is
    > stored in the allocated space. res is type-casted to void * and
    > returned as result.
    >
    >
    > Everything seems to be ok, but when I run valgrind it gives the
    > following warnings:
    >
    > ==3186== Invalid read of size 1
    > ==3186== at 0x401EB8C: memcpy (mc_replace_strmem.c:406)
    > ==3186== by 0x804844A: foo (test.c:43)
    > ==3186== by 0x8048462: main (test.c:54)
    > ==3186== Address 0x416408B is not stack'd, malloc'd or (recently)
    > free'd ==3186==
    > ==3186== Invalid read of size 1
    > ==3186== at 0x401EB91: memcpy (mc_replace_strmem.c:406)
    > ==3186== by 0x804844A: foo (test.c:43)
    > ==3186== by 0x8048462: main (test.c:54)
    > ==3186== Address 0x416408A is not stack'd, malloc'd or (recently)
    > free'd ==3186==
    > ==3186== Invalid read of size 1
    > ==3186== at 0x401EB98: memcpy (mc_replace_strmem.c:406)
    > ==3186== by 0x804844A: foo (test.c:43)
    > ==3186== by 0x8048462: main (test.c:54)
    > ==3186== Address 0x4164089 is not stack'd, malloc'd or (recently)
    > free'd ==3186==
    > ==3186== Invalid read of size 1
    > ==3186== at 0x401EB9F: memcpy (mc_replace_strmem.c:406)
    > ==3186== by 0x804844A: foo (test.c:43)
    > ==3186== by 0x8048462: main (test.c:54)
    > ==3186== Address 0x4164088 is not stack'd, malloc'd or (recently)
    > free'd
    >
    >
    > Can any one figures out where is the mistake(s) please?
    > Here is my code:
    >
    >
    >
    > void processResult(void **result)
    > {
    > int *res = (int *) malloc(sizeof(int));
    >
    > *res = 505;
    > *result = res;
    > }


    The problem is that void ** is not similar to void * in C. void * can
    point to any data type but void ** can only point to void *. This
    function is poorly designed. I suggest:

    int *processResult(void) {
    int *p = malloc(WHATEVER);
    return !p ? NULL : p;
    }

    or

    void processResult(int **p) {
    *p = malloc(WHATEVER);
    return;
    }

    > void foo()
    > {
    > void *result = NULL;
    > struct mytask mtask;
    >
    >
    > processResult(&result);


    Again void ** is not a generic pointer type like void * or char *.

    > if (result == NULL)
    > bzero( &mtask, sizeof(struct mytask) );
    > else
    > mtask = *((struct mytask *) result);
    > }
    santosh, Mar 20, 2008
    #2
    1. Advertising

  3. In article <frt70u$10g$>,
    Ramon <> wrote:

    >void processResult(void **result)
    >{
    > int *res = (int *) malloc(sizeof(int));
    >
    > *res = 505;
    > *result = res;
    >}
    >
    >
    >
    >void foo()
    >{
    > void *result = NULL;
    > struct mytask mtask;
    >
    >
    > processResult(&result);
    >
    > if (result == NULL)
    > bzero( &mtask, sizeof(struct mytask) );
    > else
    > mtask = *((struct mytask *) result);
    >}


    You haven't shown us the definition of struct mytask. But you are
    casting result, which is a pointer to space for a single int, to
    a pointer to struct mytask, and then dereferencing it. So if struct
    mytask is bigger than an int, you are accessing unallocated memory.

    It's also not allowed to modify memory through an int * pointer
    and then refer to it through some other type (except a character
    pointer), so if the struct doesn't start with an int you have
    another problem. (Can someone else confirm I have interpreted
    the aliasing rules correctly here?)

    -- Richard
    --
    :wq
    Richard Tobin, Mar 20, 2008
    #3
  4. Ramon <> writes:

    > santosh wrote:
    >> Ramon wrote:
    >>
    >>> I have a pointer (result) of type void, which is passed (via
    >>> parameter) to another function named preocessResult().
    >>>
    >>> At processResult() a pointer of type int (res) is malloced and data is
    >>> stored in the allocated space. res is type-casted to void * and
    >>> returned as result.
    >>>
    >>> Everything seems to be ok, but when I run valgrind it gives the
    >>> following warnings:
    >>>
    >>> ==3186== Invalid read of size 1
    >>> ==3186== at 0x401EB8C: memcpy (mc_replace_strmem.c:406)
    >>> ==3186== by 0x804844A: foo (test.c:43)
    >>> ==3186== by 0x8048462: main (test.c:54)
    >>> ==3186== Address 0x416408B is not stack'd, malloc'd or (recently)
    >>> free'd ==3186==

    <big snip>
    >>> Can any one figures out where is the mistake(s) please?


    Post, if you can, minimal code that exhibits the problem. I don't get
    any error from valgrind if I add the minimum required to make your
    code fragment work. The error (about memcpy) also suggests it relates
    some other part of the code that you did not post

    In addition, remove all but the required casts (two out of the three).
    A cast will indicate dangerous or possibly non-portable code so it is
    best not to have too many of them all over the place. Use them to
    alert the reader to problems.

    --
    Ben.
    Ben Bacarisse, Mar 20, 2008
    #4
  5. Ramon

    Ramon Guest

    Richard Tobin wrote:
    > In article <frt70u$10g$>,
    > Ramon <> wrote:
    >
    >> void processResult(void **result)
    >> {
    >> int *res = (int *) malloc(sizeof(int));
    >>
    >> *res = 505;
    >> *result = res;
    >> }
    >>
    >>
    >>
    >> void foo()
    >> {
    >> void *result = NULL;
    >> struct mytask mtask;
    >>
    >>
    >> processResult(&result);
    >>
    >> if (result == NULL)
    >> bzero( &mtask, sizeof(struct mytask) );
    >> else
    >> mtask = *((struct mytask *) result);
    >> }

    >
    > You haven't shown us the definition of struct mytask. But you are
    > casting result, which is a pointer to space for a single int, to
    > a pointer to struct mytask, and then dereferencing it. So if struct
    > mytask is bigger than an int, you are accessing unallocated memory.
    >
    > It's also not allowed to modify memory through an int * pointer
    > and then refer to it through some other type (except a character
    > pointer), so if the struct doesn't start with an int you have
    > another problem. (Can someone else confirm I have interpreted
    > the aliasing rules correctly here?)
    >
    > -- Richard



    Excuse me... I've forgot to show you the definition of struct mytask, so
    here it is:

    struct mytask {
    char info[100];
    };

    How can i solve this problem without changing the type of result -- i.e.
    leaving result as a pointer to void?

    Thanks
    Ramon, Mar 20, 2008
    #5
  6. In article <frtg1p$hdl$>,
    Ramon <> wrote:
    >>> int *res = (int *) malloc(sizeof(int));

    ....

    >Excuse me... I've forgot to show you the definition of struct mytask, so
    >here it is:
    >
    >struct mytask {
    > char info[100];
    >};
    >
    >How can i solve this problem without changing the type of result -- i.e.
    >leaving result as a pointer to void?


    What are you trying to achieve? Why do you think you can assign
    a block of sizeof(int) bytes to something which is supposed to point
    to 100 bytes?

    -- Richard
    --
    :wq
    Richard Tobin, Mar 20, 2008
    #6
  7. In article <>,
    Ben Bacarisse <> wrote:

    >Post, if you can, minimal code that exhibits the problem. I don't get
    >any error from valgrind if I add the minimum required to make your
    >code fragment work. The error (about memcpy) also suggests it relates
    >some other part of the code that you did not post


    The memcpy() is probably the structure assignment. And you probably
    didn't see an error because in your minimum program the assigned-to
    structure wasn't used, so the assignment was optimised away.

    The error is simple: he allocates space for an int, then copies it as
    a whole struct.

    -- Richard
    --
    :wq
    Richard Tobin, Mar 20, 2008
    #7
  8. Ramon

    Ramon Guest

    Richard Tobin wrote:
    > In article <frtg1p$hdl$>,
    > Ramon <> wrote:
    >>>> int *res = (int *) malloc(sizeof(int));

    > ...
    >
    >> Excuse me... I've forgot to show you the definition of struct mytask, so
    >> here it is:
    >>
    >> struct mytask {
    >> char info[100];
    >> };
    >>
    >> How can i solve this problem without changing the type of result -- i.e.
    >> leaving result as a pointer to void?

    >
    > What are you trying to achieve? Why do you think you can assign
    > a block of sizeof(int) bytes to something which is supposed to point
    > to 100 bytes?
    >
    > -- Richard


    As i've said before,
    The problem is that processResult() is designed to be a generic
    function; i.e. you don't know the type of result that it will process --
    for example, sometimes it may return an integer, while sometimes it
    may return a "string". It depends on the implementation of the user.

    In this case it was an int, but it may be any other data-structure
    (hopefully).
    Ramon, Mar 20, 2008
    #8
  9. In article <frtj7i$s9$>,
    Ramon <> wrote:

    >> What are you trying to achieve? Why do you think you can assign
    >> a block of sizeof(int) bytes to something which is supposed to point
    >> to 100 bytes?


    >As i've said before,
    >The problem is that processResult() is designed to be a generic
    >function; i.e. you don't know the type of result that it will process --
    > for example, sometimes it may return an integer, while sometimes it
    >may return a "string". It depends on the implementation of the user.
    >
    >In this case it was an int, but it may be any other data-structure
    >(hopefully).


    If it was an int, why did you assign it to a struct?

    -- Richard


    --
    :wq
    Richard Tobin, Mar 20, 2008
    #9
  10. Ramon

    Ramon Guest

    Richard Tobin wrote:
    > In article <frtj7i$s9$>,
    > Ramon <> wrote:
    >
    >>> What are you trying to achieve? Why do you think you can assign
    >>> a block of sizeof(int) bytes to something which is supposed to point
    >>> to 100 bytes?

    >
    >> As i've said before,
    >> The problem is that processResult() is designed to be a generic
    >> function; i.e. you don't know the type of result that it will process --
    >> for example, sometimes it may return an integer, while sometimes it
    >> may return a "string". It depends on the implementation of the user.
    >>
    >> In this case it was an int, but it may be any other data-structure
    >> (hopefully).

    >
    > If it was an int, why did you assign it to a struct?
    >
    > -- Richard
    >
    >



    Ok here is non-C stuff. As far as i know, POSIX message queues do not
    allows you to transmit pointers from one process to another (since each
    process has a protected address space). Hence one cannot assign an int
    to a void and post it to a message queue.

    To what type (except void) can i cast it (the int or something)?
    Ramon, Mar 20, 2008
    #10
  11. (Richard Tobin) writes:

    > In article <>,
    > Ben Bacarisse <> wrote:
    >
    >>Post, if you can, minimal code that exhibits the problem. I don't get
    >>any error from valgrind if I add the minimum required to make your
    >>code fragment work. The error (about memcpy) also suggests it relates
    >>some other part of the code that you did not post

    >
    > The memcpy() is probably the structure assignment. And you probably
    > didn't see an error because in your minimum program the assigned-to
    > structure wasn't used, so the assignment was optimised away.


    Kind of you to assume I'd be silly, but no. :)

    The memcpy is probably the assignment but the error relates to "some
    other part of the code that [the OP] did not post" in that you can't
    get the reported error (at least I can't) if the structure is
    "correct". Unless we see the struct, we can only guess at the error.

    > The error is simple: he allocates space for an int, then copies it as
    > a whole struct.


    No problem if the struct is the right size. I want to see the whole
    program before assuming even an "obvious" mistake. I think it helps
    more to say that what was posted was insufficient, but we all have our
    own ways of helping.

    --
    Ben.
    Ben Bacarisse, Mar 20, 2008
    #11
  12. Ramon <> writes:

    > Richard Tobin wrote:
    >> In article <frtj7i$s9$>,
    >> Ramon <> wrote:
    >>
    >>>> What are you trying to achieve? Why do you think you can assign
    >>>> a block of sizeof(int) bytes to something which is supposed to point
    >>>> to 100 bytes?

    >>
    >>> As i've said before,
    >>> The problem is that processResult() is designed to be a generic function; i.e. you don't know the type of result that it will process --
    >>> for example, sometimes it may return an integer, while sometimes
    >>> it may return a "string". It depends on the implementation of the
    >>> user.
    >>>
    >>> In this case it was an int, but it may be any other data-structure
    >>> (hopefully).

    >>
    >> If it was an int, why did you assign it to a struct?
    >>
    >> -- Richard


    Best to snip sig blocks (OK, just one line in this case, but it is
    still the preferred posting style to remove them).

    > Ok here is non-C stuff. As far as i know, POSIX message queues do not
    > allows you to transmit pointers from one process to another (since
    > each process has a protected address space). Hence one cannot assign
    > an int to a void and post it to a message queue.
    >
    > To what type (except void) can i cast it (the int or something)?


    You need to separate your different problems.

    (1) To solve the problem of passing an address between POSIX processes
    you need to post in comp.unix.programmer explaining what you are trying
    to do at the top level. The best solution may be very different to
    fixing the "how can I turn a pointer into something else" problem.

    (2) You specific problem here is that taking a pointer and treating as
    a pointer to something bigger will always be an error. Often, the
    solution is that generic data needs to be represented as a void * and
    an size_t to say how big the object is. You function might have to
    return a

    struct generic_data { void *ptr; size_t size; };

    However, your problem (1) may well be solved by some entirely
    different approach (i.e. shared memory or some RPC-like structure
    marshaling) so this problem could end up being secondary.

    --
    Ben.
    Ben Bacarisse, Mar 20, 2008
    #12
  13. "Ramon" <> wrote in message
    news:frtj7i$s9$...
    > Richard Tobin wrote:
    > > In article <frtg1p$hdl$>,
    > > Ramon <> wrote:
    > >> How can i solve this problem without changing the type of result --

    i.e.
    > >> leaving result as a pointer to void?

    > >
    > > What are you trying to achieve? Why do you think you can assign
    > > a block of sizeof(int) bytes to something which is supposed to point
    > > to 100 bytes?
    > >

    >
    > As i've said before,
    > The problem is that processResult() is designed to be a generic
    > function; i.e. you don't know the type of result that it will process --
    > for example, sometimes it may return an integer, while sometimes it
    > may return a "string". It depends on the implementation of the user.
    >
    > In this case it was an int, but it may be any other data-structure
    > (hopefully).


    Like the other responders, I think you're "barking up the wrong tree" for a
    couple of reasons. "Why, why, why?" It seems that there is a fundamental
    problem with the structure of your original program that would require you
    to need a function that can be "overloaded" with numerous types and allocate
    them too. Overloading is for C++, not C. C has a typesystem. Abusing C's
    typesystem when you don't know how to cast, when to cast, or how to
    determine if the cast is correct, is almost guaranteed to lead you into
    trouble since you'll be unable to locate and fix any errors with the casts.
    I.e., if you have to ask, you shouldn't be doing it. But, it seems you just
    want some code to solve your problem. So, here's some code. I don't know
    if it'll solve your problem. It has some limitations or restrictions: 1)
    sizeof() must return the size for the desired type, 2) must also have a
    pointer to the type, 3) type must be assignable (i.e., copies data when
    assigned to same type)... I've been up almost 19 hours so you'll have to
    locate any errors, illegal/undefined behavior, etc. You should pass it
    through Valgrind.

    #include <stdlib.h>

    struct mytask
    {
    char info[100];
    };

    void* processResult(size_t insize)
    {
    void *res;

    if(insize<(sizeof(int)))
    insize=sizeof(int);
    res=malloc(insize);
    *(int *)res=505;

    return(res);
    }

    void foo(void)
    {
    void *result=NULL;
    struct mytask mtask,*ptask;

    result=processResult(sizeof(struct mytask));

    ptask=((struct mytask *)result);
    mtask=*ptask;
    }

    int main(void)
    {
    foo();

    return(0);
    }


    Rod Pemberton
    Rod Pemberton, Mar 20, 2008
    #13
  14. Ramon

    CBFalconer Guest

    Ramon wrote:
    >

    .... snip ...
    >
    > Ok here is non-C stuff. As far as i know, POSIX message queues
    > do not allows you to transmit pointers from one process to another
    > (since each process has a protected address space). Hence one
    > cannot assign an int to a void and post it to a message queue.


    I have no idea what your real problem is, but consider that there
    is probably a very good reason for such a POSIX ban. Memory space
    in one process can be entirely different from memory space in
    another process. Thus the same 'pointer' value could point to
    entirely different entities.

    --
    [mail]: Chuck F (cbfalconer at maineline dot net)
    [page]: <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Mar 21, 2008
    #14
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. kevin
    Replies:
    11
    Views:
    5,803
    Andrew McDonagh
    Jan 8, 2005
  2. heyo
    Replies:
    3
    Views:
    905
    Dan Pop
    Apr 1, 2004
  3. pete
    Replies:
    4
    Views:
    795
    Dan Pop
    Apr 2, 2004
  4. Wally Barnes
    Replies:
    3
    Views:
    523
    Wally Barnes
    Nov 20, 2008
  5. Sosuke

    Up casting and down casting

    Sosuke, Dec 20, 2009, in forum: C++
    Replies:
    2
    Views:
    561
    James Kanze
    Dec 20, 2009
Loading...

Share This Page