分段为数组元素赋值时出错

时间:2014-07-30 07:07:18

标签: c linux segmentation-fault printf

当我尝试打印变量len的值时遇到了分段错误,len是一个在函数开始时初始化的局部变量。

除了误用fprintf之外,真正困扰我的是第二个fprintf之后的线路也会导致分段错误。

具体来说,就是我将'\ n'赋给tokens [len] [0]的行:“tokens [len] [0] ='\ n';”

以下是GDB向我展示的内容:

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++;
}

对于我在此函数中使用的两个fprintf,来自编译器的抱怨是:

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

这对我来说是一个奇怪的警告,因为fprintf中没有使用指针类型。我想知道这个警告的可能来源是什么。

所以当我用fprintf运行到这一行时,这就是gdb向我展示的内容:

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

另一个相关文件是main.c(我猜),因为我使用GNU readline函数将某些内容写入输入流,并将该输入流写入临时文件。这种写作可能会在内存中引起一些问题。

在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 个答案:

答案 0 :(得分:3)

您的问题标题令人困惑:您没有使用printf();您正在使用fprintf()

问题是你没有将FILE*指针作为第一个参数传递给fprintf()

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

这是编译器试图警告你的内容,以及导致段错误的原因。

如果您只想打印到标准输出,请使用printf()代替fprintf()

答案 1 :(得分:1)

fprintf("the value of len is %d\n", len);语法错误。

这是fprintf的原型: int fprintf ( FILE * stream, const char * format, ... );

应为fprintf(yourfilepointer, "the value of len is %d\n", len);

如果要打印到stdout或stderr,请按照以下方式使用它们:

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

答案 2 :(得分:1)

您不应该使用fprintf,它用于打印到FILE流。只需使用printf删除错误并将len的值打印到标准输出。

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