Reputation: 2679
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
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
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
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