英文:
Segmentation fault when using fgets with array of strings
问题
需要将文件的一行添加到字符串数组中,但当它执行fgets函数时,出现了分段错误。
```c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *file = fopen("test.txt", "r");
char **array = malloc((sizeof(char) * 100) * 3);
fgets(*(array), 100, file);
printf("%s\n", *array);
free(array);
return 0;
}
在这段代码中,我试图将文件的第一行("My name is bob" 是第一行)添加到数组的第零个元素中。但每当它执行fgets语句时,都会出现分段错误。
<details>
<summary>英文:</summary>
I need to add a line of a file to a array of strings but am getting a segmentation fault when it hits the fgets function.
```c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *file = fopen("test.txt", "r");
char **array = malloc((sizeof(char) * 100) * 3);
fgets(*(array), 100, file);
printf("%s\n", *array);
free(array);
return 0;
}
In this code I am trying to add the first line of the file ("My name is bob" is the first line) and set it to the zeroth element of the array. I am getting a segmentation whenever it hits the fgets statement.
答案1
得分: 0
-
检查
fopen()
的返回值。 -
检查
malloc()
的返回值。 -
char **array = malloc((sizeof(char) * 100) * 3);
分配了300字节,你说它们是char *
,然后尝试在其中写入char
。解引用未初始化的数据是未定义行为。 -
使用
fclose(file)
关闭你的文件句柄是一个好习惯。 -
使用符号常量而不是魔术值。
如果你想动态执行,你可以使用一个指向字符串数组的指针:
#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 100
#define LINES 3
int main(void) {
FILE *file = fopen("test.txt", "r");
if(!file) {
perror("test.txt");
return 1;
}
char (*array)[LINES][LINE_LEN] = malloc(sizeof *array);
if(!array) {
perror("malloc");
fclose(file);
return 1;
}
fgets((*array)[0], sizeof *(*array)[0], file);
printf("%s\n", (*array)[0]);
fclose(file);
return 0;
}
或者一个字符串数组:
#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 100
#define LINES 3
int main(void) {
FILE *file = fopen("test.txt", "r");
if(!file) {
perror("test.txt");
return 1;
}
char (*array)[LINE_LEN] = malloc(sizeof *array * LINES);
if(!array) {
perror("malloc");
fclose(file);
return 1;
}
fgets(array[0], sizeof array[0], file);
printf("%s\n", array[0]);
fclose(file);
return 0;
}
使用一个栈分配的变量会更容易:
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LEN 100
int main(void) {
FILE *file = fopen("test.txt", "r");
if(!file) {
perror("test.txt");
return 1;
}
char array[ARRAY_LEN];
fgets(array, sizeof array, file);
printf("%s\n", array);
fclose(file);
return 0;
}
英文:
-
Check the return value from
fopen()
. -
Check the return value from
malloc()
. -
char **array = malloc((sizeof(char) * 100) * 3);
allocates 300 bytes which you say arechar *
then try to writechar
in it. Dereferencing uninitialized data is undefined behavior. -
Close your file handle with
fclose(file)
is a good practice. -
Use symbolic constants instead of magic values.
If you want to do it dynamically you could use a pointer to array of strings:
#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 100
#define LINES 3
int main(void) {
FILE *file = fopen("test.txt", "r");
if(!file) {
perror("test.txt");
return 1;
}
char (*array)[LINES][LINE_LEN] = malloc(sizeof *array);
if(!array) {
perror("malloc");
fclose(file);
return 1;
}
fgets(*array[0], sizeof *array[0], file);
printf("%s\n", *array[0]);
fclose(file);
return 0;
}
or an array of string:
#include <stdio.h>
#include <stdlib.h>
#define LINE_LEN 100
#define LINES 3
int main(void) {
FILE *file = fopen("test.txt", "r");
if(!file) {
perror("test.txt");
return 1;
}
char (*array)[LINE_LEN] = malloc(sizeof *array * LINES);
if(!array) {
perror("malloc");
fclose(file);
return 1;
}
fgets(array[0], sizeof array[0], file);
printf("%s\n", array[0]);
fclose(file);
return 0;
}
It would be easier to use a stack allocated variable:
#include <stdio.h>
#include <stdlib.h>
#define ARRAY_LEN 100
int main(void) {
FILE *file = fopen("test.txt", "r");
if(!file) {
perror("test.txt");
return 1;
}
char array[ARRAY_LEN];
fgets(array, sizeof array, file);
printf("%s\n", array);
fclose(file);
return 0;
}
答案2
得分: 0
在 fgets
语句执行时,每当发生分段错误时。
在以下代码之后:
char **array = malloc((sizeof(char) * 100) * 3);
array
指向未初始化的分配内存。
使用以下代码:
fgets(*(array), 100, file);
*array
是不好的,因为array
指向的内存是未初始化的。代码传递了一个指针,具有不确定的值,导致未定义的行为(UB)。
为了创建一个包含3个字符串的数组(使用大小为100的字符数组)并进行一次分配:
#define ARRAY_N 3
#define STRING_SZ 100
char (*array_alt)[STRING_SZ] = malloc(sizeof *array_alt * ARRAY_N);
if (array_alt) {
for (size_t i = 0; i < ARRAY_N; i++) {
if (fgets(array_alt[i], sizeof array_alt[i], file) == NULL) {
array_alt[i][0] = '#define ARRAY_N 3
#define STRING_SZ 100
char (*array_alt)[STRING_SZ] = malloc(sizeof *array_alt * ARRAY_N);
if (array_alt) {
for (size_t i = 0; i < ARRAY_N; i++) {
if (fgets(array_alt[i], sizeof array_alt[i], file) == NULL) {
array_alt[i][0] = '\0';
}
printf("<%s>\n", array_alt[i]);
}
free(array_alt);
}
';
}
printf("<%s>\n", array_alt[i]);
}
free(array_alt);
}
使用 char (*array_alt)[STRING_SZ]
,array
是指向大小为100的字符数组的指针。
这里 array_alt[i]
引用了一个大小为100的字符数组。将其传递给 fgets()
时,它会转换为该类型(char *
)和其第一个元素的地址(&array_alt[i][0]
),这正是 fgets()
预期的。
英文:
> I am getting a segmentation whenever it hits the fgets statement.
After
char **array = malloc((sizeof(char) * 100) * 3);
array
points to to the uninitialized allocated memory.
With:
fgets(*(array), 100, file);
*array
is bad as the memory array
points to is initialized. Code is passing a pointer, with an indeterminant value resulting in undefined behavior (UB).
To form an array (size 3) of strings (using a size 100 char array) with 1 allocation:
#define ARRAY_N 3
#define STRING_SZ 100
char (*array_alt)[STRING_SZ] = malloc(sizeof *array_alt * ARRAY_N);
if (array_alt) {
for (size_t i = 0; i < ARRAY_N; i++) {
if (fgets(array_alt[i], sizeof array_alt[i], file) == NULL) {
array_alt[i][0] = '#define ARRAY_N 3
#define STRING_SZ 100
char (*array_alt)[STRING_SZ] = malloc(sizeof *array_alt * ARRAY_N);
if (array_alt) {
for (size_t i = 0; i < ARRAY_N; i++) {
if (fgets(array_alt[i], sizeof array_alt[i], file) == NULL) {
array_alt[i][0] = '\0';
}
printf("<%s>\n", array_alt[i]);
}
free(array_alt);
}
';
}
printf("<%s>\n", array_alt[i]);
}
free(array_alt);
}
With char (*array_alt)[STRING_SZ]
, array
is a pointer to array 100 of char
.
Here array_alt[i]
refences an array of char
, size 100. Giving that to fgets()
, it is converted to the type (a char *
) and address of its first element (&array_alt[i][0])
, just what fgets()
expects.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论