Peter3
Peter3

Reputation: 2679

segmentation fault core dumped Issue with C

I know this question has been asked before and I think that I understand that having a segmentation fault means that I have a bad pointer somewhere. Having said that I would really appreciate help trying to figure out where my error is. i have a header file and two source files they are

Header:

#ifndef LINEHOLDER_H_INCLUDED
#define LINEHOLDER_H_INCLUDED



#define DEFAULT 100
#define MAXLEN 256
#define MAXLINES 1024
int readlines(char *lineptr[], int maxlines);
unsigned getline2(char *s, int size);
void printlines(char **lineptr, int size, int numlines);

#endif // LINEHOLDER_H_INCLUDED

The first Source file is :

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



int main(int argc, char *argv[])
{
  char *lineptr[MAXLEN];      /* input lines */
  int linecount = 0;
  int tail_count = 0;

   int i;

for (i = 1 ; i < argc ; ++i)
{
    char *arg = argv[i]; 
    if (strcmp(arg, "-n") == 0);
    {
        char *endptr;
        tail_count = strtol(arg, &endptr, 10);     
        if (*endptr == '\0')
            continue;
        fprintf(stderr, "warning , argument `%d' is not an integer\n", 1 + i);
     }
 }
  if (!tail_count)
    tail_count = 10;

  if ((linecount = readlines(lineptr,MAXLINES)) >= 0)
    printlines(lineptr, linecount,tail_count);

  return 0;
}

The Second Source file is:

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

unsigned getline2(char *s, int size);

int readlines(char *lineptr[], int maxlines)
{ 
  int len, nlines;
  char *p, line[MAXLEN];

  nlines = 0;

  while ((len = getline2(line, MAXLEN)) > 0) {
    p = malloc(len);
    if (nlines >= maxlines || p == NULL) {
      return -1;
    } else {
      // line[len-1] = '\n';
      if ((len > 0) && line[len-1] == '\n') line[len-1] = '\n';
      strcpy(p,line);
      lineptr[nlines++] = p;
    }
  }
  return nlines;
}

void printlines(char **lineptr, int size, int numlines)
{
  /* 72 lines, we start on line 62 */
  int print_start;
  int line;

  print_start = size - numlines;
  for (line=print_start; line < size; line++)
    printf("%s", lineptr[line]);
}

unsigned getline2(char *s, int size)
{
  int i, c;

  for (i=0; i<size-1 && (c=getchar()) != EOF && c != '\n'; ++i)
    *s++ = c;
  if (c == '\n') {
    *s++ = c;
    ++i;
  }
  *s = '\0';

  return i;
}

After building it out with a makefile I will get an executable called tails When I run ./tails test.out I receive the segmentation fault core dumped error. Can anyone help me figure out where I am trying to allocate memory where I am not supposed to?

thanks

I updated the code thanks to the help from you guys but my problem still exists.

Upvotes: 1

Views: 172

Answers (3)

chux
chux

Reputation: 154169

After getline2() reads the last '\n', the next time it is called it may return with a 0 as that '\n' was the last character in the file.

while ((len = getline2(line, MAXLEN)) > 0) {
  p = malloc(len);
  if (... || p == NULL) {

malloc(0) might not return NULL and so code continues to attempt line[-1] = '\n'; which is undefined behavior.

    ...
    line[len-1] = '\n';

Also the last line may not end with a '\n' in which case line[len-1] = '\n'; lops off a valuable `char. Better to defensively code

    // line[len-1] = '\n';
    if ((len > 0) && line[len-1] == '\n') line[len-1] = '\n';

Upvotes: 1

Iharob Al Asimi
Iharob Al Asimi

Reputation: 53016

You are incrementing the pointer twice, because you increment it again in strcmp(*argv++, "-n"), in the second case you might be reading beyond bounds in strtol(*argv, NULL, 10).

while (*++argv) { /* First time you increment the pointer */
    if (strcmp(*argv++,"-n") == 0); /* You do it again */
        /* If *++argv was `NULL' you went after it anyway
         * so this is undefined behavior 
         */
        tail_count = strtol(*argv, NULL, 10);

And this is not necessary

while (*++argv)

you can youse argc for that

int i;

for (i = 1 ; i < argc ; ++i)
 {
    char *arg = argv[i]; 
    if (strcmp(arg, "-n") == 0);
     {
        char *endptr;
        tail_count = strtol(arg, &endptr, 10);     
        if (*endptr == '\0')
            continue;
        fprintf(stderr, "warning , argument `%d' is not an integer\n", 1 + i);
     }
 }

the argc parameter in main() contiains the number of command line arguments passed to the program, counting of course argv[0] which is the name of the program itself.

Also, the signature of the functions recieving lineptr is wrong

void printlines(char **lineptr, int size, int numlines)

should be

void printlines(char *lineptr[MAXLEN], int size, int numlines)

Upvotes: 2

doron
doron

Reputation: 28932

A segmentation fault comes about when your application tries to access memory for which it does not have permission. In such a case, the operating system will generate a SIGSEGV. This will normally terminate your application and do a core dump.

By default, core dumps are turned off or severely limited to prevent one from filling up one's disk space.

They can be easily turned on using: ulimit -c unlimted which will allow the creation of core file with unlimited size. Core file are typically created int the current working directory.

Provided you compiled your application with the -g (debug symbol) flag, you can now find out where the problem was by running:

gdb

To get a callstack , type the bt command into gdb.

Upvotes: 2

Related Questions