File of words to a linked-list of words I'd like to get a review for the function build_list() which reads a file containing words (separated by spaces) and returns a linked-list of words:

#include &lt;stdio.h&gt;
#include &lt;assert.h&gt;
#include &lt;stdlib.h&gt;

typedef struct ListNode {
    char* word;
    struct ListNode *next;
} ListNode;

typedef struct List {
    ListNode *head;
    ListNode *tail;
} List;

List* build_list(char* fileName)
{
    FILE* file = fopen(fileName, "r");
    assert(file != NULL);

    List* list = malloc(sizeof(List));
    assert(list != NULL);
    list-&gt;head = NULL;
    list-&gt;tail = NULL;

    char c;
    int word_size = 1;
    char* word = malloc(word_size);
    int word_count = 0;

    while ((c = fgetc(file)) != EOF)
    {
        assert(!ferror(file));

        while (c != ' ' &amp;&amp; c != EOF)
        {
            if (word_count == word_size)
            {
                word_size += 1;
                word = realloc(word, word_size);
                assert(word != NULL);
            }

            word[word_count++] = c;

            c = fgetc(file);
            assert(!ferror(file));
        }

        word = realloc(word, word_size + 1);
        word[word_size] = '\0';

        ListNode *node = malloc(sizeof(ListNode));
        assert(node != NULL);
        node-&gt;next = NULL;
        node-&gt;word = word;

        if (list-&gt;head == NULL)
        {
            list-&gt;head = node;
            list-&gt;tail = node;
        }
        else
        {
            list-&gt;tail-&gt;next = node;
            list-&gt;tail = node;
        }

        if (c == EOF)
            break;

        word_count = 0;
        word_size = 1;
        word = malloc(word_size);

    }

    free(word);

    assert(!ferror(file));

    return list;
}
assert() isn't meant for runtime errors like an invalid filename. It's meant to aid in debugging by catching logical errors. Essentially, it says, "There should be no possible way this statement can be false. If it is false, something about this program is invalid, so I need to blow up."

A good use of assert() here would be:

List* build_list(char* fileName)
{
    assert(fileName &amp;&amp; fileName[0]);
    // Alternately (more verbose, but maybe more clear):
    assert(fileName != NULL &amp;&amp; fileName[0] != '\0');
    // Another alternative, which gives a helpful message
    // if it fails
    assert(fileName &amp;&amp; fileName[0]
        &amp;&amp; "build_list(char* fileName) was given a null or empty fileName");


This way, if you write a function somewhere else that passes a null filename into build_list, you'll get notified of the programming error.

A runtime error such as a missing file is better handled by returning some kind of error. You could return NULL on error, or you could take a List* (or List**) as an argument and return an integer result (0 for success is typical).