c - 为数组元素赋值时出现段错误

标签 c linux segmentation-fault printf

当我尝试打印变量 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);


}

最佳答案

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

问题是您未能将FILE* 指针作为第一个参数传递给fprintf()。 :

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

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

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

关于c - 为数组元素赋值时出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25030667/

相关文章:

linux - 删除一个巨大的文本文件中只包含数字和标点符号的行

linux - 在 vim 中使用 & 符号时如何消除空格

C: fgetc 给出段错误

c - 当我更改在 C 中分配双指针的方式时,会导致段错误

第二次 scanf() 后 C 程序崩溃/停止工作

我可以在双重解锁 pthread_mutex_t 时强制崩溃吗?

linux - 如何在 SMP linux 中获取给定 cpu 的当前任务?

c - SQLite:错误调用 sqlite3_prepare_v2 -> SIGSEGV

c - C 中是否可以不使用 sprintf 将 int 转换为字符串?

c - 指针导致C程序崩溃