c - 障碍,获取和获取线

标签 c linux posix libc

我正在尝试从标准输入中获取一行。据我所知,我们永远不应该使用gets的手册页中所说的gets:

Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.

它建议我们可以改用 fgets()。 fgets() 的问题在于我们事先不知道用户输入的大小,并且 fgets() 从流中读取的字节数正好小于 size 字节,正如 man 所说:

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.

还有另一种使用 POSIX getline() 的方法,它使用 realloc 来更新缓冲区大小,因此我们可以从输入流中读取任意长度的字符串,正如 man 所说:

Alternatively, before calling getline(), *lineptr can contain a pointer to a malloc(3)-allocated buffer *n bytes in size. If the buffer is not large enough to hold the line, getline() resizes it with realloc(3), updating *lineptr and *n as necessary.

最后还有另一种使用 obstack 的方法,如 libc 手册所述:

Aside from this one constraint of order of freeing, obstacks are totally general: an obstack can contain any number of objects of any size. They are implemented with macros, so allocation is usually very fast as long as the objects are usually small. And the only space overhead per object is the padding needed to start each object on a suitable boundary...

所以我们可以对任何大小的任何对象使用 obstack 分配非常快,空间开销很小,这不是什么大问题。我编写这段代码是为了在不知道长度的情况下读取输入字符串。

#include <stdio.h>
#include <stdlib.h>
#include <obstack.h>
#define obstack_chunk_alloc malloc
#define obstack_chunk_free free
int main(){
        unsigned char c;
        struct obstack * mystack;
        mystack = (struct obstack *) malloc(sizeof(struct obstack));
        obstack_init(mystack);
        c = fgetc(stdin);
        while(c!='\r' && c!='\n'){
                obstack_1grow(mystack,c);
                c = fgetc(stdin);
        }
        printf("the size of the stack is: %d\n",obstack_object_size(mystack));
        printf("the input is: %s\n",(char *)obstack_finish(mystack));
        return 0;
}

所以我的问题是: 这样使用 obstack 安全吗? 就像使用 POSIX getline 一样吗? 我在这里错过了什么吗?有什么缺点吗? 为什么我不应该使用它? 提前致谢。

最佳答案

fgetsgets 相比没有缺点。它只是迫使 承认 必须知道缓冲区的大小。 gets 需要您以某种方式神奇地事先知道(可能是恶意的)用户将输入您的程序的输入的长度。这就是 gets 从 C 编程语言中删除的原因。它现在是非标准,而fgets标准 和可移植的。

至于事先知道行的长度,POSIX 表示实用程序必须准备好处理适合 LINE_MAX 缓冲区的行。尺寸。因此你可以这样做:

char line[LINE_MAX];
while (fgets(line, LINE_MAX, fp) != NULL)

任何产生问题的文件都不是标准的文本文件。实际上,如果您不盲目地假设缓冲区中的最后一个字符始终是 '\n'(事实并非如此),那么一切都会很好。


getline 是一个 POSIX 标准函数。 obstack 是不可移植的 GNU libc 扩展。 getline 是为从文件中高效读取行而构建的,obstack 不是,它被构建为通用。使用 obstack,字符串在内存中/在其最终位置不正确连续,直到您调用 obstack_finish

如果在 POSIX 上,请使用 getline,在需要最大可移植性的程序中使用 fgets;为基于 fgets 的非 POSIX 平台寻找 getline 的模拟。

关于c - 障碍,获取和获取线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46764250/

相关文章:

linux - 无法使用 while 修改 bash 脚本 case 语句中的变量

linux - 根文件夹下的大文件

c - 通过函数分配矩阵内存

c - 按特定字符拆分单词适用于字符串,但不适用于 argv[1]

c - 为什么在使用 system() 调用管理程序的 setuid-root C 程序中需要 setuid(0)?

c++ - 指针比较 "<"与数组对象的最后一个元素

c - 尝试通过传递 ip (getnameinfo) 打印名称时出现段错误

php - 如何使用 yum 轻松地将 posix 支持添加到 PHP?

mysql - 如何在 SQL 友好的正则表达式中匹配标签外但不在标签内的 URL

c -/bin/sh依赖哪些POSIX系统接口(interface)?