Search code examples
arrayscsegmentation-fault

Why does my C program with any input results in segmentation fault?


I've spent hours of racking my brain on why doesn't this work

#include <stdio.h>
#define MAXLINE 1000
#define TRUE 1
#define FALSE 0

int getLine(char s[], int lim);
void copy(char to[], char from[]);
void add(char to[], char from[], int max);

int main(){
  int len;
  int max;
  char line[MAXLINE];
  char longest[MAXLINE];

  max = 0;
  len = 0;
  while(( len = getLine(line, MAXLINE)) > 0){
    
    if(max == len){
      add(longest, line, max);
    }

    if (len > max){
      max = len;
      copy(longest, line);
    }
  }
  
  if (max > 0){ 
    printf("%s", longest);
  }
  return 0;
}
int getLine(char s[], int lim){
  int c, i;
  
  for (int state = FALSE, i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n';){
    if(c == '\t' || c == ' ' && state == TRUE)
      continue;

    if (c == '\t' || c == ' '){
      s[i] = c;
      ++i;
      state = TRUE;
    } else {
      s[i] = c;
      state = FALSE;
      ++i;
    }
  }
  if (c == '\n'){
    s[i] = c;
    ++i;
  }
  s[i] = '\0';

  return i;
}

void copy(char to[], char from[]){
  int i = 0;

  while((to[i] = from[i]) != '\0'){
    ++i;
  }
}

void add(char to[], char from[], int max){
  if (max != 0){
    int control = max * 2;
    to[max] = from[0];
    ++max;
    for(int i = 1; max <= control; ++max, ++i ){
      to[max] = from[i];
    };
  };
}

Am I missing something ? I ran valgrind with this results

==22786== Memcheck, a memory error detector

==22786== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==22786== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info

==22786== Command: ./maxLine

==22786==

as

==22786== Use of uninitialised value of size 8

==22786== at 0x10933A: getLine

==22786== by 0x109230: main

==22786==

==22786== Use of uninitialised value of size 8

==22786== at 0x10934D: getLine

==22786== by 0x109230: main

==22786==

==22786== Conditional jump or move depends on uninitialised value(s)

==22786== at 0x10923E: main

==22786==

==22786== Conditional jump or move depends on uninitialised value(s)

==22786== at 0x1091C9: main

==22786==

==22786== Conditional jump or move depends on uninitialised value(s)

==22786== at 0x1091F6: main

==22786==

==22786== Conditional jump or move depends on uninitialised value(s)

==22786== at 0x109396: copy

==22786== by 0x10921C: main

==22786==

In gdb :

[Thread debugging using libthread_db enabled]

Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

as

Program received signal SIGSEGV, Segmentation fault.

0x000055555555533a in getLine (s=0x7fffffffd7e0 "as\377\367\377\177", lim=1000) at maxLine.c:53

53 s[i] = c;

(gdb) backtrace

#0 0x000055555555533a in getLine (s=0x7fffffffd7e0 "as\377\367\377\177", lim=1000) at maxLine.c:53

#1 0x0000555555555231 in main () at maxLine.c:18

I don't know where to start


Solution

  • In getline, for (int state = FALSE, i = 0; … declares an i that exists only during execution of the for statement. The value of the i declared earlier in the routine is not affected. That earlier i is uninitialized. That earlier i is used later in the routine without having been initialized.

    Most compilers would diagnose this. Compile with warnings enabled and elevated to errors. With Clang, start with -Wmost -Werror. With GCC, start with -Wall -Werror. With MSVC, start with /W3 /WX.

    There may be other errors in the program.