2

I can't figure out what I'm doing wrong. I am learning C so sorry if this is obviously wrong, but I'm trying to use uthash to make a hash map of stocks and their prices. But when I add stocks to my hash map, I get the above error.

What I did was take the example from their site and ran it to make sure it worked, once it worked as expected I changed the values to fit my problem. In the original code, the variable id in the struct was an integer but I changed it to a char(instead of number, I wanted to use the stock ticker as the key), then I started to the following errors:

../src/stackCsamples.c:87: warning: passing argument 1 of '__builtin_object_size' makes pointer from integer without a cast
../src/stackCsamples.c:87: warning: passing argument 1 of '__builtin_object_size' makes pointer from integer without a cast
../src/stackCsamples.c:87: warning: passing argument 1 of '__builtin___strcpy_chk' makes pointer from integer without a cast
../src/stackCsamples.c:87: warning: passing argument 1 of '__inline_strcpy_chk' makes pointer from integer without a cast
../src/stackCsamples.c:89: warning: passing argument 1 of 'strlen' makes pointer from integer without a cast
../src/stackCsamples.c:89: warning: passing argument 1 of 'strlen' makes pointer from integer without a cast
../src/stackCsamples.c:89: warning: passing argument 1 of 'strlen' makes pointer from integer without a cast

The problem seems to be with two lines here(87) which is strcpy(s->id, user_id); and (89) which is: HASH_ADD_STR( users, id, s );

How am I using both of these wrong? I looked strcpy up and it looks like it takes 3 items, but when I add the size I still get errors.

Here's a snippet of the parts I think are relevant:

#include <stdio.h>   /* gets */
#include <stdlib.h>  /* atoi, malloc */
#include <string.h>  /* strcpy */
#include "uthash.h"

struct my_struct {
    char id;                    /* key */
    float price;
    UT_hash_handle hh;         /* makes this structure hashable */
};

struct my_struct *users = NULL;

void new_stock(char *user_id, float price) {
    struct my_struct *s;

    s = (struct my_struct*)malloc(sizeof(struct my_struct));
    strcpy(s->id, user_id);
    s->price = price;
    HASH_ADD_STR( users, id, s );  /* id: name of key field */
}

int main() {
    printf("starting..");
    new_stock("IBM", 10.2);
    new_stock("goog", 2.2);
    return 0;
}
Lostsoul
  • 25,013
  • 48
  • 144
  • 239
  • What is `user_id`? How is it defined? Also how is `HASH_ADD_STR` defined? – Alok Save Jun 05 '12 at 03:02
  • @Als Sorry not sure I understand, I thought in this case user_id was just the name of the variable I passing to the function, in this case its either "IBM" or "good"? I think `HASH_ADD_STR` is a macro thats included with uthash. It was originally HASH_ADD_INT but I changed it to str since my main key was not an int. – Lostsoul Jun 05 '12 at 03:04
  • `strcpy`takes in address of the destination and the source strings,the function assumes destination is big enough to hold the string.In your case the destination is a `char` while the source is probably a string, you cannot copy a string to a char, there is not enough memory in a char(`1 byte`) to hold a string.You could just assign a char to another you don't need copying. – Alok Save Jun 05 '12 at 03:09
  • @Als your right..I didn't realize that..I know the sizes for INT,etc..I just made the mistake of thinking chars had a natural size as well didn't realize that python/java were adjusting it for me. Thanks for your help. – Lostsoul Jun 05 '12 at 03:23

2 Answers2

3

With this line:

strcpy(s->id, user_id);

You are trying to copy a string onto a char. Note that both arguments to strcpy are to be pointers to chars: char *.

Furthermore, note that you'll also need to make some space in memory for s->id, as a char[] or a char *. Hint: you've made space for the struct, but that only includes enough space for a single character for id.

If you want to use C then you should get a copy of K&R, but failing that, you might spend some time reviewing this.

pb2q
  • 58,613
  • 19
  • 146
  • 147
  • hmm..should I be using strcpy then in my case? When I try `s->id = user_id;` I still get the same error. – Lostsoul Jun 05 '12 at 03:07
  • you should prefer [`strncpy`](http://stackoverflow.com/questions/1258550/why-should-you-use-strncpy-instead-of-strcpy), which is the version that you may have been reviewing that accepts 3 arguments, but you need to understand how C handles strings first. – pb2q Jun 05 '12 at 03:09
1

You need to provide enough space in the structure for the user ID array, or dynamically allocate enough space. For instance, you might do:

enum { MAX_ID_LEN = 32 };
struct my_struct
{
    char id[MAX_ID_LEN];                    /* key */
    float price;
    UT_hash_handle hh;         /* makes this structure hashable */
};

Then you could use:

strcpy(s->id, user_id);

as long as you've checked that user_id is not longer than 31 characters plus null before hand. If you've not done that check, you should. If you refuse to do that check and don't mind truncating overlong user ID strings, then you could use:

strncpy(s->id, user_id, sizeof(s->id) - 1);
s->id[sizeof(s->id)-1] = '\0';

This ensures null termination; just using strncpy() alone does not. Beware, if the string (s->id) was much longer, you could find your code wasting time zeroing out the tail end of the string.


The residual warnings about strlen() are hidden by the HASH_ADD_STR() macro, but likely come from the same problem as the strcpy() warnings did — the s->id field was not a character pointer or a character array. The amended structure will likely quash those warnings too. For us to be sure, you'd have to show the definition of HASH_ADD_STR() and any macros it invokes.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • ahh..I changed the size and it worked. Sorry I've been working with integers so far and never chars, I just assumed(wrongly) that C just accepted any size I sent it. I did that and everything worked! I'll look into cropping the string like you mentioned. – Lostsoul Jun 05 '12 at 03:21