C getline()函数出现分段错误?
我正在Linux上的终端上学习C,我用文本做了一个小游戏,所以一切都在运行,特别是我的大循环,如果玩家想重新启动游戏,我只是在开始时添加了一个dump,Enter your pseudo 当我进入它时它不起作用,它说我C getline()函数出现分段错误?,c,linux,getline,C,Linux,Getline,我正在Linux上的终端上学习C,我用文本做了一个小游戏,所以一切都在运行,特别是我的大循环,如果玩家想重新启动游戏,我只是在开始时添加了一个dump,Enter your pseudo 当我进入它时它不起作用,它说我 Segmentation Error , core dumped 以下是所有代码,最重要的是第一行,因为所有其他代码都运行良好: #include <stdio.h> #include <stdlib.h> #include <time.h>
Segmentation Error , core dumped
以下是所有代码,最重要的是第一行,因为所有其他代码都运行良好:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
int main (void) {
// déclaration des variables
bool essais8 = false ;
bool essais10 = false ;
bool essais12 = false;
bool essais14 = false;
bool condition = true;
bool condition_diff = false;
bool condition_recommencer = false;
bool condition_bonus1 = true;
bool condition_bonus2 = true;
bool condition_bonus3 = true;
char* buffer;
char* recommencer;
char* pseudo ;
size_t bufsize = 32;
size_t characters;
int difficulte;
int sheitan = 0;
int sheitan2 = 0;
int a;
int bonus1;
int bonus2;
int bonus3;
int ecart;
int essais;
int nb_bonus2;
srand(time(NULL));
// on récupère le pseudo du joueur
printf("Salut ! Quel est ton nom ? ");
characters = getline(&buffer,&bufsize,stdin);
pseudo = buffer;
// after this I have the segmentation errror
while (condition == true) { // Boucle de recommencement du Jeu
// here is the big game that was functioning perfectly before I add the pseudo option on top.
}
printf("Fin du programme \n");
return(0);
}
您忘记初始化缓冲区了。在缓冲任何输入之前,最好使用\n或else调用结束格式控制字符串
未初始化的指针包含垃圾。使用它是必要的。是的
所以我的建议是编码
size_t bufsiz = 64;
char *buffer = malloc(bufsiz);
if (!buffer) { perror("malloc buffer"); exit(EXIT_FAILURE); };
后来
printf("Salut ! Quel est ton nom ?\n");
characters = getline(&buffer,&bufsize,stdin);
下次编译时启用所有警告和调试信息,所以如果使用,请编译代码gcc-Wall-Wextra-g。你会得到一些警告
当然,阅读和阅读
在Linux上,在您的特定情况下,您可能会对使用而不是
不要忘记阅读您正在使用的每个函数的文档,例如,如果它是标准的C函数。'buffer'变量指向某个垃圾内存地址。您需要首先使用“malloc”函数分配必要的内存,或者将“buffer”设置为静态数组,而不是指针。可以两种不同的方式使用: 读入调用者提供的缓冲区。 读取时分配内存。 使用1。初始化传递给指向有效内存的指针,并传递有效内存的大小
#define INITIAL_SIZE (42)
int main(void)
{
char * buffer = malloc(INITIAL_SIZE * sizeof *buffer);
size_t bufsize = INITIAL_SIZE;
ssize_t characters = getline(&buffer, &bufsize, stdin);
if (-1 == characters)
{
/* handle error. */
}
else
{
/* use buffer */
}
free(buffer); /* Free buffer. */
}
使用2。初始化传递给NULL的指针,并将0作为大小传递
注意:getline返回ssize\u t而不是size\u t。是一个函数,它将行读入动态分配的缓冲区,允许任何长度的行仅受可用内存量的限制。它返回读取的字符数,如果没有更多输入或发生错误,则返回-1
下面是一个示例使用模式:
char *line = NULL;
size_t size = 0;
ssize_t len;
while (1) {
len = getline(&line, &size, stdin);
if (len < 1)
break;
/* Do something with the input line */
}
您希望将指针清除为NULL,并将大小清除为零的原因是,这样您就不会意外地尝试访问已释放的内存,但您可以调用getline&line,&size,handle来读取更多行,因为调用只会识别出它没有缓冲区,并将分配一个新的缓冲区
如果小心的话,可以按任何方式操纵动态数据。例如:
while (1) {
char *line = NULL;
size_t size = 0;
ssize_t len;
len = getline(&line, &size, stdin);
if (len < 1) {
free(line);
break;
}
/* Do something with the contents of the line */
free(line);
}
如果我们将上述内容保存为example.c,并使用gcc-Wall-O2 example.c-o example进行编译,然后运行程序,将文本文件名作为参数提供给它,例如./example.c,它将输出如下内容
example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
example.c: Line 4: '#include <string.h>' (19 of 20 characters)
example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
example.c: Line 8: '' (0 of 1 characters)
example.c: Line 9: 'int main(int argc, char *argv[])' (32 of 33 characters)
在linenum++行之后,查看文本文件的第七行发生了什么。它们被跳过,即使释放了缓冲区,也不会发生什么不好的事情,因为continue会启动while循环体的下一个迭代,因为下一个getline只会动态地分配一个新行
如果您决定保留一部分行的副本,只需计算需要为字符串nul\0的结尾添加一个的长度,始终为C中的重复大小分配多个字符,即char==1;所以malloc等人计算数据中要分配给memcpy的字符数,并添加终止nul。比如说,
char *sdup(const char *const source, const size_t length)
{
char *s;
s = malloc(length + 1);
if (!s) {
/* Either return NULL, or: */
fprintf(stderr, "sdup(): Not enough memory for %zu chars.\n", length + 1);
exit(EXIT_FAILURE);
}
if (length > 0)
memcpy(s, source, length);
s[length] = '\0';
return s;
}
如果您希望完整的字符串一直到字符串nul的末尾,可以使用POSIX.1-2008。没有一个指针被初始化为指向有效的memory@UnholySheep ... 或空或0。谢谢,它成功了!但是,如果我的缓冲区没有显示任何内存,为什么它在我所有的程序中都能正常工作,而且从来没有出现过这个错误?请按照我在回答中给出的所有链接进行操作。非常感谢!祝你有美好的一天!您需要首先分配[…]内存,但不一定。请参阅我关于使用getline.Outsh的替代方案的答案@名义动物修复!Thx!:}
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <locale.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
int main(int argc, char *argv[])
{
unsigned long linenum;
char *line = NULL, *in, *out, *end;
size_t size = 0, n;
ssize_t len;
FILE *src;
int arg;
if (!setlocale(LC_ALL, ""))
fprintf(stderr, "Warning: Your C library does not support your current locale.\n");
if (argc < 2) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s FILENAME [ FILENAME ... ]\n", argv[0]);
fprintf(stderr, "\n");
exit(EXIT_FAILURE);
}
for (arg = 1; arg < argc; arg++) {
src = fopen(argv[arg], "r");
if (!src) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
free(line);
exit(EXIT_FAILURE);
}
linenum = 0;
while (1) {
len = getline(&line, &size, src);
if (len < 1)
break;
linenum++;
/* First character in the line read: */
in = line;
out = line;
/* Pointer to the end-of-string character on the line: */
end = line + len;
/* Skip all leading whitespace characters. */
while (in < end && isspace((unsigned char)(*in)))
in++;
/* Character copy loop. */
while (in < end)
if (isspace((unsigned char)(*in))) {
/* Replace consecutive whitespace characters with spaces. */
*(out++) = ' ';
do {
in++;
} while (in < end && isspace((unsigned char)(*in)));
} else {
/* Copy all other characters as-is. */
*(out++) = *(in++);
}
/* There may be a single space before out. Backtrack it, if so. */
if (out > line && out[-1] == ' ')
out--;
/* Mark the end of the string at out. */
*out = '\0';
/* Calculate the new length, just for output purposes. */
n = (size_t)(out - line);
/* Print the line. */
printf("%s: Line %lu: '%s' (%zu of %zd characters)\n",
argv[arg], linenum, line, n, len);
}
if (!feof(src) || ferror(src)) {
fprintf(stderr, "%s: Read error.\n", argv[arg]);
fclose(src);
free(line);
exit(EXIT_FAILURE);
}
if (fclose(src)) {
fprintf(stderr, "%s: Error closing file: %s.\n",
argv[arg], strerror(errno));
free(line);
exit(EXIT_FAILURE);
}
}
free(line);
line = NULL;
size = 0;
return EXIT_SUCCESS;
}
example.c: Line 1: '#define _POSIX_C_SOURCE 200809L' (31 of 33 characters)
example.c: Line 2: '#include <stdlib.h>' (19 of 20 characters)
example.c: Line 3: '#include <locale.h>' (19 of 20 characters)
example.c: Line 4: '#include <string.h>' (19 of 20 characters)
example.c: Line 5: '#include <stdio.h>' (18 of 19 characters)
example.c: Line 6: '#include <ctype.h>' (18 of 19 characters)
example.c: Line 7: '#include <errno.h>' (18 of 19 characters)
example.c: Line 8: '' (0 of 1 characters)
example.c: Line 9: 'int main(int argc, char *argv[])' (32 of 33 characters)
if (linenum == 7) {
/* We skip line 7, and even destroy it! Muahhahah! */
free(line);
line = NULL;
size = 0;
continue;
}
char *sdup(const char *const source, const size_t length)
{
char *s;
s = malloc(length + 1);
if (!s) {
/* Either return NULL, or: */
fprintf(stderr, "sdup(): Not enough memory for %zu chars.\n", length + 1);
exit(EXIT_FAILURE);
}
if (length > 0)
memcpy(s, source, length);
s[length] = '\0';
return s;
}