user720694
user720694

Reputation: 2075

Segmentation fault always occurs after 3 inputs

I have the following code to accept any number of lines from the user and print out the ones whose length is > 80 characters :-

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

int MAXLINE =  10;
int INCREMENT = 10;
int NUM = 1;

char* longest = NULL;
char* line = NULL;
char** row = NULL;

void _memcleanup(){

    int i =0;

    free(line);
    free(longest);

    for(i=0;i<NUM;i++){
      free(row[i]);
    }

    free(row);
}

void print_lines(int len){

  int i;

  for(i=0;i<len;i++){

    if(strlen(row[i])>80){
    printf("%s\n",row[i]);
    }

  }


}

void copy(char** longest, char** line){

  int i=0;

  char* temp = realloc(*longest,(MAXLINE)*sizeof(char));

      if(temp == NULL){
        printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);
      }

      *longest = temp;

      while(((*longest)[i] = (*line)[i]) != '\0'){
    ++i;
      }

      longest[i] = '\0';

}

void store(char** s, int pos){

  int i=0;



  char* temp = realloc(row[pos],(MAXLINE)*sizeof(char));

      if(temp == NULL){
        printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);
      }

      row[pos] = temp;

      while((row[pos][i] = (*s)[i]) != '\0'){
    ++i;
      }

      row[pos][i] = '\0';

}

int _getline(char** s, int pos){

  int i,c;

  for(i=0; ((c=getchar())!=EOF && c!='\n'); i++){

    if(i == MAXLINE - 2){

      char* temp = realloc(*s,(MAXLINE + INCREMENT)*sizeof(char));

      if(temp == NULL){
        printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);
      }

      *s= temp;

      MAXLINE += INCREMENT;
    }
    (*s)[i] = c;
  }

  if(c == '\n'){
    (*s)[i++] = c;
  }

  (*s)[i]= '\0';

  store(s, pos);

  return i;
} 

int main(){

  int max=0, len, i=0;

  line = malloc(MAXLINE*sizeof(char));
  longest = malloc(MAXLINE*sizeof(char));

  //array of character pointers
  row = malloc(NUM*sizeof(char*));

  //allocate memory for each row in the array
  for(i = 0; i < NUM; i++){
    row[i]= malloc(MAXLINE*(sizeof(char)));
  }

  i=0;

  //for(i=0; len = _getline(&line)) > 0; i++){
  while((len = _getline(&line, i)) > 0){
    printf("%d %d", len, MAXLINE);

    /* if(len > max){ */
    /*   max = len; */
    /*   copy(&longest, &line); */
    /* } */

    i++;
  }
    /* if(max>0){ */
    /*   printf("%s",longest); */
    /* } */

  print_lines(i);

    _memcleanup();
  return 0;

}

The idea that i am following is to reallocate the 2D array when the number of lines exceed NUM. Now to test it out, i set NUM as 1. However, even after doing so, the program gladly accepts upto 3 inputs and segfaults on the 4th input i.e. pos=3 in the program's context.

Why does it accept 3 inputs (ideally it should give a segfault pos=1 itself since i have given size as only 1 and i am not allocating more space for the 2D array)

Working code is as follows:

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

int MAXLINE =  10;
int INCREMENT = 10;
int NUM = 1;

char* longest = NULL;
char* line = NULL;
char** row = NULL;

void _memcleanup(){

    int i =0;

    free(line);
    free(longest);

    for(i=0;i<NUM;i++){
      free(row[i]);
    }

    free(row);
}

void print_lines(int len){

  int i;

  for(i=0;i<len;i++){

    if(strlen(row[i])>80){
    printf("%s\n",row[i]);
    }

  }


}

void copy(char** longest, char** line){

  int i=0;

  char* temp = realloc(*longest,(MAXLINE)*sizeof(char));

      if(temp == NULL){
        printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);
      }

      *longest = temp;

      while(((*longest)[i] = (*line)[i]) != '\0'){
    ++i;
      }

      longest[i] = '\0';

}

void store(char** s, int pos){

  int i=0;

  if(pos == NUM){
    char** temprow = realloc(row, (NUM + INCREMENT)*sizeof(char*));

    if(temprow == NULL){
            printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);      
    }

    row = temprow;
    //allocate space for extra elements
    for(i=NUM;i<NUM+INCREMENT;i++){
      row[i] = malloc(MAXLINE*sizeof(char));
    }

    NUM = NUM + INCREMENT; 

  }

  char* temp = realloc(row[pos],(MAXLINE)*sizeof(char));

      if(temp == NULL){
        printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);
      }

      row[pos] = temp;

      while((row[pos][i] = (*s)[i]) != '\0'){
    ++i;
      }

      row[pos][i] = '\0';

}

int _getline(char** s, int pos){

  int i,c;

  for(i=0; ((c=getchar())!=EOF && c!='\n'); i++){

    if(i == MAXLINE - 2){

      char* temp = realloc(*s,(MAXLINE + INCREMENT)*sizeof(char));

      if(temp == NULL){
        printf("%s","Unable to allocate memory");
        _memcleanup();
        exit(1);
      }

      *s= temp;

      MAXLINE += INCREMENT;
    }
    (*s)[i] = c;
  }

  if(c == '\n'){
    (*s)[i++] = c;
  }

  (*s)[i]= '\0';

  store(s, pos);

  return i;
} 

int main(){

  int max=0, len, i=0;

  line = malloc(MAXLINE*sizeof(char));
  longest = malloc(MAXLINE*sizeof(char));

  //array of character pointers
  row = malloc(NUM*sizeof(char*));

  //allocate memory for each row in the array
  for(i = 0; i < NUM; i++){
    row[i]= malloc(MAXLINE*(sizeof(char)));
  }

  i=0;

  //for(i=0; len = _getline(&line)) > 0; i++){
  while((len = _getline(&line, i)) > 0){
    printf("%d %d", len, MAXLINE);

    /* if(len > max){ */
    /*   max = len; */
    /*   copy(&longest, &line); */
    /* } */

    i++;
  }
    /* if(max>0){ */
    /*   printf("%s",longest); */
    /* } */

  print_lines(i);

    _memcleanup();
  return 0;

}

Upvotes: 0

Views: 79

Answers (2)

Ingo Leonhardt
Ingo Leonhardt

Reputation: 9904

You are asking:

Why does it accept 3 inputs (ideally it should give a segfault pos=1 itself since i have given size as only 1 and i am not allocating more space for the 2D array)

and you are right, that if you allocate memory for one row only, it invokes Undefined Behaviour if you attempt to access rows[1]. But that behaviour is just -- undefined -- what means that you can't rely on the program crashing. Anything might happen, including that the program seems to work flawlessly

Upvotes: 1

rohit
rohit

Reputation: 228

In the main(), instead of using

while((len = _getline(&line, i)) > 0){  

use

while(i< NUM)
{
  len = _getline(&line, i);

For me with this code change, it worked correctly.

Upvotes: 0

Related Questions