Keil C51 在编译时不会为结构指针分配内存

Posted

技术标签:

【中文标题】Keil C51 在编译时不会为结构指针分配内存【英文标题】:Keil C51 doesn't allocate memory for struct pointers at compile time 【发布时间】:2021-10-08 01:49:58 【问题描述】:

我正在尝试为 EFM8 微控制器项目创建结构链接列表。我想让编译器在编译时为所有节点分配内存。我遇到的问题是没有为结构指针分配内存。

#define FOO_QUEUE_LEN   32
 
struct Foo 
    uint8_t  bar0;
    struct Foo *next;
;
 
struct Foo queue[FOO_QUEUE_LEN];
 
void main (void)

    while(1)  ;; 

我希望这段代码为每个 Foo 结构分配 4 个字节(bar0 为 1 个字节,next 为 3 个字节,因为在此架构中,如果您不指定内存位置,则为 24 位地址是必需的。

但在调试时,该结构只报告每个结构的 1 个字节,并且扩展任何数组成员都会显示 Error: cannot dereference this type 消息。

更奇怪的是,如果你在主循环中对结构体数组进行操作,结构体在内存中的大小计算正确:queue[1].bar0 = 0xCC; 会将值写入内存地址 0x4。问题是编译没有分配足够的内存,所以我们超出了每个结构的边界(在这种情况下,0xCC 最终位于queue[4].bar0)。

是否需要一些指令在编译时正确调整这些结构指针的大小?

【问题讨论】:

我希望它是调试器的工件。如果只打印 sizeof 值会发生什么? 谢谢@SergeyA,你为我解决了这个问题。在主循环中,添加一个变量来存储 sizeof(queue) 和一个 dummy 来存储 0xCCCC,我可以看到结构数组在哪里结束并且它被正确分配。非常感谢! 【参考方案1】:

comment from SergeyA 是正确答案:

我希望它是调试器的产物。如果只打印 sizeof 值会发生什么?

考虑这个程序的扩展版本:

#define FOO_QUEUE_LEN   32

struct Foo 
    uint8_t  bar0;
    struct Foo* next;
;

struct Foo xdata queue[FOO_QUEUE_LEN];




void zeroFooStruct(struct Foo *fooPacket) 
    // Using FF for debugging so I can see memory writes
    fooPacket->bar0 = 0xFF;
    fooPacket->next = 0;


void initializeFooQueue(void)

    uint8_t i;
    struct foo *previous;

    previous = NULL;

    // This linked list is a FILO
    for (i=0; i<FOO_QUEUE_LEN; i++)
    
        zeroFooStruct(&queue[i]);
        queue[i].next = previous;
        previous = &queue[i];
    


void main (void)

    uint16_t s;
    uint16_t mydata = 0xCCCC;
    initializeFooQueue();

    s = sizeof(queue);

    while(1)  ;; 

我们可以看到,对于每个节点,我们为 bar0 存储 0xFF 和前一个节点的地址。 4 个字节乘以 32 个节点 = 0x80 个内存插槽。然后,该内存空间具有我们预期的sizeof 值 (0x0080),后跟我们的虚拟值 (0xCCCC),表明确实分配了正确的内存量,而调试器没有正确显示内存。

【讨论】:

请注意,您的列表与您选择的变量名称的链接方式令人困惑。 next 实际上指向前一个元素(假设 queue[0] 是您列表的头部,如果您认为 queue[FOO_QUEUE_LEN-1] 是您的头部,那么 IMO 同样令人困惑)。 是的,这很好。这实际上是一个更大程序的抽象,其中有两个由相同结构数组组成的 FILO 缓冲区。该数组本身保存在另一个结构中,该结构具有指向这两个列表中每个列表中第一个元素的指针。所以数组中的实际顺序并不重要,因为链表可以以任何组合对它们进行排序。对我来说重要的是在编译时分配内存。

以上是关于Keil C51 在编译时不会为结构指针分配内存的主要内容,如果未能解决你的问题,请参考以下文章

Keil C51 中堆栈指针的问题

突破KEIL软件编译时 C51中断号最大只能为31限制的补丁,使中断号可以达到256

keil c51为啥按f12时不能跟踪函数

keil c51编译器怎么有的文件出错时,双击错误提示没有定位到错误行,有的文件就可以,怎么回事

结构体指针在使用完free后,该指针所指向的内存区域是啥,这个指针是变成了NULL,还是野指针。

C 语言结构体 ( 结构体中嵌套一级指针 | 分配内存时先 为结构体分配内存 然后再为指针分配内存 | 释放内存时先释放 指针成员内存 然后再释放结构头内存 )