从未使用过 strlen 时 strlen 的分段错误?
Segmentation fault with strlen when not ever using strlen?
我有一些代码获取一个文件,将每一行读入一个新的字符串数组(并向每个字符添加 128),然后将每个数组分配给一个指针数组,然后打印每个数组。当尝试 运行 代码时,我收到一条错误消息,指出由于以下原因导致的分段错误:
strlen () at ../sysdeps/x86_64/strlen.S:106
106 ../sysdeps/x86_64/strlen.S: No such file or directory.
但我实际上从未在我的代码中调用过 strlen?
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define ROW 10
#define COL 40
#define ARGS 2
#define FLIP_VALUE 128
char** read_file (char* argv[], char **array_pointers);
char* new_array (void);
void print_strings (char** array_pointers);
int main(int argc, char* argv[])
{
char **array_pointers = NULL;
if (argc == ARGS)
{
array_pointers = read_file(&argv[1], array_pointers);
print_strings(array_pointers);
}
return 0;
}
char** read_file (char* argv[], char **array_pointers)
{
FILE* file_name;
int i = 0, j = 0;
char c;
char *temp_array;
array_pointers = malloc(sizeof(char*) * ROW);
file_name = fopen(argv[0], "r");
assert(file_name);
if (file_name) /* if file is not null */
{
while (c != EOF) /* while not equal to end of file */
{
for (j = 0; j < ROW; j++) /* for each row */
{
temp_array = new_array(); /* generate a new array for each new string (row) */
for (i = 0; i < COL; i++) /* for each char in a row */
{
c = fgetc(file_name);
temp_array[i] = c + FLIP_VALUE;
}
array_pointers[j] = temp_array; /*assign array pointers to point at each new temp_array */
}
}
}
return array_pointers;
}
char* new_array (void)
{
char* temp;
temp = malloc(sizeof(char) * COL);
assert(temp);
return temp;
}
void print_strings (char** array_pointers)
{
int i = 0;
for (i = 0; i < COL; i++)
{
printf("%s\n",array_pointers[i]);
}
}
完整的堆栈跟踪如下:
#1 0x00007ffff7a84e3c in _IO_puts (str=0x0) at ioputs.c:36
result = -1
len = <optimised out>
#2 0x0000000000400806 in print_strings (array_pointers=0x602010)
at array_of_string_arrays.c:65
i = 10
#3 0x00000000004006a1 in main (argc=2, argv=0x7fffffffdff8)
at array_of_string_arrays.c:19
array_pointers = 0x602010
之后
temp = malloc(sizeof(char) * COL);
你应该
memset(temp,0,sizeof(char) * COL);
因为 strlen
以阅读 0
结束。
在 print_strings
中,您使用 printf("%s", str);
打印字符串。这要求字符串以空值终止。如果您正在读取普通文本文件,则您写入的字符串不会以 null 结尾。您需要将终止空字节添加到您读取的字符串中 - 否则您不能使用 printf
.
您遇到崩溃的原因是您的 printf
似乎在打印之前先检查字符串的长度(使用 strlen
)。 strlen
递增 char 指针,直到它读取一个空字节。由于字符串中没有任何内容,strlen
读取缓冲区并最终读取内存中某处的空字节,或者如果不允许读取该内存则崩溃。
这里其实有几个bug:
在 read_file
中,c
最初与 EOF
比较时未定义。你甚至需要这个外循环吗?
你应该在 returns 后立即检查 fgetc
的结果,看看它是否是 EOF
。
您正在为每一行的每个字符分配一个新的 temp_array
,而不是为每一行分配一次。这需要向上移动到包含循环中。
在 print_strings
中,您正在遍历行,因此您应该将循环索引与 ROW
进行比较,而不是 COL
.
打印一行时,您在 printf
中使用了 %s
。你不能那样做,因为不能保证一行中的字符以 null 结尾。您可以通过分配一个额外的字符并在其中存储 '[=21=]'
来强制它们,或者您可以在格式说明符中包含一个长度字段以限制长度(您可以使用 *
将其传递为一个论点)。
我怀疑最后一个错误是导致分段错误的错误。
我有一些代码获取一个文件,将每一行读入一个新的字符串数组(并向每个字符添加 128),然后将每个数组分配给一个指针数组,然后打印每个数组。当尝试 运行 代码时,我收到一条错误消息,指出由于以下原因导致的分段错误:
strlen () at ../sysdeps/x86_64/strlen.S:106
106 ../sysdeps/x86_64/strlen.S: No such file or directory.
但我实际上从未在我的代码中调用过 strlen?
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#define ROW 10
#define COL 40
#define ARGS 2
#define FLIP_VALUE 128
char** read_file (char* argv[], char **array_pointers);
char* new_array (void);
void print_strings (char** array_pointers);
int main(int argc, char* argv[])
{
char **array_pointers = NULL;
if (argc == ARGS)
{
array_pointers = read_file(&argv[1], array_pointers);
print_strings(array_pointers);
}
return 0;
}
char** read_file (char* argv[], char **array_pointers)
{
FILE* file_name;
int i = 0, j = 0;
char c;
char *temp_array;
array_pointers = malloc(sizeof(char*) * ROW);
file_name = fopen(argv[0], "r");
assert(file_name);
if (file_name) /* if file is not null */
{
while (c != EOF) /* while not equal to end of file */
{
for (j = 0; j < ROW; j++) /* for each row */
{
temp_array = new_array(); /* generate a new array for each new string (row) */
for (i = 0; i < COL; i++) /* for each char in a row */
{
c = fgetc(file_name);
temp_array[i] = c + FLIP_VALUE;
}
array_pointers[j] = temp_array; /*assign array pointers to point at each new temp_array */
}
}
}
return array_pointers;
}
char* new_array (void)
{
char* temp;
temp = malloc(sizeof(char) * COL);
assert(temp);
return temp;
}
void print_strings (char** array_pointers)
{
int i = 0;
for (i = 0; i < COL; i++)
{
printf("%s\n",array_pointers[i]);
}
}
完整的堆栈跟踪如下:
#1 0x00007ffff7a84e3c in _IO_puts (str=0x0) at ioputs.c:36
result = -1
len = <optimised out>
#2 0x0000000000400806 in print_strings (array_pointers=0x602010)
at array_of_string_arrays.c:65
i = 10
#3 0x00000000004006a1 in main (argc=2, argv=0x7fffffffdff8)
at array_of_string_arrays.c:19
array_pointers = 0x602010
temp = malloc(sizeof(char) * COL);
你应该
memset(temp,0,sizeof(char) * COL);
因为 strlen
以阅读 0
结束。
在 print_strings
中,您使用 printf("%s", str);
打印字符串。这要求字符串以空值终止。如果您正在读取普通文本文件,则您写入的字符串不会以 null 结尾。您需要将终止空字节添加到您读取的字符串中 - 否则您不能使用 printf
.
您遇到崩溃的原因是您的 printf
似乎在打印之前先检查字符串的长度(使用 strlen
)。 strlen
递增 char 指针,直到它读取一个空字节。由于字符串中没有任何内容,strlen
读取缓冲区并最终读取内存中某处的空字节,或者如果不允许读取该内存则崩溃。
这里其实有几个bug:
在
read_file
中,c
最初与EOF
比较时未定义。你甚至需要这个外循环吗?你应该在 returns 后立即检查
fgetc
的结果,看看它是否是EOF
。您正在为每一行的每个字符分配一个新的
temp_array
,而不是为每一行分配一次。这需要向上移动到包含循环中。在
print_strings
中,您正在遍历行,因此您应该将循环索引与ROW
进行比较,而不是COL
.打印一行时,您在
printf
中使用了%s
。你不能那样做,因为不能保证一行中的字符以 null 结尾。您可以通过分配一个额外的字符并在其中存储'[=21=]'
来强制它们,或者您可以在格式说明符中包含一个长度字段以限制长度(您可以使用*
将其传递为一个论点)。
我怀疑最后一个错误是导致分段错误的错误。