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