Getting a "Segmentation Fault" when running on Linux


M

Maxx

I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option "-a" is specified on the
command line it will append the output at the end of the file. Now
this program is getting compiled error free but when i attempt to run
it i get a segmentation fault.

../exrcs401<ename.c.inc tfile
Segmentation fault.

exrcs401 is the name of the program
ename.c.inc is the input file
tfile is the output file.

here is the program:::


#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif

int
main(int argc, char *argv[])
{
int openFlags, outputFd;
mode_t filePerms;
ssize_t numRead, numWritten;
size_t len = 0;
char buf[BUF_SIZE], *tempBuf;

if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s input file or {-a:append}...\n",
argv[0]);

filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;



if (strcmp(argv[2], "-a") == 0)
openFlags = O_RDWR | O_APPEND;

else
openFlags = O_RDWR | O_CREAT | O_TRUNC;


outputFd = open(argv[1], openFlags, filePerms);
if (outputFd = -1)
errExit("opening file %s", argv[1]);

while ((numRead = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
len += numRead;
if (!tempBuf)

tempBuf = malloc(len);
if (tempBuf == NULL) {
errExit("cannot allocate");
memcpy(tempBuf, buf, numRead);

} else {
tempBuf = realloc(tempBuf, len);
memcpy(tempBuf, buf, numRead);
}

if (( write(STDOUT_FILENO, buf, numRead )) != numRead &&
( write(outputFd, tempBuf, numRead) != numRead ))
fatal("couldn't write whole buffer");

if (numRead == -1)
errExit("read");

if (close(outputFd) == -1)
errExit("close output");

exit(EXIT_SUCCESS);

}

Please help i cannot figure out the source of the problem.
 
Ad

Advertisements

B

Ben Bacarisse

Maxx said:
I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option "-a" is specified on the
command line it will append the output at the end of the file. Now
this program is getting compiled error free

Then you need more warning to be turned on. Maybe you only posted a
part of the program, but it uses functions that have no declaration
(or definition for that matter).

here is the program:::

#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif

int
main(int argc, char *argv[])
{
int openFlags, outputFd;
mode_t filePerms;
ssize_t numRead, numWritten;
size_t len = 0;
char buf[BUF_SIZE], *tempBuf;

if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s input file or {-a:append}...\n",
argv[0]);

filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;

if (strcmp(argv[2], "-a") == 0)
openFlags = O_RDWR | O_APPEND;

else
openFlags = O_RDWR | O_CREAT | O_TRUNC;

outputFd = open(argv[1], openFlags, filePerms);
if (outputFd = -1)

You mean == I think.
errExit("opening file %s", argv[1]);

while ((numRead = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)

Big point: why are you giving yourself the hassle of using low-level IO
functions? It's way simpler to use C's standard IO library (fopen,
fread etc). If you really need to use read, you should consult
comp.unix.programmer to get all the details right.
len += numRead;
if (!tempBuf)

This is confusing indentation. Maybe you forgot to put this in {}s?

There is a lot else to say (you have some very odd logic below here) but
let's stick to the big stuff first.
tempBuf = malloc(len);
if (tempBuf == NULL) {
errExit("cannot allocate");
memcpy(tempBuf, buf, numRead);

} else {
tempBuf = realloc(tempBuf, len);
memcpy(tempBuf, buf, numRead);
}

if (( write(STDOUT_FILENO, buf, numRead )) != numRead &&
( write(outputFd, tempBuf, numRead) != numRead ))
fatal("couldn't write whole buffer");

if (numRead == -1)
errExit("read");

if (close(outputFd) == -1)
errExit("close output");

exit(EXIT_SUCCESS);
}
<snip>
 
N

Nick Keighley

I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option  "-a" is specified on the
command line it will append the output at the end of the file.  Now
this program is getting compiled error free but when i attempt to run
it i get a segmentation fault.

Please help i cannot figure out the source of the problem.

might help if you gave us a clue as to where it crashed.
Either stick some printf()s in or use a debugger.
 
P

Philip Lantz

Maxx said:
... when i attempt to run
it i get a segmentation fault.

./exrcs401<ename.c.inc tfile
Segmentation fault.

exrcs401 is the name of the program
ename.c.inc is the input file
tfile is the output file.


if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s input file or {-a:append}...\n",
argv[0]);

if (strcmp(argv[2], "-a") == 0)

argv[2] is null.
 
B

Barry Schwarz

I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option "-a" is specified on the
command line it will append the output at the end of the file. Now
this program is getting compiled error free but when i attempt to run
it i get a segmentation fault.

./exrcs401<ename.c.inc tfile
Segmentation fault.

exrcs401 is the name of the program
ename.c.inc is the input file
tfile is the output file.

