0

I encountered a segmentation fault when I tried to print the value of a variable, len, which is a local variable that has been initialized at the start of the function.

Except for the misuse of fprintf, what really bothers me is that the line right after the second fprintf would cause segmentation fault also.

Specifically, it is the line where I assign '\n' to tokens[len][0]: "tokens[len][0] = '\n';"

Here is what GDB shows me:

250         tokens[len][0] = '\n';
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x08049f49 in make_command_stream (get_next_byte=0x80495eb <get_next_byte>, 
get_next_byte_argument=0x8059b58) at read-command.c:250
250         tokens[len][0] = '\n';


command_stream_t
make_command_stream (int (*get_next_byte) (void *),
                 void *get_next_byte_argument)
{
int c = (*get_next_byte)(get_next_byte_argument);
char** tokens = (char**) checked_malloc(CMD_SIZE * sizeof(char*));
tokens[0] = (char*) checked_malloc(WORD_SIZE);
int len = 0;
int word_length = 0;
int len_mult = 1;
int word_count = 1;

bool prev = true;
bool comment = false;
bool prevOp = false;
char prevOpe = '\0';

//reading input into the buffer
while (c != EOF)
{
    if (c == '#') comment = true;

    if (!comment)
    {
        bool cur = (c != ' ') && (c != '\t');
        bool curOp = isOperator(c);
        if (cur)
        {
            if (!(curOp || isValidWordChar(c)))
                error_report1(210);
            if (!prev)
            {
                tokens[len][word_length] = '\0';
                len++;
                if (len > CMD_SIZE  * len_mult)
                {
                    len_mult++;
                    tokens = checked_realloc(tokens, sizeof(char*) * len_mult * CMD_SIZE);
                }
                tokens[len] = (char*) checked_malloc(WORD_SIZE);
                tokens[len][0] = c;
                word_length = 1;
                word_count = 1;
            }
            else {
                if (prevOpe != '\0' && (curOp != prevOp || (curOp && c != prevOpe)))
                {
                    tokens[len][word_length] = '\0';
                    len++;
                    if (len > CMD_SIZE * len_mult)
                    {
                        len_mult++;
                        tokens = checked_realloc(tokens, sizeof(char*) * len_mult * CMD_SIZE);
                    }
                    tokens[len] = (char*) checked_malloc(WORD_SIZE);
                    word_length = 0;
                    word_count = 1;
                }
                tokens[len][word_length] = c;
                word_length++;
                if (word_length > WORD_SIZE  * word_count)
                {
                    word_count++;
                    tokens[len] = checked_realloc(tokens[len], word_count * word_length);
                }
            }
        }
        prev = cur;
        prevOp = curOp;
        prevOpe = c;
    }
    else if (c == '\n')
        comment = false;
    c = (*get_next_byte)(get_next_byte_argument);
}
tokens[len][word_length] = '\0';
len++;
fprintf("the value of len is %d\n", len);
if (tokens[len-1][0] != '\n')
{
    if (len > len_mult * CMD_SIZE)
        tokens = checked_realloc(tokens, (len_mult + 1) * CMD_SIZE);
fprintf("the value of len is %d\n", len);
    tokens[len][0] = '\n';
    tokens[len][1] = '\0';
    len++;
}

For two fprintf I used in this function, complaints from the compiler are:

read-command.c: In function ‘make_command_stream’:
read-command.c:244: warning: passing argument 1 of ‘fprintf’ from incompatible pointer type
/usr/include/stdio.h:333: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘            char *’
read-command.c:244: warning: passing argument 2 of ‘fprintf’ makes pointer from integer without a cast
/usr/include/stdio.h:333: note: expected ‘const char * __restrict__’ but argument is of type ‘int’
read-command.c:244: warning: format not a string literal and no format arguments
read-command.c:249: warning: passing argument 1 of ‘fprintf’ from incompatible pointer type
/usr/include/stdio.h:333: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘char *’
read-command.c:249: warning: passing argument 2 of ‘fprintf’ makes pointer from integer without a cast
/usr/include/stdio.h:333: note: expected ‘const char * __restrict__’ but argument is of type ‘int’
read-command.c:249: warning: format not a string literal and no format arguments

This appears to me a bizarre warning, as there is no pointer type used in fprintf. I wonder what is the possible source of this warning.

So when I run till the line with fprintf, here is what gdb shows me:

244     fprintf("the value of len is %d\n", len);
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x001a1389 in vfprintf () from /lib/tls/i686/cmov/libc.so.6

Another related file is main.c (I guess), as I am using GNU readline function to write something into a input stream, and write that input stream into a temporary file. This writing might cause some problem in memory.

In main.c:

#include <errno.h>
#include <error.h>
#include <getopt.h>
#include <stdio.h>

#include <readline/readline.h>
#include <readline/history.h> 
#include "command.h"

static char const *program_name;
static char const *script_name;

static void
usage (void)
{
  error (1, 0, "usage: %s [-pti] SCRIPT-FILE", program_name);
}

static int
get_next_byte (void *stream)
{
  return getc (stream);
}

int
main (int argc, char **argv)
{
  int command_number = 1;
  bool print_tree = false;
  bool time_travel = false;
  bool interactive_mode = false;
  program_name = argv[0];
  int c;

  while (((c = getopt (argc, argv, "pti"))!=-1)) 
    switch (c)
  {
  case 'p': print_tree = true; break;
  case 't': time_travel = true; break;
  case 'i': interactive_mode = true; break;
  default: usage (); break;
  case -1: goto options_exhausted;
  }
 options_exhausted:;

  // Limitation of having only one file is removed
  /* if (optind != argc - 1)
     usage ();*/

  command_t last_command = NULL;
  command_t command;
  if (time_travel || print_tree)
    {
      //only one file allowed
      if (optind != argc - 1)
    usage ();
      script_name = argv[optind];
      FILE *script_stream = fopen (script_name, "r");
      if (! script_stream)
    error (1, errno, "%s: cannot open", script_name);
      command_stream_t command_stream =
    make_command_stream (get_next_byte, script_stream);

      if (time_travel)
    last_command = execute_timetravel(command_stream);
      else {
    while ((command = read_command_stream (command_stream)))
      {
    if (print_tree)
      {
    printf ("# %d\n", command_number++);
    print_command (command);
      }
    else
      {
    last_command = command;
    execute_command (command);
      }
  }

  }
}

  if (interactive_mode)
    {
  printf("You are now in the interactive mode. Type whatever command you want to run:). \n");
  char* temp;

  char* input_stream = readline("You can enter command right now.\n");

  //write input stream into a temporary file
  FILE* script_stream = fopen (temp, "w+");
  int c = 0;
  while (input_stream[c] != '\0')
  {
putc(input_stream[c], script_stream);
c++;
  }

  command_stream_t command_stream = make_command_stream (get_next_byte, script_stream);
        if (time_travel)
last_command = execute_timetravel(command_stream);
  else {
while ((command = read_command_stream (command_stream)))
  {
    if (print_tree)
      {
    printf ("# %d\n", command_number++);
    print_command (command);
      }
    else
      {
    last_command = command;
    execute_command (command);
      }
  }

  }
}

    /*   printf("This is what you entered: ");
  int c = 0;
  while (script_scream[c] != '\0')
{
  printf("%c", script_scream[c]);
  c++;
}
  printf("\n");

  }*/

    return print_tree || !last_command ? 0 : command_status (last_command);


}
3
  • 1
    remove the f in fprintf and make it printf Commented Jul 30, 2014 at 7:23
  • Did you really look up the manual page for fprintf before asking here? Commented Jul 30, 2014 at 7:43
  • I assumed that they accept same parameters... I remember there are some situations in which printf() won't print out instantaneously. That's why I am using fprintf. Commented Jul 30, 2014 at 17:56

3 Answers 3

3

The title of your question is confusing: you are not using printf(); you are using fprintf().

The problem is that you are failing to pass a FILE* pointer as the first argument to fprintf():

int fprintf(FILE *restrict stream, const char *restrict format, ...);
            ^^^^^^^^^^^^^^^^^^^^^

This is what the compiler is trying to warn you about, and what's causing the segfault.

If you just want to print to standard output, use printf() instead of fprintf().

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I think I made a mistake by assuming fprintf the same as printf, which is not the case obviously. However, now I got a different segmentation fault.
1

fprintf("the value of len is %d\n", len); syntax is wrong.

This is the prototype of fprintf: int fprintf ( FILE * stream, const char * format, ... );

It should be fprintf(yourfilepointer, "the value of len is %d\n", len);

If you are printing to stdout, or stderr, then use them like this:

fprintf(stderr, "the value of len is %d\n", len);

Comments

1

You shouldn't use fprintf, it is used for printing to a FILE stream. Just use printf to remove error and print the value of len to standard output.

printf("the value of len is %d\n", len);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.