0

My program decodes an image that is covered by random pixels, to decode the image, I have to multiply each pixel's red color component by 10. The green and blue color components are the same values as the new red component. I've created multiple helper functions, to make the code easier to read in main, but when I try to run my a.out, I keep getting "Segmentation Fault". I can't seem to find my mistakes! Help is appreciated.

void check_argument(int arg_list)
{
   if (arg_list < 2)
   {
      perror("usage: a.out <input file>\n");
   }
}

void print_pixel(int a, FILE *out)
{
   int r, g, b;

   r = a * 10;

   if (r > 255)
   {
      r = 255;
   }

   g = r;
   b = r;

   fprintf(out, "%d\n", r);
   fprintf(out, "%d\n", g);
   fprintf(out, "%d\n", b);
}

void read_header(FILE *in)
{
   char str[20];

   for (int i = 0; i < 3; i++)
   {
      fgets(str, 20, in);
   }
}

FILE*  open_files(FILE *infile, char *input[])
{
   infile = fopen(input[1], "r");

   if (infile == NULL)
   {
      perror("Error: Cannot read file.\n");
   }

   return infile;
}

void decode(int arg_list, char *in[])
{
   FILE *input, *output;

   int check, red, green, blue;

   open_files(input, in);
   output = fopen("hidden.ppm", "w");

   fprintf(output, "P3\n");
   fprintf(output, "%d %d\n", 500, 375);
   fprintf(output, "255\n");

   read_header(input);
   check = fscanf(input, "%d %d %d", &red, &green, &blue);

   while (check != EOF)
   {
      print_pixel(red, output);
      check = fscanf(input, "%d %d %d", &red, &green, &blue);
   }

   fclose(input);
   fclose(output);
}

int main(int argc, char *argv[])
{
   check_argument(argc);
   decode(argc, argv);
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • 2
    Where exactly do you receive the error? – SH- Jun 03 '13 at 23:01
  • After I compile it using: gcc -std=c99 -Wall -pedantic puzzle.c, I get the a.out file. But when I try running the a.out file with the command line argument, it tells me: "Segmentation Fault". –  Jun 03 '13 at 23:04
  • Umm, I don't think I'm allowed to use a debugger for this problem. :( –  Jun 03 '13 at 23:09
  • @Karen Your comment contradicts your question: In your question (title and text), you get þe segfault when compiling, in your comment, you get it when running. Please correct that. – glglgl Jun 03 '13 at 23:09
  • @Karen Why no debugger? – glglgl Jun 03 '13 at 23:09
  • @Karen Are you sure your input file exists? What do you think your program does when there is no such file? And: where does your `FILE* input` point to? – glglgl Jun 03 '13 at 23:10
  • @glglgl: Thanks, yeah, I corrected it. :) And I think my instructor wants us to be able to find the bug in our program without using a debugger (he never mentioned anything about using a debugger) So no debugger for us. :( –  Jun 03 '13 at 23:11
  • 1
    You're not allowed to use a debugger, but you're allowed to ask people on the internet to find the problem? – interjay Jun 03 '13 at 23:13
  • They didn't forbid it as well... – glglgl Jun 03 '13 at 23:14
  • Hmm...when there is no such file, I want to exit out of my program so...would I have to say: if (infile == NULL), printf("Error!\n"), and then return 1 inside the body of that if statement? And the FILE *input in the "decode" function is the input file that I am passing to the open_files function...but I'm not too sure if I did this right. :( –  Jun 03 '13 at 23:15
  • @interjay: I just need someone to point me in the right direction...I'm not sure where my problem is. :( And true, he didn't forbid using a debugger, but he never taught us how to use a debugger so...I'm not too sure if we can use one. :( –  Jun 03 '13 at 23:17
  • @Karen You can add debugging info to the console. A simple `prinf("At Location 1");` can work wonders. You will know exactly where you die. Just place a few. Remember to clean up after. – SH- Jun 03 '13 at 23:28

2 Answers2

0

As this is supposed to be homework, I'll try to show you the some common source of bugs and how to find them.

  1. Variables which are used must (should) be assigned to before that. This counts especially for pointers, e. g. FILE *.

  2. If a function (e. g. fopen()) fails, it normally indicates this by returning a special value which must be checked before continuing.

  3. To check which value a variable has, you can use printf() to show it.

This is for finding principal errors such as segfaults.

But logical errors are hard to find as well: if you read 3 values and store them into variables, it might be more useful to use them all instead of only one of them. (But maybe this one is not yet the goal of this exercise.)


I wrote the lines before this before I learned that it is not the task to search for bugs in a given program, but to write a program by yourself, so I'll get a little more concrete by now.

A FILE * is something returned by fopen(). You can return it or you can write it to a variable or another memory location indirectly pointed to by a pointer "one level deeper".

So you should rewrite your open_files() (BTW: why file*s*? It's currently only one...):

either for returning the value (preferrable):

FILE* open_files(char *input[])
{
   FILE *infile = fopen(input[1], "r");

   if (infile == NULL)
   {
      perror("Error: Cannot read file.\n");
   }

   return infile;
}

and call it with

input = open_files(input);

or with "pass by reference":

void open_files(FILE **infile, char *input[])
{
   *infile = fopen(input[1], "r");

   if (*infile == NULL)
   {
      perror("Error: Cannot read file.\n");
   }

   return *infile;
}

and call it with

open_files(&input, in);

Only doing that you'll have your variable input at the caller's site really written to.

glglgl
  • 89,107
  • 13
  • 149
  • 217
0

After calling open_files(input, in); you will not have the file handle in input.

SpacedMonkey
  • 2,725
  • 1
  • 16
  • 17