3

I'm reasonably new to C - I've made a program that reads a text file and through several functions processes the text by using malloc() and realloc() and formats an output. At the moment I only have the following in my main():

1. initializing the structs

  line_arr.max_size = 0;
  line_arr.num_lines = 0;
  line_arr.line = NULL;

  Word_Array word_arr;
  word_arr.max_size_ = 0;
  word_arr.num_words = 0;
  word_arr.word = NULL;

  Word_Array ex_words;
  ex_words.max_size_ = 0;
  ex_words.num_words = 0;
  ex_words.word = NULL; 

Line_Array.line and Word_Array.word are both pointers to structs Line and Word, respectively. Line and Word are structs that hold a char array and an int that keeps track of what line number the line is or the word occurs in.

2. calling the functions that process the input text files

  get_lines(&line_arr, argv[1]);
  get_words(&line_arr, &word_arr);
  sort_keywords(&word_arr);

All of my functions return void.

All the output and formatting occurs within the functions and any space I have malloc'd I have subsequently freed without any error. The program produces the desired output, however if I add any statement to the main() even a print statement, I get a bus10 error or a segmentation fault 11 error.

I have tried gdb but I haven't used it before, and it seems as though gdb hangs and freezes when I try to run the program anyway.

I'm wondering if anyone knows why this is the case? / is there some fundamental logic I'm not understanding about C or malloc()?

Thanks for your expertise!

edit structs:

typedef struct Line Line;
struct Line{
  char line[MAX_LINE_LEN];
};

typedef struct Word{
  char word[MAX_WORD_LEN];
  int line_number;
}Word;

typedef struct Word_Array{
  //will point to the base in memory where the list of words begins.
  Word *word;
  int max_size_;
  int num_words;
}Word_Array;

typedef struct Line_Array{
  //line is a variable that stores an address of a line object.
    Line *line;
    int max_size;
    int num_lines;
}Line_Array;

get_lines():

void get_lines(Line_Array *la, char const *filename){
  Line *line_ptr;
  char *buffer;
  size_t buffer_len;

  FILE *fp = fopen(filename, "r");
  if(fp == NULL){
    printf("Can't read file. \n");
    exit(1);
  }

  while (getline(&buffer, &buffer_len, fp) > 0) {
    buffer[strlen(buffer)-1] = '\0';
    if (la->line == NULL) {
      la->line = (Line *) malloc(sizeof(Line));
      if (la->line == NULL) {
        exit(1);
      }
      la->max_size = 1;
      la->num_lines = 0;
    }

    else if (la->num_lines >= la->max_size) {
      line_ptr = (Line *) realloc(la->line, (2*la->max_size) * sizeof(Line));
      if (line_ptr == NULL) {
        exit(1);
      }

      la->max_size *= 2;
      la->line = line_ptr;

    }

    strncpy(la->line[la->num_lines].line, buffer, MAX_LINE_LEN);
    la->num_lines++;
  }
  fclose(fp);
}

I haven't freed the memory in this method since I make use of it later, but even when other functions aren't being run the same problem exists where if I add something to the main before or after calling get_lines, I receive bus 10 error as my only output. However if i only call get_lines() and other functions the program produces the right output.

Joel Bodenmann
  • 2,152
  • 2
  • 17
  • 44
  • 2
    Need to see the full code, or at least a representative sample, including the struct definitions. – John Bode Mar 21 '20 at 17:13
  • 1
    It sounds like you have a memory error somewhere, but it's impossible to track it down without seeing a more complete example. – Tom Karzes Mar 21 '20 at 17:14
  • Thanks Tom and John! I added structs and the code for one of my functions – Matt Plaudis Mar 21 '20 at 17:19
  • 2
    You have an invalid memory access. Try to run it with `valgrind` and check for invalid reads and/or writes. – Maxime B. Mar 21 '20 at 17:21
  • 2
    You are passing the address of an uninitialised `char *buffer` to function `getline`. Local variables must be explicitly initialised. – Weather Vane Mar 21 '20 at 17:25
  • 1
    I reverted your last edit: you are not supposed to do this, it makes the comments and answers irrelevant. You can accept the answer by clicking on the grey checkmark below its score. If you insist on removing your code, first accept the answer and delete the question. – chqrlie Mar 21 '20 at 18:21
  • Please, don't explain us (well, you did that ok) but then put only snippets of code. Post a full example, ready to be compiled and tested, that is minimum to show the problem you talk about. Read [this page](https://stackoverflow.com/help/minimal-reproducible-example) to get an idea of what is expected from your explanation. If you hide code, probably you are hidding errors, that can be the heart of the problem you are having. – Luis Colorado Mar 26 '20 at 17:14

1 Answers1

3

A least one problem:

Variables need to be initialized before getline() usage. @Weather Vane

  //char *buffer;
  //size_t buffer_len;
  char *buffer = NULL;
  size_t buffer_len = 0;

Notes:

After the while (getline(... , code should free with free(buffer);

strncpy(la->line[la->num_lines].line, buffer, MAX_LINE_LEN); does not insure la->line[la->num_lines].line is a string. Why is strncpy insecure?

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256