我试图找到为如下结构动态分配内存的正确方法:
typedef struct myThread {
unsigned int threadId;
char threadPriority;
unsigned int timeSlice;
sem_t threadSem;
} myThread;
我记得,但我不确定,在一些学校的论文中,我看到为这种情况分配内存的正确方法是这样的:
myThread *node = (myThread *)malloc(sizeof(myThread *));
我试过了,效果很好,但我不明白为什么。我的体系结构的指针大小是8字节,所以通过编写上面的指令,我分配了8字节的连续内存,不足以容纳结构中所需的信息。所以我试着分配1个字节的内存,像这样:
myThread *node = (myThread *)malloc(1);
它仍然有效。我试图为这种行为找到答案,但没有成功。为什么这样有效?除此之外,我还有几个问题:
- 为结构动态分配内存的正确方法是什么
- 这个石膏有必要吗
- 这个结构是如何存储在内存中的?我知道(*node).threadId相当于node->threadId,这让我有点困惑,因为通过取消引用指向结构的指针,我得到了整个结构,然后我必须访问特定的字段。我希望通过这种方式访问知道结构地址的字段:*(node)是第一个元素的值,*(node+sizeof(firstElement))是第二个的值,依此类推。我认为访问结构字段类似于访问数组值
谢谢
后期编辑:谢谢你的回答,但我意识到我没有正确地解释自己。说它有效,我的意思是它有效地将值存储在结构的特定字段中,并在以后使用它们。我通过填充字段并在之后打印来测试这一点。我想知道为什么这是有效的,为什么我可以填充和处理我只分配了一个字节内存的结构的字段。
下面的工作原理是它们分配内存,但大小错误。
myThread *node = (myThread *)malloc(sizeof(myThread *));// wrong size,s/b sizeof(myThread)
myThread *node = (myThread *)malloc(1); // wrong size
为什么这样做?
当代码试图将数据保存到该地址时,错误的大小可能会变得明显,也可能不会变得明显。这是未定义的行为(UB)。
C在没有训练轮的情况下进行编码。当代码有UB时,比如没有分配足够的内存并使用它,它不一定会失败,它可能会失败,现在或稍后或下周二。
myThread *node = (myThread *)malloc(1); // too small
node->timeSlice = 42; // undefined behavior
为结构动态分配内存的正确方法是什么@M.M
以下内容易于正确编码、审查和维护。
p = malloc(sizeof *p); //no cast, no type involved.
// or
number_of_elements = 1;
p = malloc(sizeof *p * number_of_elements);
// Robust code does error checking looking for out-of-memory
if (p == NULL) {
Handle_error();
}
有必要进行强制转换吗?
否。我是否投射malloc的结果?
结构是如何存储在内存中的?
每个成员后面都有潜在的填充。它取决于实现。
unsigned int
maybe some padding
char
maybe some padding
unsigned int
maybe some padding
sem_t
maybe some padding
我想知道为什么这能工作,为什么我可以填充和处理我只分配了一个字节内存的结构的字段。
OP正在寻找它工作的原因。
也许内存分配是以64字节的块或超过sizeof *p
的块来完成的,所以分配1和sizeof *p
具有相同的效果。
也许由于代码使用了不足的分配而损坏的后期内存区域稍后会显现出来。
也许分配器是一只恶意的野兽,玩弄OP,结果却在明年4月1日将硬盘擦除。(恶意代码经常利用UB感染系统——这并不牵强)
都是UB。任何事情都有可能发生。
由于C中的内存分配非常容易出错,所以我总是定义宏函数NEW和NEW_ARRAY,如下例所示。这使得内存分配更加安全简洁。
#include <semaphore.h> /*POSIX*/
#include <stdio.h>
#include <stdlib.h>
#define NEW_ARRAY(ptr, n)
{
(ptr) = malloc((sizeof (ptr)[0]) * (n));
if ((ptr) == NULL) {
fprintf(stderr, "error: Memory exhaustedn");
exit(EXIT_FAILURE);
}
}
#define NEW(ptr) NEW_ARRAY((ptr), 1)
typedef struct myThread {
unsigned int threadId;
char threadPriority;
unsigned int timeSlice;
sem_t threadSem;
} myThread;
int main(void)
{
myThread *node;
myThread **nodes;
int nodesLen = 100;
NEW(node);
NEW_ARRAY(nodes, nodesLen);
/*...*/
free(nodes);
free(node);
return 0;
}
malloc
保留内存供您使用。
当您试图使用比您要求的更多的内存时,可能会出现以下几种结果,包括:
- 您的程序访问不应该访问的内存,但没有任何中断
- 您的程序访问不应该访问的内存,这会损坏程序所需的其他数据,因此程序失败
- 您的程序试图访问未映射到其虚拟地址空间中的内存,从而导致陷阱
- 编译器的优化会以一种意想不到的方式转换程序,并出现奇怪的错误
因此,当您无法分配足够的内存时,您的程序似乎可以工作,或者当您未能分配足够的存储器时,程序会中断,这都不足为奇。
为结构动态分配内存的正确方法是什么?
好的代码是myThread *node = malloc(sizeof *node);
。
有必要进行强制转换吗?
否,不在C.中
结构是如何存储在内存中的?我知道(*node).threadId相当于node->threadId,这让我有点困惑,因为通过取消引用指向结构的指针,我得到了整个结构,然后我必须访问特定的字段。我希望通过这种方式访问知道结构地址的字段:*(node)是第一个元素的值,*(node+sizeof(firstElement))是第二个的值,依此类推。我认为访问结构字段类似于访问数组值。
结构以字节序列的形式存储在内存中,就像C中的所有对象一样。您不需要进行任何字节或指针计算,因为编译器会为您进行计算。例如,在编写node->timeSlice
时,编译器获取指针node
,将偏移量添加到成员timeSlice
,并使用结果访问存储成员timeSlice
的内存。
进行时没有分配正确的大小
myThread *node = (myThread *)malloc(sizeof(myThread *));
正确的方法可以是例如
myThread *node = (myThread *)malloc(sizeof(myThread));
铸造是无用的,所以最后
myThread *node = malloc(sizeof(myThread));
或者正如在回答你的问题时所说的那样
myThread *node = malloc(sizeof(*node));
原因是您分配的myThread不是指针,所以要分配的大小是myThread的大小
如果您分配sizeof(myThread *)
,则意味着您想要myThread **
而不是myThread *
我知道(*node).threadId相当于node->threadI
是,->
取消引用,而.
不进行
让myThread node;
访问字段threadId您可以执行node.threadId
,但有一个指向您的指针需要遵守的任何方式
后期编辑:。。。
当您访问分配的块外时,没有分配足够的资源,行为是未定义的,这意味着任何事情都可能发生,包括没有任何坏的东西立即可见