LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-07-2009, 02:25 PM   #1
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 366
Blog Entries: 1

Rep: Reputation: 44
C: Casting a pointer to (void **)


I am trying to understand the following line of C code:

pool->free_list = (GC_MS_PObj_Wrapper*)(*(void **)ptr);

in the following context (irrelevant bits snipped out):

Code:
typedef struct pobj_t {
    unsigned long flags;
} PObj;

typedef struct GC_MS_PObj_Wrapper {
    size_t flags;
    struct GC_MS_PObj_Wrapper * next_ptr;
} GC_MS_PObj_Wrapper;

typedef struct Fixed_Size_Pool {
    ...

    GC_MS_PObj_Wrapper * free_list;
}

static void * gc_ims_get_free_object(Fixed_Size_Pool *pool)
{
    PObj *ptr; 

    ...

    ptr             = (PObj *)pool->free_list;
    pool->free_list = (GC_MS_PObj_Wrapper*)(*(void **)ptr);

    ...

    return (void *)ptr;
}
Why not just cast ptr to GC_MS_PObj_Wrapper ** and dereference it? Why cast it to void ** first?

Also, I don't understand how they are casting between the two different structs that are a different size. Does casting a PObj * to a GC_MS_PObj_Wrapper * act as some type of "overlay" that keeps the flags field from the PObj intact, and adds on the next_ptr field?

Thanks,
Jesse Taylor
 
Old 09-07-2009, 05:18 PM   #2
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
I suggest you update your code the last reference I can easliy find to that code is two years ago and there are mentions of bugs which stamp over memory and lose data. The latest supported release is 1.4 in which the code is quite different.
Code:
static void *
gc_ms_get_free_object(PARROT_INTERP, ARGMOD(Small_Object_Pool *pool))
{
    ASSERT_ARGS(gc_ms_get_free_object)
    PObj *ptr;
    PObj *free_list = (PObj *)pool->free_list;

    /* if we don't have any objects */
    if (!free_list) {
        (*pool->more_objects)(interp, pool);
        free_list = (PObj *)pool->free_list;
    }

    ptr             = free_list;
    pool->free_list = ((GC_MS_PObj_Wrapper*)ptr)->next_ptr;

    PObj_flags_SETTO(ptr, 0);

    --pool->num_free_objects;

    return ptr;
}
As for why the code was as you posted I can not see from here, yet I suspect there is more to this than what you have posted. Normally when something like this is done you are looking to put the address in a integer. You could ask the developers or just get the latest from the site or svn.

Quote:
Also, I don't understand how they are casting between the two different structs that are a different size.
Hehe welcome to the wonderful world of C where it is quite common. You can see it is done in the above code also but after a quick look I would really question why they are doing this as well it does not seem to gain anything here.

Last edited by dmail; 09-07-2009 at 05:19 PM.
 
Old 09-07-2009, 05:35 PM   #3
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 366

Original Poster
Blog Entries: 1

Rep: Reputation: 44
Quote:
Originally Posted by dmail View Post
I suggest you update your code the last reference I can easliy find to that code is two years ago and there are mentions of bugs which stamp over memory and lose data. The latest supported release is 1.4 in which the code is quite different.
I'm using the latest SVN sources.

Quote:
As for why the code was as you posted I can not see from here, yet I suspect there is more to this than what you have posted.
I'm pretty sure this should be all that is necessary to answer my questions regarding it.

Quote:
Normally when something like this is done you are looking to put the address in a integer.
What?

Quote:
You could ask the developers
They are very busy, and this is a basic programming question, better suited to a forum for basic programming questions.

Quote:
Hehe welcome to the wonderful world of C where it is quite common. You can see it is done in the above code also but after a quick look I would really question why they are doing this as well it does not seem to gain anything here.
I'm sure it might be "quite common", but I was asking about what the purpose is.


So again, my two questions were:

Why not just cast ptr to GC_MS_PObj_Wrapper ** and dereference it? Why cast it to void ** first?

Also, I don't understand how they are casting between the two different structs that are a different size. Does casting a PObj * to a GC_MS_PObj_Wrapper * act as some type of "overlay" that keeps the flags field from the PObj intact, and adds on the next_ptr field?

Thanks,
Jesse Taylor
 
Old 09-07-2009, 05:45 PM   #4
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 366

Original Poster
Blog Entries: 1

