1

I am currently working on a project in C where my goal is to create a an array of strings, and fill them all with words from a file (Currently I just explicitly insert a string).

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

int main(){
        
    int numLetters = 4;
    /* The Amount of words in each file, File 1, 2, 3 */
    int totalWordQuantity = 19829; 
    /*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
    char word[numLetters + 1]; 
    /*how many times we've changed the character*/
    int letterSpot = 0; 
    /*the character that goes through the file*/
    char c; 
        
    char* wordDocuments[3] = {"WordDocuments/Two_Letter_Connections.txt", "WordDocuments/Three_Letter_Connections.txt", "WordDocuments/Four_Letter_Connections.txt"};
    /*Four Letter Word Document*/
    FILE *flwd = fopen(wordDocuments[numLetters - 2], "r"); 
    if(flwd == NULL){
        printf("Cold Dog.");
    } 
    /* P is a step ahead of c, because otherwise the words get super messed up. */
    char p = fgetc(flwd); 
    c = p; 
 
    /*This stores all of the words*/
    char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*) * (numLetters + 1));
    int wordCount = 0; 
    int i;
    for(i = 0; i < totalWordQuantity; i++){
        wordStorage[i] = malloc(sizeof(char) * (numLetters + 1)); 
    }

    /* First, take the character */
    while((c = p) != EOF){
        p = fgetc(flwd);

        if((c == ' ' && p != '\n') || c == '\n'){
            strcpy(wordStorage[wordCount], "pies");  
            wordCount++;
        }
        c = p;
    }
    
    for(i = 0; i < totalWordQuantity; i++){
        free(wordStorage[i]); 
    }
    
    free(wordStorage);
    
    fclose(flwd); 
    return 0; 
}

This code does not receive any compilation issues and runs perfectly; however, when I run it, valgrind gives me this error:

==29== Memcheck, a memory error detector
==29== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==29== Command: ./flwp
==29==
==29== error calling PR_SET_PTRACER, vgdb might block
==29== Invalid write of size 4
==29==    at 0x109419: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==29==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==29==
==29==
==29== Process terminating with default action of signal 11 (SIGSEGV)
==29==  Access not within mapped region at address 0x0
==29==    at 0x109419: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==29==  If you believe this happened as a result of a stack
==29==  overflow in your program's main thread (unlikely but
==29==  possible), you can try to increase the size of the
==29==  main thread stack using the --main-stacksize= flag.
==29==  The main thread stack size used in this run was 8388608.
==29==
==29== HEAP SUMMARY:
==29==     in use at exit: 892,777 bytes in 19,831 blocks
==29==   total heap usage: 19,832 allocs, 1 frees, 896,873 bytes allocated
==29==
==29== LEAK SUMMARY:
==29==    definitely lost: 0 bytes in 0 blocks
==29==    indirectly lost: 0 bytes in 0 blocks
==29==      possibly lost: 0 bytes in 0 blocks
==29==    still reachable: 892,777 bytes in 19,831 blocks
==29==         suppressed: 0 bytes in 0 blocks
==29== Reachable blocks (those to which a pointer was found) are not shown.
==29== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==29==
==29== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==29==
==29== 1 errors in context 1 of 1:
==29== Invalid write of size 4
==29==    at 0x109419: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==29==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==29==
==29== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Segmentation fault (core dumped)

Dr. Memory crashes when I try to run it. It works without any memory issues if I replace the while loop and all the lines within it to:

for(int i = 0; i < totalWordQuantity; i++){
    strcpy(wordStorage[wordCount], "word"); 
}

Any help or suggestions to improve the question would be greatly appreciated! Thank you!

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 1
    Accessing illegal memory location might give you the impression everything is running perfect, but still, its undefined behavior. Avoid re-inventing the wheel, a simple search in google and you will find how to read lines from file to array. Try to see what they did otherwise and learn from your possible mistake. – Tony Tannous Jul 23 '20 at 21:42
  • There's no reason to multiply by `numLetters + 1` when allocating the array of pointers. – Barmar Jul 23 '20 at 21:50
  • The return type of `fgetc()` is `int`, not `char`. You need to use an `int` variable so you can compare to `EOF` properly. – Barmar Jul 23 '20 at 22:54
  • I tried to take out multiplication when allocating the array of pointers but that oddly gave me another issue. I also changed the type of p & c to be ints, but it didn't fix the memory leaks. Thank you, for the time you're spending to help me fix this issue. It really does mean a lot. – Jordan Driscoll Jul 23 '20 at 23:19
  • Can you explain this peice: `FILE *flwd = fopen(wordDocuments[numLetters - 2], "r"); ` – Burstful Jul 23 '20 at 23:33
  • @CoreyLakey Yes, that is the line that opens up the document. The wordDocument is an array of string, the strings being file names, and the "r" declares that it's a read only file. There are 3 documents. if numLetters = 2, it will open wordDocuments[0], or the 2 letter file. – Jordan Driscoll Jul 24 '20 at 00:10

1 Answers1

0

The title is a bit misleading. The issue does not seem to be a memory leak, i.e memory that's allocated, but never freed, but an illegal memory access.

Maybe the issue is just because of an incorrect path (since you seem to be using Valgrind from Cygwin), but you are unable to see it because of improper error handling.

if(flwd == NULL){
    printf("Cold Dog.");
} 

Here the program continues execution despite the file not being successfully opened. Since stdout is buffered, on my machine I was unable to see the error and get a SEGFAULT.

if(flwd == NULL){
    fprintf( stderr, "Cold Dog.");
    exit(EXIT_FAILURE);
} 

There are some other issues as well:

char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*) * (numLetters + 1));

You are allocating too much space here. You should allocate totalWorldQuantity times sizeof char pointer (char *).

char** wordStorage = (char**)calloc(totalWordQuantity, sizeof(char*));

But this shouldn't cause any issues other than an excessive allocation.

char p = fgetc(flwd); 

should be

int p = fgetc(flwd); 

Otherwise a non-EOF character might be interpreted as EOF.

Uku Loskit
  • 40,868
  • 9
  • 92
  • 93