C 如何从流中读取数据

By char *gets(char *s)

gets()函数用于从stdin读取一行内容到s所指向的buffer里面。但Linux Man page告诉我们:Never use this function。因为它没有溢出检查,可能读取的长度超过了s所指向的buffer的大小,但函数的实现任然会往buffer里面填充数据,这会导致数据被填充到了buffer以外的地方。这是非常危险的。

Linux man page是这么描述这个函数的:it is extremely dangerous to use. It has been used to break computer security, use fgets() instead.

By char *fgets(char *s, int size, FILE *stream)

fgets()函数用于从一个stream中读取一行内容,但最多读取size-1个字符,并将读取的内容填充到s所指向的buffer中。为什么最多读取size-1个字符,因为最后一个字符需要用\0填充。

fets()的问题在于,不能事先知道用户输入了多少个字符。如果输入的内容超过size,则需要读取多次。

By ssize_t getline(char **lineptr, size_t *n, FILE *stream)

getline()函数用于从stream中读取一行内容,存储到*lineptr指向的buffer中。如果*lineptr是NULL或者通过*n指向的buffer size不够,会调用realloc()来重新分配,新的指向buffer的指针,会通过*lineptr返回,同时通过*n返回这一行内容的size。

所以说,getline()可以不用考虑从stream中读取到的内容的长短,函数内部会自动帮我们处理。但是处理的方式可能会涉及到realloc()等耗时的内存重新分配操作。

By obstack

正如obstack.h文件中关于obstack的描述:提供obstack的一个目的,是为了解决symbol tables中增长的char strings的问题

  1. 如果每个符号都重新读取到不通的buffer,则可能涉及到很多的realloc(),对性能影响很大。
  2. 如果重复的使用同一个buffer,当读取更大的符号的时候,才会realloc,则要通过将保存该symbol的buffer,重新copy到一个新的地方才能持久化。这样的话,会浪费很多时间在copy操作本身上。对于读取很多的符号的程序来说(比如gdb),体验会非常差。

实际上,从实现上来看,obstack就是使用了malloc/free来管理一大片内存(称为trunk),如果满了,就再申请一片更大的内存,然后把原来内存的数据拷贝到新的更大的内存里面。

其本质相当于一个帮我们造好了的轮子,轮子本身除了有性能有优化外,还有很多便捷的地方可以定制化处理。比如:

  • 申请和释放trunk的函数可以定制化(通过obstack_specify_allocationobstack_chunkfunobstack_freefun等宏),默认为xmalloc和free;
  • obstack内存储的数据可以指定alignment(通过obstack_specify_allocation等宏)
  • 考虑了字符串末尾是\0的特性,提供了obstack_copy0obstack_1grow等宏。
    总而言之,obstack的解决方案,比较优雅。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值