编译器为嵌入式 C 中指向结构的指针分配相同的内存

Compiler allocates same memory for pointers to struct in embedded C

提问人:rishb 提问时间:11/15/2023 最后编辑:Jonathan Lefflerrishb 更新时间:11/15/2023 访问量:100

问:

我有一个结构,我使用指向结构的指针创建了该结构的两个实例,我希望它们根据输入返回两个不同的值。如果我在 Visual Studio Code 中执行此代码,我会看到 int_struct_pt1 和 int_struct_pt2 在内存中具有相同的地址。因此,当int_struct_pt2收到它时,int_struct_pt1值会被相同的值 int_struct_pt2 覆盖。

我正在处理STM32F4,所以我不想使用动态内存分配。有没有其他方法可以在不被覆盖的情况下获取这些数据,或者如何处理内存分配。

//int_struct.h
//Declaration in header file
typedef struct {
    int a;
    int b;
} int_struct;

int_struct * func(int a);

//int_app.c
//Pointer to struct in source file 
static int_struct* int_struct_pt1;
static int_struct* int_struct_pt2;
int_struct_pt1 = func(10);
int_struct_pt2 = func(16);

//int_struct.c
static int_struct int_struct_app;
int_struct * func(int a ){
    int_struct_st.a = a;
    int_struct_st.b = 15;
    return &int_struct_st;
}

谢谢

尝试创建不同的变量。已调试并发现指针具有相同的内存地址。 我的期望是在 C 中获得最好的方法来执行此功能而不会被覆盖。

C 指针 struct embedded

评论

2赞 Eugene Sh. 11/15/2023
当然,它接收相同的值,因为它是 返回的值,并且是静态分配的值(顺便说一句,您真的应该重新考虑您的命名以使变量更易于区分)funcint_struct_st
0赞 rishb 11/15/2023
那么你认为保留每个实例输出的最佳方式是什么。我是否需要创建另一个变量并从第一个实例复制这些变量?
1赞 Tom Karzes 11/15/2023
您声明为文件级静态变量。它只有一个实例。它只有一个地址。你有没有想过,每次调用任何引用它的函数时,它都会神奇地创建一个新的副本?事实并非如此。怎么可能?如果希望在函数返回后保留多个实例,请使用 .int_struct_stmalloc
0赞 rishb 11/15/2023
它是嵌入式 C 语言。所以我对使用 malloc 犹豫不决。此外,我正在研究的系统对安全至关重要
1赞 Eugene Sh. 11/15/2023
如果不动态分配内存,则无法动态创建新实例。您将需要根据需要预先分配尽可能多的结构实例,并让初始化函数获取指向这些变量的指针并初始化它们(如果需要初始化......

答:

1赞 gulpr 11/15/2023 #1
static int_struct int_struct_st;

只有一个实例,如果调用函数,它将始终返回同一对象的相同地址。

每次调用此函数时,都需要创建结构:

通常(因为它是一个小型 MCU 医疗项目),您应该实现静态分配的内存池分配器/释放器,这不会对堆进行碎片化。这是最简单实现的一个非常微不足道的例子:

#define MAXINITS 4

static int_struct ist[MAXINITS];
static int taken;

int_struct * func(int a )
{
    if(taken < MAXINITS)
    {
        ist[taken].a = a;
        ist[taken++].b = 15;
        return &ist[taken -1];
    }
    return NULL;
}

或与 malloc 一起使用

int_struct * func(int a ){
    int_struct *st = malloc(sizeof(*st);
    if(st)
    {
        st -> a = a;
        st -> b = 15;
    }
    return st;
}

评论

0赞 rishb 11/15/2023
第一种方法似乎我应该知道调用该函数的次数。如果我没有这些信息,你认为 malloc 是唯一的方法吗?
0赞 gulpr 11/15/2023
@rishb据我所知,在医疗嵌入式系统中,这是被禁止的。 在小目标上往往会“碎片化”堆并以非确定性的方式失败(即您可能有足够的可用内存,但您将无法进行 malloc,因为您没有足够的大块)\malloc
0赞 Lundin 11/17/2023
@rishb malloc 是任何嵌入式系统的错误解决方案,而不仅仅是像医疗技术这样的高完整性系统。TL;DR 不应该使用它,因为这样做是完全没有意义的。这里可以找到一长串原因:为什么我不应该在嵌入式系统中使用动态内存分配?
0赞 gulpr 11/17/2023
@Lundin嵌入式系统 != 微型转换器。如果您有STM32MP1 Open Linux 系统,malloc 是 100% OK。
0赞 Lundin 11/17/2023
@gulpr 是的,如果你对嵌入式系统的定义是笔记本电脑或Android手机,那么显然任何事情都会发生。但OP明确提到,使用STM32F4这是安全关键的,这意味着不能使用Linux。
2赞 Ian Abbott 11/15/2023 #2

您可以更改为初始化函数:func

void func(int_struct *st, int a ){
    st->a = a;
    st->b = 15;
}

在其他地方,为每个实例定义一个变量:

static int_struct int_struct_1;
static int_struct int_struct_2;

如果确实必须使用指针变量:

static int_struct* int_struct_pt1 = &int_struct_1;
static int_struct* int_struct_pt2 = &int_struct_2;

调用函数以初始化:int_struct

    func(&int_struct_1, 10);
    func(&int_struct_2, 16);

艺术

    func(int_struct_pt1, 10);
    func(int_struct_pt2, 16);

评论

0赞 rishb 11/15/2023
这对我来说似乎是一个很好的解决方案。谢谢!