0

I'm trying to read in words from a text file in C using fscanf and putthem into a dynamically allocated array. However, I keep getting errors in Valgrind and (null) characters seem to be popping up in my output. I create a double pointer **str_array to hold each character array and initially allocate enough space for 4 character arrays. fscanf runs and stores the read in string into str[] and I use strcpy to copy str[]'s string into str_array. I realloc memory if str_array needs to hold more strings.

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

int main(int argc, char *argv[]) {
    char str[80];
    int word_alloc = 0;
    int word_count = 0;
    char **str_array;

    FILE *file;
    file = fopen(argv[1], "r");

    // Allocate memory to the array of strings (char arrays)
    word_alloc = 4;        
    str_array = (char **) malloc(sizeof(char*) * word_alloc);

    while (fscanf(file, "%s", str) != EOF) {
        // If there are more than 4 strings, double size
        if (word_count > word_alloc) {
            word_alloc *= 2;
            str_array = (char **) realloc(str_array, sizeof(char*) * word_alloc);
        }

        str_array[word_count] = (char *) malloc(sizeof(char) * (strlen(str) + 1));
        strcpy(str_array[word_count], str);
        ++word_count;
    }

    int i = 0;
    for (; i<word_count; i++) {
        printf("Word: %s\n", str_array[i]);
    }

    i = 0;
    for (; i<word_count; i++) {
        free(str_array[word_count]);
    }
    free(str_array);
    fclose(file);

    return 0;
}

Here's the Valgrind error code.

==6254== Memcheck, a memory error detector
==6254== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6254== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==6254== Command: ./a.out readin-test.txt
==6254== 
==6254== Invalid write of size 8
==6254==    at 0x4008A6: main (readin-test.c:25)
==6254==  Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254==    by 0x400835: main (readin-test.c:16)
==6254== 
==6254== Invalid read of size 8
==6254==    at 0x4008C0: main (readin-test.c:26)
==6254==  Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254==    by 0x400835: main (readin-test.c:16)
==6254== 
==6254== Conditional jump or move depends on uninitialised value(s)
==6254==    at 0x4C2BDA2: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254==    by 0x40094A: main (readin-test.c:37)
==6254==  Uninitialised value was created by a heap allocation
==6254==    at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254==    by 0x400871: main (readin-test.c:22)
==6254== 
==6254== 
==6254== HEAP SUMMARY:
==6254==     in use at exit: 999 bytes in 173 blocks
==6254==   total heap usage: 181 allocs, 8 frees, 5,631 bytes allocated
==6254== 
==6254== 999 bytes in 173 blocks are definitely lost in loss record 1 of 1
==6254==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254==    by 0x4008A5: main (readin-test.c:25)
==6254== 
==6254== LEAK SUMMARY:
==6254==    definitely lost: 999 bytes in 173 blocks
==6254==    indirectly lost: 0 bytes in 0 blocks
==6254==      possibly lost: 0 bytes in 0 blocks
==6254==    still reachable: 0 bytes in 0 blocks
==6254==         suppressed: 0 bytes in 0 blocks
==6254== 
==6254== For counts of detected and suppressed errors, rerun with: -v
==6254== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)
3
  • "%s" should be "%79s" in scanf. Also you write out of bounds when word_count == word_alloc. Commented Feb 2, 2016 at 3:33
  • Allocate with calloc (or initialize new memory to NULL) to eliminate the Conditional jump or move depends on uninitialised value(s) ...and.. do not cast the return of malloc... Commented Feb 2, 2016 at 3:35
  • Invalid write of size 8 is because you need to realloc when word_count >= word_alloc, (not just > ) since C arrays are zero based. You store word 0, 1, 2, 3 (that is 4 word-pointers, all you alloc'ed!) so when word_count=4, you must realloc before writing to position[4] in the destination. Commented Feb 3, 2016 at 17:21

1 Answer 1

2

You have an error in the free loop:

i = 0;
for (; i<word_count; i++) {
    free(str_array[word_count]);
}

The array index should be i, not word_count.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.