c - Kernel Device Driver "dereferencing 'void *' pointer -
i learning how write device drivers linux, , have question regarding use of generic data structures.
i have assignment, have functional...so i'm not asking homework...
this assignment requires device able enqueue , dequeue elements fifo buffer. made buffer "generic" element size used(and specified @ runtime). source included below(note not kernel version, error same)...kernel version requires kmalloc, copy_to/from_user() etc...
#include <stdio.h> #include <stdlib.h> #include <string.h> struct rb_buffer { void* rbdata; unsigned int getindex; //index remove element unsigned int putindex; //index put element @ unsigned int capacity; //max elements buffer holds unsigned int elemcount; //num elements inserted unsigned int elemsize; //size of each element }; void* rb_kcreate(int numelements, unsigned int elementsize); int putring(struct rb_buffer *rbptr, void* data); int getring(struct rb_buffer *rbptr, void* data); //creates ring buffer of specified number of elements , element size. //returns void* pointer pointing rb_buffer struct. pointer can //then used on putring , getring functions. void* rb_kcreate(int numelements, unsigned int elementsize) { struct rb_buffer *newbuf = malloc(sizeof(struct rb_buffer)); if(newbuf == null) return 0; newbuf->rbdata = (void*)malloc(elementsize*numelements);//, gfp_kernel); if(newbuf->rbdata == null) { free(newbuf); return 0; } newbuf->capacity = numelements; newbuf->elemsize = elementsize; newbuf->getindex = 0; newbuf->putindex = 0; newbuf->elemcount = 0; return newbuf; } //puts element in buffer. returns -1 if full, 0 on success //send data through void* data argument int putring(struct rb_buffer *rbptr, void* data) { int = 0; if ( rbptr->elemcount >= rbptr->capacity ) return -1; memcpy(&rbptr->rbdata[rbptr->putindex * rbptr->elemsize], data, rbptr->elemsize); rbptr->putindex++; if (rbptr->putindex >= rbptr->capacity ) rbptr->putindex = 0; rbptr->elemcount++; return 0; } //removes element in buffer. returns -1 if empty, 0 on success //data returned through data pointer int getring(struct rb_buffer *rbptr, void *data) { if ( !rbptr->elemcount ) return -1; rbptr->elemcount--; memcpy(data, &rbptr->rbdata[rbptr->getindex * rbptr->elemsize], rbptr->elemsize); rbptr->getindex++; if ( rbptr->getindex >= rbptr->capacity ) rbptr->getindex = 0; return 0; }
when compile kernel module, warnings:
kringbuf_generic.c:53: warning: dereferencing ‘void *’ pointer kringbuf_generic.c:72: warning: dereferencing ‘void *’ pointer
the error occurs here in putring(in memcpy)
if ( rbptr->elemcount >= rbptr->capacity ) return -1; memcpy(&rbptr->rbdata[rbptr->putindex * rbptr->elemsize], data, rbptr->elemsize); rbptr->putindex++;
and here in getring, in memcpy() function
rbptr->elemcount--; memcpy(data, &rbptr->rbdata[rbptr->getindex * rbptr->elemsize], rbptr->elemsize); rbptr->getindex++;
obviously since kernel module, not known use this, , fixing buffer element size limit usage of buffer.
is there way rid of warnings? or there fundamental thing should doing differently when developing such code?
i think problem code:
rbptr->rbdata[rbptr->getindex * rbptr->elemsize]
is trying index array pointed @ rbdata
, of type void *
. can't meaningfully make operation work on void*
pointer, because indexing array in c requires know size of elements in array, , definition void*
pointer elements of unknown type.
most compilers let anyway implicitly casting void*
char*
, reading raw byte values. however, it's not idea this, since operation isn't well-defined.
to fix , silence warning, consider explicitly typecasting rbdata
field char*
before dereferencing it:
((char *)rbptr->rbdata)[rbptr->getindex * rbptr->elemsize]
or alternatively, store char*
in struct avoid having repeatedly typecast.
hope helps!
Comments
Post a Comment