Rep: Reputation: 44
Quote:
Originally Posted by dmail View Post
Code:
static void *
gc_ms_get_free_object(PARROT_INTERP, ARGMOD(Small_Object_Pool *pool))
{
    ASSERT_ARGS(gc_ms_get_free_object)
    PObj *ptr;
    PObj *free_list = (PObj *)pool->free_list;

    /* if we don't have any objects */
    if (!free_list) {
        (*pool->more_objects)(interp, pool);
        free_list = (PObj *)pool->free_list;
    }

    ptr             = free_list;
    pool->free_list = ((GC_MS_PObj_Wrapper*)ptr)->next_ptr;

    PObj_flags_SETTO(ptr, 0);

    --pool->num_free_objects;

    return ptr;
}
And by the way -- that code you posted was not the same code that I am working on. That is the code for the default Mark & Sweep algorithm. The code I posted is from the Incremental Mark & Sweep algorithm.

Note the gc_ms_ vs gc_ims_ prefix on the two different functions.
 
Old 09-07-2009, 06:23 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by jrtayloriv View Post
Why not just cast ptr to GC_MS_PObj_Wrapper ** and dereference it? Why cast it to void ** first?
This isn't a basic programming question; it's a question of programming technique for the person who wrote it.
Kevin Barry
 
Old 09-08-2009, 04:48 PM   #6
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 366

Original Poster
Blog Entries: 1

Rep: Reputation: 44
Quote:
Originally Posted by ta0kira View Post
This isn't a basic programming question; it's a question of programming technique for the person who wrote it.
Kevin Barry
They were basic programming questions.

I've found an answer to the first question via the C programming channel on the Freenode IRC network. The answer is, there is no reason to make that cast to void **, and that it should have just been this instead:

pool->free_list = (*(GC_MS_PObj_Wrapper **)ptr);

I got that answer from a person that was not a developer from the project. Thus, a general knowledge of C was enough to answer the question. Thus it is a generic programming question.

As far as the second question, I have yet to find an answer to that, but once again, I'm sure it's a question about C programming, and not about the particular application I'm looking at.

The question was:

Quote:
How are they are casting between the two different structs that are a different size? Does casting a PObj * to a GC_MS_PObj_Wrapper * act as some type of "overlay" that keeps the flags field from the PObj intact, and adds on the next_ptr field?
But just so it's a general programming question, I could say:

How is it possible to cast between two structs that are a different size in C? For instance, if I had two structs that looked like this:

Code:
typedef struct pobj_t {
    unsigned long flags;
} generic_question_struct;

typedef struct generic_question_Wrapper {
    size_t flags;
    struct generic_questiom_Wrapper * next_ptr;
} generic_question_Wrapper;
Does casting a generic_question_struct * to a generic_question_Wrapper * act as some type of "overlay" that keeps the flags field from the generic_question_struct intact, and adds on the next_ptr field?

Thanks,
jrtayloriv

Last edited by jrtayloriv; 09-08-2009 at 05:56 PM.
 
Old 09-08-2009, 05:05 PM   #7
jiml8
Senior Member
 
Registered: Sep 2003
Posts: 3,171

Rep: Reputation: 116Reputation: 116
Quote:
Does casting a generic_question_struct * to a generic_question_Wrapper * act as some type of "overlay" that keeps the flags field from the generic_question_struct intact, and adds on the next_ptr field?
No. Quite the opposite.

C will assume that you know what you are doing; it doesn't force much on you at all.

In your example, when you cast generic_question_struct * to a generic_question_Wrapper *, then the address your cast pointer points to will be treated exactly like a generic_question_struct location. Thus, when you write to ptr->flags, you are going to write an unsigned long instead of a size_t (which might be an unsigned long, depending on your platform). If that happens to work, great. If not, you will corrupt your target structure.
 
Old 09-08-2009, 05:52 PM   #8
jrtayloriv
Member
 
Registered: Jun 2004
Location: Inland NW, US
Distribution: Ubuntu
Posts: 366

Original Poster
Blog Entries: 1

Rep: Reputation: 44
Quote:
Originally Posted by jiml8 View Post
In your example, when you cast generic_question_struct * to a generic_question_Wrapper *, then the address your cast pointer points to will be treated exactly like a generic_question_struct location. Thus, when you write to ptr->flags, you are going to write an unsigned long instead of a size_t (which might be an unsigned long, depending on your platform).
Thank you. That cleared everything up.
 
  


Reply

Tags
pointers, void



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Help on void pointer yfaye Programming 7 04-18-2009 07:10 AM
casting void* to an abstract class qwijibow Programming 3 12-23-2006 08:43 PM
casting std::string to void * lucky6969b Programming 1 03-17-2006 04:38 AM
void * pointer in function xailer Programming 23 01-16-2004 02:14 PM
void pointer help gonnaWorkItOut Programming 1 10-12-2003 11:52 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:54 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration