0

I have a while loop that reads through a CSV file, gets the first and second entries, and adds it into a hash table implemented in C. I've tested it with small files with around 40 entries, and it works fine, but when I try to pass in any file larger than that, the WHILE part causes an infinite loop.

The code that handles the adding is shown below:

void populateTable(Table *table, char *name) {
    FILE *file = fopen(name, "r");
    if(file != NULL) {
        while(!feof(file)) {
            char line[128];
            fgets(line, sizeof line, file);
            char key[64];
            int value;
            sscanf(line, "%[^','],%d", key, &value);
            addEntry(table, key, value);
        }
    }
    fclose(file);
    return;
}

I've tried using GDB to debug the program. When I have 42 entries, all entries are entered correctly, and they can be printed and accessed correctly. When there are any more, the code becomes unresponsive. When I step through with GDB, it says

#0 __lll_lock_wait_private() at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:97
#1 0x00007ffff763f518 in _L_lock_28 () from /lib/x96_64-linux-gnu/libc.so.6
#2 0x00007ffff763f4b1 in _IO_feof (fp=0x60c070) at feof.c:37
#3 0x0000000000402e78 in populateTable (table=0x604250, name=0x40310b "data/census.csv") at Table.c:193
#4 0x00000000004016aa in main (argc=2, argv=0x7fffffffeae8) at server.c:189
Employed Russian
  • 164,132
  • 27
  • 242
  • 306
anarian
  • 25
  • 1
  • 7
  • `nptl` _is the Native POSIX Thread Library_. So your code is dead-locking in some deep nested library. Try showing the full stack trace, if available, with the gdb command `where` or `backtrace`. – rodrigo Feb 11 '14 at 21:51
  • `#0 __lll_lock_wait_private() at ../nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S:97 #1 0x00007ffff763f518 in _L_lock_28 () from /lib/x96_64-linux-gnu/libc.so.6 #2 0x00007ffff763f4b1 in _IO_feof (fp=0x60c070) at feof.c:37 #3 0x0000000000402e78 in populateTable (table=0x604250, name=0x40310b "data/census.csv") at Table.c:193 #4 0x00000000004016aa in main (argc=2, argv=0x7fffffffeae8) at server.c:189` – anarian Feb 11 '14 at 22:51
  • 1
    Ok, so you have a deadlock in your call to `feof()`. And since your `file` isn't shared anywhere, the most likely cause of this is memory corruption. That is, your `addEntry()` somewhere corrupts the stack memory, probably because of some local buffer overflow, or similar... – rodrigo Feb 11 '14 at 23:10
  • BTW, your call to `fclose()` should be inside the `if`, as calling `fclose(NULL)` is undefined. Probably not related to your problem, though. – rodrigo Feb 11 '14 at 23:11
  • [Don't use `feof` in `while` condition](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong). – herohuyongtao Feb 12 '14 at 03:43
  • @herohuyongtao "don't use feof" -- why on Earth not? – Employed Russian Feb 12 '14 at 03:44
  • @EmployedRussian: see the hero link posted. Basically, using feof this way leads to undefined behavior when you get to the end of the file, since it doesn't return true until after you've had a failed read past the end of the file. – Chris Dodd Feb 12 '14 at 06:29
  • @ChrisDodd There is *nothing* wrong with using `feof` as the loop condition (but obviously return value of `fgets` also needs to be checked). – Employed Russian Feb 12 '14 at 15:30
  • Found the issue, it was a malloc error, I tried to allocate an array of structs by allocating each one individually rather than allocating number * sizeof(struct) to the pointer. Thanks for everyone's help! – anarian Feb 12 '14 at 16:19

1 Answers1

1

The code for feof reads:

int _IO_feof (_IO_FILE *fp)
{
  int result;
  CHECK_FILE (fp, EOF);
  _IO_flockfile (fp);
  result = _IO_feof_unlocked (fp);
  _IO_funlockfile (fp);
  return result;
}

You are deadlocked on the _IO_flockfile line.

The only way I can think of for this to happen is if the file itself is corrupted.

It is very likely that you have heap corruption (overflow of a malloced buffer) elsewhere in your program, which triggers this. Valgrind is likely to point you straight at your bug.

Employed Russian
  • 164,132
  • 27
  • 242
  • 306
  • Ah yes, I do have a malloc error. I was trying to allocate an array of structs inside a struct, but mistakenly attempted allocating each individual element in the pointer, rather than allocating the number * sizeof(struct). It works now, thanks! – anarian Feb 12 '14 at 16:18