Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >C关于为与fread一起使用的字符*分配内存的问题

C关于为与fread一起使用的字符*分配内存的问题
EN

Stack Overflow用户
提问于 2020-04-02 17:00:03
回答 2查看 147关注 0票数 2

所以我有这个密码

代码语言:javascript
运行
AI代码解释
复制
FILE* file = fopen("file.txt", "r");
if(file == NULL)
{
    printf("Failed to open file.\n");
    return NULL;
}

fseek(file, 0L, SEEK_END);
long bufferSize = ftell(file);
fseek(file, 0L, SEEK_SET);

char* buffer = (char*) malloc(bufferSize);
if(buffer == NULL)
{
    printf("Failed to allocate memory for buffer.\n");
    return NULL;
}

fread(buffer, sizeof(char), bufferSize, file);
fclose(file);

当使用printf("%s",缓冲区)打印控制台时,这似乎非常好,但我想知道这是否应该导致缓冲区溢出,或者它是否错误,因为在末尾似乎没有空终止符字符。让我们假设file.txt中正好有4个字符。当计算bufferSize时,它将是一个长的值为4。因此,当我调用malloc(bufferSize)时,我将创建一个大小为4字节的缓冲区,不代表为空终止符字符。在我见过的例子中,人们都使用这样的代码来读取整个文本文件,但这难道不应该用文件中的字符来创建char*而不使用终止符字符吗?我应该使用malloc(bufferSize + 1)分配这个缓冲区并添加一个空终止符吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-04-02 17:44:55

--当用printf("%s",缓冲区)打印到控制台时,这似乎非常好。

看起来工作得很好是undefined behavior的完美表现。

应该使用malloc(bufferSize + 1)并添加一个空终止符字符来分配这个缓冲区吗?

如果希望使用指向可打印字符的连续字节的指针的%s printf格式说明符,则需要以零字节结束这些字节。或者另一种方式,%s printf格式说明符需要一个以零结尾的字节序列。否则,就会发生未定义的行为。

所以:

您的输入文件包含一个零字节,以便printf("%.*s", (int)bufferSize, buffer);停止输出。

  • 您需要自己提供一个零终止字节,以确保%s知道在哪里停止。

  • 或者您可以自己迭代字节,或者(假设bufferSizeINT_MAX低,所以很可能是)只要告诉printf何时停止指定格式说明符的精度,比如:

否则就会发生不明确的行为。

票数 3
EN

Stack Overflow用户

发布于 2020-04-02 17:26:22

根据您分配的缓冲区的大小和您的操作系统提供的分配单元的大小,分配结束时通常会有额外的字节。这意味着,根据以后如何使用内存,精确的缓冲区分配可能会导致失败,或者在分配结束时可能会出现空闲字节,而fread()不会覆盖这些字节。结果是什么呢?您可以使用具有意外大小的文件来测试您的程序,但一旦发布,程序可能会间歇性地失败。

快速修复?始终在缓冲区的末尾分配更多的空间--取决于程序如何解释字节(char、short、int、long、long、struct)。

请注意,如果字符串嵌套在struct中,则分配单元的大小不太可能将您保存,其中struct元素紧贴在一起。但奇数大小的字符串仍有空闲空间,这取决于编译器标志。

请注意,您的特定用法是查找文件的结尾,并将整个文件读入内存。您的操作系统很可能以16、32或64字节块的形式提供内存。这意味着您有1/16、1/32或1/64的机会意外地从您分配的缓冲区的末尾走出来。

建议:(0)总是分配额外的垫子,以缓冲跑到墙上。(1)考虑使用fstat()而不是ftell()?(2)考虑内存映射文件,而不是使用malloc/free和fread。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61003564

