Search code examples
cpointersstructvoid-pointersdereference

Dereferencing 'void *' pointer when using struct


I'm trying to make use of inode's i_private and store a struct with name and block number in it:

struct osffs_inode_private_info* info;
inode->i_private = kzalloc(sizeof(struct osffs_inode_private_info), GFP_KERNEL);
inode->i_private = info;
strncpy(inode->i_private->name, "private succ", OSFFS_MAX_NAME_LEN);

Where the struct is defined as follows:

struct osffs_inode_private_info {
    char name[OSFFS_MAX_NAME_LEN];
    __be64 block;
};

When I try to compile, I get a warning that I am

"dereferencing a 'void *' pointer"

and an error

"request for member ‘name’ in something not a structure or union"

in the line where I do the strncpy().

I know there are many threads/questions about dereferencing a void pointer and it seems like I just have to do a cast or such. But unfortunately, I don't know how to apply that to my problem.


Solution

  • First of all, in your code

    inode->i_private = kzalloc(sizeof(struct osffs_inode_private_info), GFP_KERNEL);
    inode->i_private = info;
    

    you're leaking memory. In the later statement, you're overwriting the previous pointer in inode->i_private by assigning to it.

    maybe you wanted to do

    info = inode->i_private;
    

    That said, the issue in the question is with the said usage of i_private. This being a void pointer, cannot be dereferenced.

    Quoting C11, chapter §6.5.2.3, Structure and union members

    The first operand of the -> operator shall have type ‘‘pointer to atomic, qualified, or unqualified structure’’ or ‘‘pointer to atomic, qualified, or unqualified union’’,[...]

    That's why, you have to cast the void * to the pointer-to-required-type to make that eligible to be used as the left-operand for member access operator (->).

    You need to use something like

     strncpy( ((struct osffs_inode_private_info *)(inode->i_private))->name, 
               "private succ", 
                OSFFS_MAX_NAME_LEN);