c - 为什么这个结构需要比 sizeof 本身更多的分配空间?
问题描述
我对 C 中的动态内存有点陌生,到目前为止我已经设法更好地理解它,但我正在尝试为这个结构分配内存,它应该是 24 字节长,但保留 24 字节不起作用,我必须分配 29 个字节或更多才能使其工作,我不明白这个的确切原因。
我正在尝试创建一个函数来初始化 tInfection,并且我正在为 tInfection tInfectiousAgent* 指针分配内存object->tInfectiousAgent = (tnfectiousAgent*) malloc(sizeof(tInfectiousAgent));
这是调试器信息,据我所知,如果不能分配其数据,malloc 会返回 NULL 指针吗?但在这里它不返回 NULL 指针。
这是2个结构
tError infection_init(tInfection* object, tInfectiousAgent* infectiousAgent, const char* country, tDate* date, int cases, int deaths){
// We check pre conditions
assert(object != NULL);
assert(infectiousAgent != NULL);
assert(country != NULL);
assert(date != NULL);
// We allocate memory
object->infectiousAgent = (tInfectiousAgent*) malloc(sizeof(tInfectiousAgent));
object->country = (char*) malloc(sizeof(char) * (strlen(country) + 1));
object->date = (tDate*) malloc(sizeof(tDate));
// We check that memory was allocated correctly
if ((object->country == NULL) || (object->date == NULL) || (object->infectiousAgent == NULL)) {
return ERR_MEMORY_ERROR;
}
//infectiousAgent_cpy(object->infectiousAgent, infectiousAgent);
strcpy(object->country, country);
strcpy(object->date, date);
object->cases = cases;
object->deaths = deaths;
return OK;
}
解决方案
您是否分配足够的空间不是这里的问题。如果您使用sizeof
,一切都应该正常工作。
顺便说一句,如果您提供错误的尺寸,
malloc
也不会失败,因为它无法知道正确的尺寸是多少。它只能使用你给它的东西,对或错。如果您在界限之外读取或写入,错误的大小通常会导致问题出现,但那是在成功之后。malloc
潜在问题是您的调试器中的r0
,medium
和的值date
。3.09456111e+35
浮点数的值r0
存储为 IEEE754 单精度十六进制字节{7a,6e,65,75}
(请参阅此处了解让我辨别的有用工具)。medium
变量是{33,48,20,61}
,变量date
是{32,4e}
。
如果您应用英特尔小端调整,您最终得到的字节序列是(如下所示为十六进制转储,包括 ASCII 字符):
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +0123456789
0000 75 65 6e 7a 61 20 48 33 4e 32 uenza H3N2
鉴于您在谈论传染性病原体,那几乎可以肯定是字符串的一部分Influenza H3N2
,是许多流感病毒株之一。浮点数、指针和其他非字符串的东西可能包含看起来像文本的东西,但是三个连续的变量在它们之间都有一个连贯的字符串这一事实,以及指针值不是有效地址的事实,强烈暗示了损坏。
这意味着您正在执行类似将该字符串直接复制到指针所在的空间中的操作,因此可能会在某处溢出一些缓冲区。造成这种情况的一个潜在原因可能是strcpy(object->date, date)
,除非tDate
是与 C 样式字符串兼容的类型( 的定义tDate
将有助于确定这是否是问题所在)。
你的论点也支持这一点,即使结构应该是 24 字节长,除非你分配 29 字节,否则会发生奇怪的事情。这是一个明显的迹象,表明某些东西正在超出其应有的范围,并且很可能会破坏内存领域。
我不确定根本原因,因为您没有提供所有可以让我们确定这一点的代码,但根据我们可以看到的证据,这是一个不错的选择。
还有一件事需要注意,比如:
assert(object != NULL);
实际上,如果定义了 when是没有效果的。NDEBUG
assert.h
通常,该宏不是为调试版本定义的,而是为发布版本定义的(当然,这取决于您的构建系统)。
这意味着您不能将assert
其用作通用合同保护,因为发布版本会将其转换assert
为空操作。因此,如果断言可以基于运行时数据为真或假,assert
则可能不是该工作的好工具(如果它仅基于编译时数据,那么您将在测试期间捕获所有断言)。
推荐阅读
- c# - 依赖注入 ASP.NET 身份用户(和单元测试)
- c - 减法的性能是否不如否定?
- angular - 在angular2中使用模态创建表单
- python - 如何在 Windows 上修复此 pytorch 错误?(ModuleNotFoundError:没有名为“火炬”的模块)
- batch-file - 使用 BAT 脚本更改快捷方式的目标
- javascript - 如何更改自定义手风琴的图标?
- java - IntelliJ maven 项目生成的源未拾取(仅部分)
- ios - 分段选择器内的元素修饰符不起作用
- c - 如何制作不包含 time.h 的 24 小时制时钟?
- vue.js - 如何在 vue.js 的生产模式下启用控制台日志记录