复制
相关文章
通过 JavaScrpit 传递 Post 变量
使用 Get 方式方式传递变量会把 URL 搞得很长,而且 IE 会对长度有限制,所以最好的方式还是通过 Post 方式来传递变量。但是通过 Post 来传递变量的时候一定要有个表单,很多时候页面上并没有表单,所以这个时候可以隐藏表单,然后通过 JavaScript 来提交表单。下面是个隐藏表单的例子:
Denis
2023/04/13
7010
类变量与对象变量
# 类变量与对象变量 # 代码 # coding=UTF-8,类变量与对象变量 class Robot: """表示有一个带有名字的机器人。""" # 一个类变量,用来计数机器人的数量 population = 0 # 这是一个类变量,属于Robot类 def __init__(self, name): # name变量属于一个对象(通过self分配),因此它是一个对象变量 """初始化数据""" self.name = name
benym
2022/07/14
9330
批处理变量详谈
他们的值由系统将其根据事先定义的条件自动赋值,也就是这些变量系统已经给他们定义了值, 不需要我们来给他赋值,我们只需要调用而以!
HUC思梦
2020/09/03
8620
测试人员该如何平衡与开发人员之间的冲突?
为什么两者之间会产生冲突? 因为开发与测试在某个程度上来说是两个行为相反的职位。开发代表着创造,而测试代表着摧毁。因为测试的目的就是以各种方式不断地从开发出来的软件中发现大大小小的各种缺陷,所以很多开发人员心里都感觉测试人员是在故意找茬,让自己难堪,证明自己做的东西不好,所以两者的矛盾必然会慢慢地产生。 职位的优越感。很多开发人员都认为测试的比自己低一等,因为开发自己是创造东西,而测试只是拿着自己做的东西在工作。所以很多开发人员对测试人员的脸色都不怎么好。 失败的沟通。在需求的理解或者说是测试发现问题时,测
软件测试君
2021/07/09
1.7K0
python的全局变量与局部变量
自定义函数里面的a要想变成全局变量,可以使用global,同时外面也需要定义一下a;
bye
2020/10/29
6920
静态变量与动态变量
1)静态存储变量通常是在变量定义时就分定存储单元并一直保持不变,直至整个程序结束。静态变量,全局动态变量都是静态存储
全栈程序员站长
2022/09/01
1.5K0
静态变量与动态变量
Lua⭐️全局变量与局部变量的使用、多变量同时赋值
星河造梦坊官方
2024/08/14
1270
如何理解变量?
看起来,它并不是一件需要特别的知识铺垫才能正确理解的东西。但是,也许正因为如此,我们总是并没有很好地厘清这个概念的内涵。它和数学中的变量是一个概念吗?
高一峰
2020/09/22
1.5K0
如何理解变量?
[C语言] 常量与变量
说明:系统会在字符串尾部添加一个字符串作为结束字符"\0",那么如图所示的长度实际上是6的原因! 
謓泽
2022/12/12
7240
[C语言] 常量与变量
Windows10 环境变量_环境变量与用户变量
大家好,又见面了,我是你们的朋友全栈君。 Windows 10 环境变量 (用户变量与系统变量)
全栈程序员站长
2022/10/01
2.3K0
Windows10 环境变量_环境变量与用户变量
Python 局部变量与全局变量
局部变量与全局变量 全局变量 在python脚本最上层代码块的变量 全局变量可以在函数内被读取使用 局部变量 在函数体内定义的变量 局部变量无法在自身函数以外使用 global 将全局变量可以在函数体内进行修改 定义一个全局变量 定义函数 global + 全局变量名 函数体内给全局变量重新赋值 工作中, 不建议使用global对全局变量进行修改 仅支持 数字 字符串 空类型 布尔类型 的声明 列表和字典的全局变量不需要global进行声明 代码 # coding:utf-8 name = 'dewe
Zkeq
2022/05/18
3530
常量与变量
常量 简介: 常量代表是程序运行过程中,不能再次改变的值 作用: 1.固定的值,代表计算过程中经常用到的值,便于程序计算   如:圆周率 3.1415926..... 2.用来代表一个含义   如:
小沐沐吖
2022/09/09
3180
static–静态变量与普通变量的区别
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。
全栈程序员站长
2022/08/18
7640
static–静态变量与普通变量的区别
JavaScript全局变量与局部变量
在 JavaScript 函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它。(该变量的作用域是局部的)。
HaC
2020/12/30
7110
Python 再谈变量作用域与变量引用
var = 'global var in ClassOne' # 类中的全局变量
授客
2019/09/11
9310
Python 再谈变量作用域与变量引用
npm与nvm的冲突处理
node本身包含一个npm,后来本人通过它安装nvm来管理npm版本,长期以来一直相安无事,再后来在终端使用中莫名其妙出现一个奇怪问题——无论在独立终端,还是vscode的集成终端,输入以下命令都能打印一样结果:
IT晴天
2019/05/14
1.3K0
gccc如何处理static变量初始化
局部变量在C++中的使用要频繁的多,并且功能也强大的多,但是这些强大功能的背后无疑会引入问题的复杂性,不想让马儿吃草只想让马儿跑的事大家表乱想。这些初始化的实现就需要C++的库执行更多的动作来完成,虽然各种编译器都是像如今开展的“学雷锋”活动一样干了很多好事都没有留名,但是作为一个程序员,还是要对别人的贡献进行表彰。 我们看一下下面的一段代码,本文将会围绕这个代码进行展开,可以看到这个简单的程序,让C++生成了非常多的代码让人应接不暇
thierryzhou
2022/12/01
7600
es6中的let声明变量与es5中的var声明变量的区别,局部变量与全局变量
自己通过看typescript官方文档里的let声明,与阮一峰老师翻译的的es6学习文档,总结以下三点 1、var声明可以多次重复声明同一个变量,let不行 2、let变量只在块级作用域里面有效果,var 变量不存在块级作用域(块级作用域指用{}包装的代码块,个人理解) 3、let变量不会声明提前,var变量会 以下是具体例子 for(var i=0;i<10;i++){ setTimeout(function(){console.log(i)},1000); } 由于var声明的变量会声明提升var i
windseek
2018/06/14
1.3K0
ubuntu环境变量配置文件_环境变量与用户变量
Ubuntu Linux系统包含两类环境变量:系统环境变量和用户环境变量。系统环境变量对所有系统用户都有效,用户环境变量仅仅对当前的用户有效。
全栈程序员站长
2022/09/29
1K0
用Groovy处理JMeter变量
本来没打算写这个系列的,又看了看JMeter的文档,发现Groovy在JMeter中能发挥很多非常有趣的功能,虽然语法和API比较隐晦,但好得不多。
FunTester
2020/03/05
1.1K0
用Groovy处理JMeter变量

相似问题

通过指向基类对象的指针来操作指向派生类对象的指针

45

使用指向派生类对象的基类指针

40

指向派生类的基指针

20

使用基类指针数组调用派生类方法,基类指针具有指向派生类对象的指针

11

如何通过指向派生类的基类指针调用基类方法

30
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文