0
#include <search.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define HASHT_SIZE 2000000
#define N 1000000
char *keys[N];
int keySize;

int main() {
    ENTRY e, *ep;
    hcreate(HASHT_SIZE);
    FILE *f;
    f = fopen("./map.txt", "r");
    char line[500], *li;
    double dub;
    while (fgets(line, sizeof(line), f)) {
        e.key = line;
        if (hsearch(e, FIND) == NULL) {
            e.data = (void *)keySize;
            li = malloc(strlen(e.key) * sizeof(char));
            strcpy(li, line);
            ep = hsearch(e, ENTER);
            keys[keySize++] = li;
            if (ep == NULL) {
                printf("failure");
                exit(1);
            }
        }
    }
}

My problem is that lookups via hsearch(e,FIND) are returning NULL as soon as the next while(fgets(line,sizeof(line),f)) is run. Why is that? Why does hsearch(keys[0],FIND) fail as soon as this fgets is called? How is the hash table forgetting the entry when fgets is called?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Berlios
  • 3
  • 2
  • 3
    One bug here: `li=malloc(strlen(e.key)*sizeof(char));` - should be: `li=malloc(strlen(e.key)+1);` – Paul R Aug 07 '18 at 15:07
  • 1
    You have forgotten that `char` strings are really called ***null-terminated** byte strings*. That *null-terminator* need space too. Since you don't allocate enough memory you will have [*undefined behavior*](https://en.wikipedia.org/wiki/Undefined_behavior) when `strcpy` writes out of bounds of your allocated memory. – Some programmer dude Aug 07 '18 at 15:07
  • 3
    You made a copy of the string with `malloc` and `strcpy`, but you forgot to update `e.key` to point to that string. – user3386109 Aug 07 '18 at 15:13
  • You should check the return value of `malloc`, although that is unlikely to be the cause of the problem in this case. – Ian Abbott Aug 07 '18 at 15:15
  • I changed my code to add space for the null character for the malloc call but my problem is still there. As soon as I break out of this while loop, hsearch(keys[0],FIND) is returning null when I have verified that in the while loop it wasn't null. – Berlios Aug 07 '18 at 15:22
  • 1
    As pointed out by @user3386109, you should set `e.key=li;` before `ep=hsearch(e,ENTER);` because `hsearch` does not make a copy of the key string and you overwrite `line` for each entry. – Ian Abbott Aug 07 '18 at 15:27
  • @user3386109 even though e.key is already set to equal to line at this point and I'm literally copying that string via strcpy(li,line) updating the e.key to equal li for some reason fixed the problem. How is an assignment and strcpy different? Why would a second assignment of li be needed? – Berlios Aug 07 '18 at 15:32
  • @IanAbbott but e.key=line is set beforehand. You're right that e.key=li fixes it but I don't understand why. e.key is reset to line on each entry in the while loop. – Berlios Aug 07 '18 at 15:33
  • 1
    `e.key` is just a pointer. So if you `hsearch(e, ENTER)` when `e.key` points to `line`, then every entry in the hash table points to `line`, and every entry in the hash table is the last string read by `fgets`. – user3386109 Aug 07 '18 at 15:35
  • 1
    You probably also want to [remove the newline that `fgets` puts in the buffer](https://stackoverflow.com/questions/2693776). Right now, all of the hash table keys have a newline at the end. – user3386109 Aug 07 '18 at 15:37
  • 4
    `hsearch(e, ENTER)` copies `e` into the hash table, but it does not make a copy of the string pointed to by `e.key`. You have `e.key` set to `line`, so when you call `fgets(line, sizeof(line), f)` again, you are overwriting the buffer for the key that is already in the hash table. So the old key will no longer match its hash code and a subsequent `hsearch(e,FIND)` for that key will fail. Also, as pointed out by @user3386109, you may want to remove the newline characters from the key before calling `hsearch` unless you want the newline to be part of the key. – Ian Abbott Aug 07 '18 at 15:55
  • @IanAbbott That makes a lot of sense. I agree with everything you said – Berlios Aug 07 '18 at 16:03
  • 1
    You haven't initialized `keySize` anywhere. – lurker Aug 07 '18 at 16:06
  • @user3386109 you're right about everything. Thanks for the help. – Berlios Aug 07 '18 at 16:09
  • @lurker it's a global variable initialized to 0 and the casting is allowed. – Berlios Aug 07 '18 at 16:10

0 Answers0