here is the program:::


#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif

int
main(int argc, char *argv[])
{
int openFlags, outputFd;
mode_t filePerms;
ssize_t numRead, numWritten;
size_t len = 0;
char buf[BUF_SIZE], *tempBuf;

if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s input file or {-a:append}...\n",
argv[0]);

filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;



if (strcmp(argv[2], "-a") == 0)
openFlags = O_RDWR | O_APPEND;

else
openFlags = O_RDWR | O_CREAT | O_TRUNC;


outputFd = open(argv[1], openFlags, filePerms);
if (outputFd = -1)
errExit("opening file %s", argv[1]);

Where is this function declared?
while ((numRead = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
len += numRead;
if (!tempBuf)

Where is tempBuf provided a value. It is not initialized in the
definition. Its value is indeterminate and you have no idea how this
if evaluates. If it is not set to NULL by default in your compiler,
this if evaluates to false and ...
tempBuf = malloc(len);
if (tempBuf == NULL) {
errExit("cannot allocate");

Does errExit actually return?
memcpy(tempBuf, buf, numRead);

I think you have your braces mixed up. This call to memcpy is
executed only when tempBuf is NULL and you cannot copy into the area
pointed to by NULL. Dereferencing a NULL pointer is a frequent cause
of seg faults.
} else {
tempBuf = realloc(tempBuf, len);

.... you invoke undefined behavior by passing realloc a value that is
neither NULL nor the result of a previous call to {m|c|re}alloc.
Passing such a value to free or {c|re}alloc is also a frequent cause
of seg faults.
memcpy(tempBuf, buf, numRead);
}

if (( write(STDOUT_FILENO, buf, numRead )) != numRead &&
( write(outputFd, tempBuf, numRead) != numRead ))
fatal("couldn't write whole buffer");

if (numRead == -1)
errExit("read");

if (close(outputFd) == -1)
errExit("close output");

exit(EXIT_SUCCESS);

}

Please help i cannot figure out the source of the problem.

Have you tried using a debugger?
 
J

Joe Pfeiffer

Maxx said:
I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option "-a" is specified on the
command line it will append the output at the end of the file. Now
this program is getting compiled error free but when i attempt to run
it i get a segmentation fault.

./exrcs401<ename.c.inc tfile
Segmentation fault.

The first thing you need in tracking it down is the location of the seg
fault. Put in a bunch of printfs, e.g.
exrcs401 is the name of the program
ename.c.inc is the input file
tfile is the output file.

here is the program:::


#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include said:
#include <string.h>

#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif

int
main(int argc, char *argv[])
{
int openFlags, outputFd;
mode_t filePerms;
ssize_t numRead, numWritten;
size_t len = 0;
char buf[BUF_SIZE], *tempBuf;

fprintf(stderr, "checkpoint 1\n");
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s input file or {-a:append}...\n",
argv[0]);

filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
S_IROTH | S_IWOTH;



if (strcmp(argv[2], "-a") == 0)
openFlags = O_RDWR | O_APPEND;

else
openFlags = O_RDWR | O_CREAT | O_TRUNC;


outputFd = open(argv[1], openFlags, filePerms);
if (outputFd = -1)
errExit("opening file %s", argv[1]);

fprintf(stderr, "checkpoint 2\n");
while ((numRead = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
len += numRead;
if (!tempBuf)

Please help i cannot figure out the source of the problem.

And, of course, once you know where the crash is occurring you can start
putting in printf's that tell the value of key variables.

Another (and in the long term better) alternative would be to run it in
a debugger like gdb and simply have it tell you where it crashed.
 
Ad

Advertisements

M

Maxx

Maxx said:
I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option  "-a" is specified on the
command line it will append the output at the end of the file.  Now
this program is getting compiled error free

Then you need more warning to be turned on.  Maybe you only posted a
part of the program, but it uses functions that have no declaration
(or definition for that matter).

<snip>








here is the program:::
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
int
main(int argc, char *argv[])
{
    int openFlags, outputFd;
    mode_t filePerms;
    ssize_t numRead, numWritten;
    size_t len = 0;
    char buf[BUF_SIZE], *tempBuf;
    if (argc < 2 || strcmp(argv[1], "--help") == 0)
        usageErr("%s input file or {-a:append}...\n",
                  argv[0]);
    filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
                S_IROTH | S_IWOTH;
    if (strcmp(argv[2], "-a") == 0)
        openFlags = O_RDWR | O_APPEND;
    else
        openFlags = O_RDWR | O_CREAT | O_TRUNC;
    outputFd = open(argv[1], openFlags, filePerms);
    if (outputFd = -1)

You mean == I think.
        errExit("opening file %s", argv[1]);
    while ((numRead = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)

Big point: why are you giving yourself the hassle of using low-level IO
functions?  It's way simpler to use C's standard IO library (fopen,
fread etc).  If you really need to use read, you should consult
comp.unix.programmer to get all the details right.
        len += numRead;
        if (!tempBuf)

This is confusing indentation.  Maybe you forgot to put this in {}s?

There is a lot else to say (you have some very odd logic below here) but
let's stick to the big stuff first.








            tempBuf = malloc(len);
            if (tempBuf == NULL) {
                errExit("cannot allocate");
                memcpy(tempBuf, buf, numRead);
            } else {
                tempBuf = realloc(tempBuf, len);
                memcpy(tempBuf, buf, numRead);
            }
        if (( write(STDOUT_FILENO, buf, numRead )) != numRead&&
            ( write(outputFd, tempBuf, numRead) != numRead ))
                fatal("couldn't write whole buffer");
    if (numRead == -1)
        errExit("read");
    if (close(outputFd) == -1)
        errExit("close output");
    exit(EXIT_SUCCESS);
}

<snip>

I was learning system programming on linux so i was using the system
calls in this program.

This is confusing indentation. Maybe you forgot to put this in {}s?

There is a lot else to say (you have some very odd logic below here) but
let's stick to the big stuff first.

Here i intended tempbuf to store the dynamically allocated memory
which if not already allocated (hence the check "if (!tempbuf)") then
will be allocated using malloc() else if tempbuf already points to a
memory location then it will be resized to the new size stored in len
using realloc().
Yeah i know by logics are a lot fuzzy cause i was just starting out
this system programming thing and still got a lots to learn.

Thanks
Maxx
 
M

Maxx

might help if you gave us a clue as to where it crashed.
Either stick some printf()s in or use a debugger.

Thats the thing i tried using printf() almost everywhere in the
program even right in the part after all the declarations are but the
program still gives Segmentation fault without printing any other
message whatsoever..
 
M

Maxx

I'm writing this program which works like the linux command tee which
copies the standard input to standard output and to the file provided
in the command line argument. By default this program will truncate
any existing file to zero or if the option  "-a" is specified on the
command line it will append the output at the end of the file.  Now
this program is getting compiled error free but when i attempt to run
it i get a segmentation fault.
./exrcs401<ename.c.inc tfile
Segmentation fault.
exrcs401 is the name of the program
ename.c.inc is the input file
tfile is the output file.
here is the program:::
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#ifndef BUF_SIZE
#define BUF_SIZE 1024
#endif
int
main(int argc, char *argv[])
{
   int openFlags, outputFd;
   mode_t filePerms;
   ssize_t numRead, numWritten;
   size_t len = 0;
   char buf[BUF_SIZE], *tempBuf;
   if (argc < 2 || strcmp(argv[1], "--help") == 0)
       usageErr("%s input file or {-a:append}...\n",
                 argv[0]);
   filePerms = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
               S_IROTH | S_IWOTH;
   if (strcmp(argv[2], "-a") == 0)
       openFlags = O_RDWR | O_APPEND;
   else
       openFlags = O_RDWR | O_CREAT | O_TRUNC;
   outputFd = open(argv[1], openFlags, filePerms);
   if (outputFd = -1)
       errExit("opening file %s", argv[1]);

Where is this function declared?
This custom error functions are all declared in "tlpi_hdr.h". and they
work fine i've tested them in other programs

Where is tempBuf provided a value.  It is not initialized in the
definition.  Its value is indeterminate and you have no idea how this
if evaluates.  If it is not set to NULL by default in your compiler,
this if evaluates to false and ...
Yeah i get it leaving tempbuf with an indeterminate value must have
been the source of the error.
I wasn't aware of this at all.
Does errExit actually return?


I think you have your braces mixed up.  This call to memcpy is
executed only when tempBuf is NULL and you cannot copy into the area
pointed to by NULL.  Dereferencing a NULL pointer is a frequent cause
of seg faults.




... you invoke undefined behavior by passing realloc a value that is
neither NULL nor the result of a previous call to {m|c|re}alloc.
Passing such a value to free or {c|re}alloc is also a frequent cause
of seg faults.














Have you tried using a debugger?

No i haven't but i did used the printf() technique pointed out by the
others in this board. Anyways i think that tempbuf thing was the
source of the problem, i will fix it right away. Thanks a lot.

Thanks
Maxx
 
B

Ben Bacarisse

Maxx said:
This is confusing indentation. Maybe you forgot to put this in {}s?

There is a lot else to say (you have some very odd logic below here) but
let's stick to the big stuff first.

Here i intended tempbuf to store the dynamically allocated memory
which if not already allocated (hence the check "if (!tempbuf)") then
will be allocated using malloc() else if tempbuf already points to a
memory location then it will be resized to the new size stored in len
using realloc().[/QUOTE]

That was obvious. What was no obvious is why you had the "if" outside
the while loop. Only "len += numRead;" is in the while loop. That did
not look like what you wanted.

Also, tempBuf was not initialised so the test is undefined -- anything
could happen.

<snip>
 
J

James Kuyper

� � � �errExit("opening file %s", argv[1]);

Where is this function declared?
This custom error functions are all declared in "tlpi_hdr.h". and they
work fine i've tested them in other programs

Does removing the custom error function calls remove the segmentation fault?

If so, then the problem involves those function calls, even if the
problem isn't actually in those functions, and we therefore need to know
how they work before we can help you.

If not, they are a complication that can be removed without removing the
ability to demonstrate the problem. As a general rule, you should make
the program which demonstrates a problem as small as possible. This
generally makes it easier to determine what the problem actually is. In
fact, I've frequently solved a problem as a side effect of simplifying
the code demonstrating the problem.
 
Ad

Advertisements

M

Maxx

Maxx said:
... when i attempt to run
it i get a segmentation fault.

./exrcs401<ename.c.inc tfile
Segmentation fault.

exrcs401 is the name of the program
ename.c.inc is the input file
tfile is the output file.


if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s input file or {-a:append}...\n",
argv[0]);

if (strcmp(argv[2], "-a") == 0)

argv[2] is null.

Yeah i fixed this error in the new one that ive written..
 
P

Philip Lantz

Gordon said:
Either use fprintf(stderr, .... ) or litter your program with fflush(stdout)
calls. A segmentation fault is not guaranteed to fflush(stdout) for
you, and it usually doesn't.

Another possible reason that you don't see any output before the
segmentation fault is that when you add a printf, the printf itself is
causing a fault, by trying to print a string where the pointer argument
to printf is null or uninitialized. (Many printf implementations will
detect a null pointer and print "(null)", but it's not required, since
the behavior is undefined.)
 
M

Maxx

On Thu, 29 Dec 2011 07:28:16 -0800 (PST), Maxx ...
errExit("opening file %s", argv[1]);
Where is this function declared?
This custom error functions are all declared in "tlpi_hdr.h". and they
work fine i've tested them in other programs

Does removing the custom error function calls remove the segmentation fault?

If so, then the problem involves those function calls, even if the
problem isn't actually in those functions, and we therefore need to know
how they work before we can help you.

If not, they are a complication that can be removed without removing the
ability to demonstrate the problem. As a general rule, you should make
the program which demonstrates a problem as small as possible. This
generally makes it easier to determine what the problem actually is. In
fact, I've frequently solved a problem as a side effect of simplifying
the code demonstrating the problem.

Those custom error function actually works fine, i've used them in
numerous other programs. Yeah i know this all made this program
complicated but i wasn't sure which part to ommit to make this more
simplified.
 
Ad

Advertisements

Ad

Advertisements

J

James Kuyper

On Thu, 29 Dec 2011 07:28:16 -0800 (PST), Maxx ...
errExit("opening file %s", argv[1]);
Where is this function declared?
This custom error functions are all declared in "tlpi_hdr.h". and they
work fine i've tested them in other programs

Does removing the custom error function calls remove the segmentation fault?

If so, then the problem involves those function calls, even if the
problem isn't actually in those functions, and we therefore need to know
how they work before we can help you.

If not, they are a complication that can be removed without removing the
ability to demonstrate the problem. As a general rule, you should make
the program which demonstrates a problem as small as possible. This
generally makes it easier to determine what the problem actually is. In
fact, I've frequently solved a problem as a side effect of simplifying
the code demonstrating the problem.

Those custom error function actually works fine, i've used them in
numerous other programs. ...

You're missing the point: even if those functions are perfectly written,
removing them could cause the symptoms of your actual problem to change
or even disappear. If so (which, so far, you've neither confirmed nor
denied), that would mean that the real problem involves an interaction
between those functions and the rest of the program. For instance,
removing them might change the relative location in memory of two other
objects, and the symptoms you're seeing might occur only when they are
exactly 13533 bytes apart.
... Yeah i know this all made this program
complicated but i wasn't sure which part to ommit to make this more
simplified.

The answer to that is simple. Before taking your program to someone else
for help, remove everything that doesn't make the symptoms of your
problem disappear - but make sure, after removing each item, that the
symptoms still occur. NOTE: do the removals on a copy of your program,
not on the original. The simpler the program is, the easier it will be
for the person who's helping you to identify what the real problem is.
 

Top