Below is a kernel module which can be compiled and run nicely. I have written a method show which gets the pointer to a hashtable and prints it. But if I use the methods argument, b, I get a compilation error. I can only use the global variable a.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/hashtable.h>
MODULE_LICENSE("GPL");
typedef struct {
int age;
struct hlist_node my_next;
} my_type;
DEFINE_HASHTABLE(a, 3);
my_type *node1, *node2, *node3;
void show(struct hlist_head b[]){
int i;
my_type *temp;
printk(KERN_INFO "a: %p \tb: %p \n", a, b); // Always the same address.
hash_for_each(a, i, temp, my_next){ // Change the a to b
printk(KERN_INFO "%d\n", temp->age);
}
}
int init_module(void){
printk(KERN_INFO "Hi.\n");
node1 = kmalloc(sizeof(my_type), GFP_KERNEL);
node1->age = 28;
node2 = kmalloc(sizeof(my_type), GFP_KERNEL);
node2->age = 27;
node3 = kmalloc(sizeof(my_type), GFP_KERNEL);
node3->age = 20;
show(a);
hash_add(a, &node1->my_next, 0);
hash_add(a, &node2->my_next, 1);
hash_add(a, &node3->my_next, 1);
show(a);
return 0;
}
void cleanup_module(void){
kfree(node1);
kfree(node2);
kfree(node);
printk(KERN_INFO "Bye.\n");
}
The error I get is:
In file included from include/linux/thread_info.h:11:0,
from /usr/src/kernels/3.15.8-200.fc20.x86_64/arch/x86/include/asm/preempt.h:6,
from include/linux/preempt.h:18,
from include/linux/spinlock.h:50,
from include/linux/seqlock.h:35,
from include/linux/time.h:5,
from include/linux/stat.h:18,
from include/linux/module.h:10,
from /home/k/development/hash2/main.c:1:
/home/k/development/hash2/main.c: In function ‘show’:
include/linux/bug.h:33:45: error: negative width in bit-field ‘<anonymous>’
#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
^
I have tried playing with the definitions like using struct hlist_head * b[] and using in the hash_for_each macro the *b but non worked.
I also tried defining DEFINE_HASHTABLE(c, 3); inside the method show() as shown below works, but it's quite useless.
void show(struct hlist_head b[]){
int i;
my_type *temp;
DEFINE_HASHTABLE(c, 3);
printk(KERN_INFO "a: %p \tb: %p \n", a, b);
hash_for_each(c, i, temp, my_next){
printk(KERN_INFO "%d\n", temp->age);
}
}
So, why do I get this error? How do I solve it?
hash_for_each is a macro which in turn uses another macro (ARRAY_SIZE) to determine the size of the array passed to hash_for_each as first parameter.
You pass a pointer to hash_for_each as 1st parameter, this makes ARRAY_SIZE choke, as "pointers are not arrays".
To get aorund this, you might like to take the approach proposed by Paul R in his comment to your question, that is implementing show() as a macro as well.
The compilation error you observe is by intention, to keep you from using code not doing what it was intended to do. The error message itself
error: negative width in bit-field ...
however is heavily missleading.
Related
Based on the documentation found here, I wrote the following code in C:
adj_hash_table.h
typedef struct {
int id_0;
int id_1;
}id_t_;
typedef struct {
id_t_ id;
double value;
UT_hash_handle hh;
}cell_t;
void add_(int id_0, int id_1, double value, cell_t *cells);
void free_table( cell_t *cells);
void main();
adj_hash_table.c
#include <stdio.h>
#include "uthash/src/uthash.h"
#include "adj_hash_table.h"
void add_(int id_0, int id_1, double value, cell_t *cells){
cell_t l, *p;
memset(&l, 0, sizeof(cell_t));
l.id.id_0 = id_0;
l.id.id_1 = id_1;
HASH_FIND(hh, cells, &l.id, sizeof(id_t_), p);
if (p == NULL) {
printf("Not found %d, %d\n", id_0, id_1);
p = (cell_t *)malloc(sizeof *p);
memset(p, 0, sizeof *p);
p->id.id_0 = id_0;
p->id.id_1 = id_1;
HASH_ADD(hh, cells, id, sizeof(id_t_), p);
}
else
{
printf("Found %d, %d\n", id_0, id_1);
}
p->value = value;
}
void free_table( cell_t *cells){
cell_t *p, *tmp;
HASH_ITER(hh, cells, p, tmp) {
HASH_DEL(cells, p);
free(p);
}
}
void main(){
int nb_cells;
cell_t *cells = NULL;
add_(0,0,1.0,cells);
add_(0,1,2.0,cells);
add_(0,0,3.0,cells);
nb_cells=HASH_COUNT(cells);
printf("number of cells: %d\n", nb_cells);
free_table(cells);
}
When I compile it using: gcc -g -Wall -o adj_hash_table adj_hash_table.c and later run it using ./adj_hash_table, I get the following output:
Not found 0, 0
Not found 0, 1
Not found 0, 0
number of cells: 0
But I expect:
Not found 0, 0
Not found 0, 1
Found 0, 0
number of cells: 2
which makes me think that HASH_ADD is not working. The examples from here work fine for me. What am I doing wrong? Also, is my free_table method correct? Thanks !!
From the "Passing the hash pointer into functions" section of the referenced documentation:
In the example above users is a global variable, but what if the caller wanted to pass the hash pointer into the add_user function? At first glance it would appear that you could simply pass users as an argument, but that won’t work right.
You really need to pass a pointer to the hash pointer:
The reason it’s necessary to deal with a pointer to the hash pointer is simple: the hash macros modify it (in other words, they modify the pointer itself not just what it points to).
That is, you need to pass cell_t ** to your add_ function instead of cell_t * and then call the HASH macros with *cells.
void add_(int id_0, int id_1, double value, cell_t **cells){
....
HASH_FIND(hh, *cells, &l.id, sizeof(id_t_), p);
....
HASH_ADD(hh, *cells, id, sizeof(id_t_), p);
And calls would be:
cell_t *cells = NULL;
add_(0,0,1.0,&cells);
add_(0,1,2.0,&cells);
add_(0,0,3.0,&cells);
having some trouble finding out the syntax around returning a vector from a pthread function. Here's currently what I have:
typedef struct vectorData {
vector v1;
vector v2;
} vectorData;
void *vectorAddThread(void *arg) {
vectorData *data = (vectorData *)arg;
vector v1 = data->v1;
vector v2 = data->v2;
vector result = {v1->x + v2->x, v1->y + v2->y, v1->z + v2->z};
return (void*) result;
}
I'm getting errors on the last two lines about the return result, and the the adding part. Thanks
You can't convert a struct to a void * pointer. You need dynamically allocate a vector in your case with malloc, and return the pointer.
vector *result = malloc(sizeof(vector));
result->x = ?;
result->y = ?;
result->z = ?;
return (void *)result;
Now that would solve the issue of returning a struct from a function that returns void *. But if you're using pthreads you shouldn't be returning objects from them, you need to pass the vector to it as user data in arg.
This is probably easiest:
typedef struct vectorData {
vector v1;
vector v2;
vector result;
} vectorData;
Saves messing about with dubious thread-stack vars, mallocs etc. and ties the result output directly to the inputs.
The thread start function in pthread library returns a pointer to void. Can return any pointer type by type-casting it to (void *). The return value can be accessed by pthread_join(3).
However, a vector needs the type of element information also. Not sure if type-casting it to (void *) and accessing it again will work fine. Using it as an element of structure seems better.
In the following example, I am returning a pointer to structure from the thread start function. The structure contains a vector and two character arrays. You can change it according to your requirement. I am using two pointers to show that data is copied on the variable used for pthread_join(3).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <vector>
void *functionPthread(void *);
struct retStruct
{
std::vector<int> vecNumber;
char name[20];
char city[20];
};
struct retStruct *r2;
struct retStruct *r1;
int main()
{
int rc, i;
pthread_t th;
r2 = (retStruct*) malloc(sizeof(retStruct));
memset(r2, '\0', sizeof(r2));
if(rc = pthread_create(&th, NULL, &functionPthread, NULL))
{
printf("Thread creation failed, return code %d, errno %d", rc, errno);
}
pthread_join(th, (void**)&r2);
for(i = 0; i < r2->vecNumber.size(); i++)
printf("Vectore element at index %d = %d\n", i, r2->vecNumber.at(i));
printf("Name: %s, City: %s, Vector Number: %d\n", r2->name, r2->city, r2->vecNumber.front());
free(r1);
free(r2);
return 0;
}
void *functionPthread(void *)
{
r1 = (retStruct*) malloc(sizeof(retStruct));
memset(r1, '\0', sizeof(r1));
strcpy(r1->name, "xxxx");
strcpy(r1->city, "yyyy");
r1->vecNumber.push_back(11);
r1->vecNumber.push_back(12);
return r1;
}
Today I'm trying to implement a queue, but one that works with structures within arrays (I've always hated the C 'Array of Structs' terminology, as I am not trying to make that). However, when I try and do a basic initialization, I run into the compiler error as follows.
"Request for member '**' in something not a structure or union. "
Here's my code, not much as of now.
//------------------------Preprocessor Instructions. ------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#define MAX 128
#define BUFFER 120
//-------------------------Global Stuff -------------------------------------------------
int head=-1;
int tail=-1; //Starting head and tail at -1.
struct Entry{
int Data;
int Hops;
};
struct Entry Queue[MAX]; //Queue made up of structs.
int visited[MAX];
//------------------------Function Definitions. -----------------------------------------
int QueuePush(struct Entry *q, int num);
int QueuePop(struct Entry *q);
int IsEmpty(struct Entry *q);
//------------------------Main. ---------------------------------------------------------
int main(void)
{
int i;
while(i<MAX){
Queue.Data[i]=0;
Queue.Hops[i]=0;
i++;
}
for(i=0;i<=10;i++){
printf("Queue Data[%d] = %d \n", i, Queue[i].Data);
printf("Queue Hops = %d \n", Queue[i].Hops);
}
}
Am I making some scary, large error in the way I'm defining the array? Or is the issue syntactical? Thanks in advance.
You should write
Queue[i].Data = 0;
Queue[i].Hops = 0;
not
Queue.Data[i] = 0;
Queue.Hops[i] = 0;
In you initialization while loop, you have written Queue.Data[i] instead of Queue[i].Data.
And another thing:
int i;
while(i<MAX){
Queue.Data[i]=0;
Queue.Hops[i]=0;
i++;
}
Here i contains random number and this loop will not work, so you should write int i = 0; or use for instead of while.
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Other way I thought as,
struct *_my_type x = (struct _my_type *)malloc(sizeof(struct _my_type));
void_x = x
printf(Value: %d\n", x->a);
But still I'm getting seg-fault error.
ok here is the problem with void*....
e.g.
in core.c
void init_my_type(hidden_my_type a)
{
my_type *the_a = malloc(...);
a = the_a // <<<<<<<<<<<<<<<<<<<<<<<<<<<< is this correct?! a is void* and the_a // is original type
pthread_cond_init(&the_a->...);
.. (in short any other methods for init ..)
}
void my_type_destroy(my_hidden_type x)
{
my_type *the_x = x;
pthread_detroy(&the_x-> ...);
}
in main.c
test()
{
my_hidden_type x;
init_my_type(x);
....
my_type_detroy(x);
}
this it self should fail. as in main.c test function, x is void* ... init will allocate but in destroy I'm again passing void* .. which can be anything!
EDIT (Solved for me)
In api.h
typedef void* hidden_my_type;
void do_something(my_type x);
In core.c
struct _my_type
{
int a;
}
void init_hidden_type(hidden_my_type void_p_my_type)
{
struct _my_type *real_my_type = (struct _my_type *)malloc(sizeof(struct _my_type));
//--- Do init for your type ---
void_p_my_type = real_my_type;
}
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
Version 0 — Critique of Question's Code
The posted code does not compile.
api.h
typedef void* hidden_my_type;
void do_something(my_type x);
This defines hidden_my_type but not the my_type that is passed to do_something(). Presumably, you intended:
typedef void *my_type;
void do_something(my_type x);
core.c
struct _my_type
{
int a;
}
As noted below too, there is a semi-colon missing after the structure definition.
void do_something(hidden_my_type void_x)
{
struct *_my_type x = void_x;
printf("Value: %d\n", x->a);
}
You have the hidden_my_type vs my_type problem again. You have the * of the pointer where it cannot go; it must go after the struct _my_type. You probably intended something like:
void do_something(my_type void_x)
{
struct _my_type *x = void_x;
printf("Value: %d\n", x->a);
}
This is now syntactically correct (I think; I haven't actually run it past a compiler). You have not shown how it is used; indeed, since the user code has no way to generate a pointer to a valid structure, there is no way for this code to be used safely.
Your test code (unshown — why don't you show your test code) might look something like this:
#include "api.h"
int main(void)
{
my_type x = 0;
do_something(x);
return 0;
}
Alternatively, it might not have the = 0 initializer in place. Either way, your code is unable to function sanely, and a core dump is almost inevitable. When you hide the structure from the user, you have to provide them with a mechanism to get hold of a valid (pointer to) the structure, and you've not done that.
Version 1
This is a better way to do it, because it is more nearly type-safe:
api.h version 1
typedef struct _my_type *my_type;
void do_something(my_type x);
core.c version 1
#include "api.h"
struct _my_type
{
int a;
};
Note the added semi-colon, and the include of the api.h file.
void do_something(my_type x)
{
// Now you don't have to do casting here!
//struct *_my_type x = void_x; /*Don't understand is that correct way to do, as I'm getting segmentation fault error */
printf("Value: %d\n", x->a);
}
Version 2
Actually, we can debate the wisdom of hiding the pointer; I would prefer not to do so:
api.h version 2
#ifndef API_H_INCLUDED
#define API_H_INCLUDED
typedef struct my_type my_type;
extern void do_something(my_type *x);
extern my_type *my_type_initializer(void);
extern void my_type_release(my_type *x);
#endif /* API_H_INCLUDED */
core.c version 2
#include "api.h"
#include <stdio.h>
#include <stdlib.h>
struct my_type
{
int a;
};
void do_something(my_type *x)
{
printf("Value: %d\n", x->a);
}
my_type *my_type_initializer(void)
{
my_type *x = malloc(sizeof(*x));
x->a = 57; // More plausibly, this would be 0
return x;
}
void my_type_release(my_type *x)
{
free(x);
}
main.c
#include "api.h"
int main(void)
{
my_type *x = my_type_initializer();
do_something(x);
my_type_release(x);
return 0;
}
That's nice and clean. Of course, the user cannot allocate a struct my_type (only a pointer to it), so you need a function to allocate the structure for them. Think of the Standard C Library, and the FILE type, and fopen() to allocate and fclose() to release and fprintf() etc to manipulate the type. The my_type_initializer() is functioning as an analogue to fopen(), my_type_release() as an analogue to fclose(), and do_something() as an analogue to fprintf().
Jonathan, you beat me to an answer, but this may be helpful as well. Here, api.c contains the (private) implementation, and api.h provides the interface to be consumed by other code such as main.c.
// main.c: uses only the public interface to the private code
#include "api.h"
int main(int argc, char *argv[]) {
void *foo;
foo = create_foo("five", 5);
print_foo(foo);
delete_foo(foo);
}
// EOF main.c
// api.h: the public interface
#ifndef _api_h_
#define _api_h_
void *create_foo(char *name, int number);
void print_foo(void *foo);
void delete_foo(void *foo);
#endif // _api_h_
// api.c: the private implementation
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// The real structure is private to the implementation.
typedef struct {
char name[20];
int number;
} real_struct;
// Create a new structure, initialize, return as ptr-to-void.
void *create_foo(char *name, int number) {
real_struct *s = malloc(sizeof(real_struct));
strcpy(s->name, name);
s->number = number;
return (void *) s;
}
// Print the data.
void print_foo(void *foo) {
real_struct *s = (real_struct *) foo;
printf("name: %s, number: %d\n", s->name, s->number);
}
// Release the memory.
void delete_foo(void *foo) {
free(foo);
}
// EOF api.c
This code should compile and run:
$ gcc -o foo main.c api.c
$ ./foo
name: five, number: 5
I am going to use GLib's Hash table implementation in a C program and just for now
I am just experimenting with it. I wrote the following piece of code for testing:
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int main(){
// Some codes and declerations here
GHashTable *g_hash_table;
uint32_t *a;
a=(uint32_t *)malloc(sizeof(uint32_t));
if(a==NULL){
printf("Not Enough Mem For a\n");
return 1;
}
*a=1123231;
uint32_t* key;
key=(uint32_t *)malloc(sizeof(uint32_t));
if(key==NULL){
printf("Not Enough Mem For key\n");
return 1;
}
*key=122312312;
int i;
g_hash_table=g_hash_table_new(g_int_hash, g_int_equal);
for(i=0;i<TABLE_SIZE;i++){
*key+=1;
*a+=1;
g_hash_table_insert(g_hash_table,(gpointer)key,(gpointer)a);
uint32_t *x=(uint32_t *)g_hash_table_lookup(g_hash_table,key);
printf("Counter:%d, %u\n",i,*x);
}
GHashTableIter iter;
g_hash_table_iter_init(&iter,g_hash_table);
int size=g_hash_table_size(g_hash_table);
printf("First size: %d\n",size);
uint32_t *val;
uint32_t *key_;
int counter=0;
// My problem is in the following loop it
// always returns the same and the last key value pair
while(g_hash_table_iter_next(&iter,(gpointer*)(void*)&key_,(gpointer*)(void*)&val)){
counter++;
printf("%u %u\n",(uint32_t)*key_,(uint32_t)*val);
printf("Counter: %d\n",counter);
}
//Some more code here
return 0;
}
Somehow my test code iterates correctly but in the loop it always returns the last key and last value pairs and it is always the same. What is the problem here? The above code may not run with its as it is format. I just copied and pasted some parts to give a clear idea about what I am trying to do.
I think your insertion code is broken. You're only allocating memory once, but then doing many inserts, incrementing the value stored in the single allocated location between each.
The hash table stores your pointer, so it will end up associating each key with the same pointer.
Also, you should probably use g_malloc() with glib, for consistency.
And I always recommend using sizeof on objects rather than on their types; that way you don't repeat yourself in quite as dangerous a way. So, instead of
guint32 *a;
a = g_malloc(sizeof (guint32));
use
a = g_malloc(sizeof *a);
This way you "lock down" the dependency, so that you always allocate enough room to store whatever a points at, even if you later change the type.
Further, you should take a hard look at every cast you do. Casting any non-constant pointer to gpointer is a sign of a hesitant programmer. With glib, gpointer is just a synonym for void *, so that cast is never needed. It just adds cruft to your code, making it harder to read.
There is an error in key, a declarations. You always put the same pointer in the hash table. Try:
#include <glib.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define TABLE_SIZE 12
int main() {
// Some codes and declarations here
GHashTable *g_hash_table;
int i;
g_hash_table = g_hash_table_new(g_int_hash, g_int_equal);
for (i=0; i<TABLE_SIZE; i++)
{
uint32_t* key = (uint32_t *)malloc(sizeof(uint32_t));
uint32_t* a = (uint32_t *)malloc(sizeof(uint32_t));
*key = i;
*a = i+10;
g_hash_table_insert(g_hash_table, (gpointer)key, (gpointer)a);
uint32_t *x = (uint32_t *)g_hash_table_lookup(g_hash_table,key);
printf("key: %d --> %u\n", *key ,*x);
}
GHashTableIter iter;
int size=g_hash_table_size(g_hash_table);
printf("First size: %d\n", size);
uint32_t *val;
uint32_t *key_;
// My problem is in the following loop
// it always returns the same and the last key value pair
g_hash_table_iter_init (&iter, g_hash_table);
while (g_hash_table_iter_next (&iter, (gpointer) &key_, (gpointer) &val))
{
printf("key %u ---> %u\n", (uint32_t)*key_, (uint32_t)*val);
}
// TODO: free keys
return 0;
}