嵌入式 C 中的动态内存分配
Dynamic memory allocation in embedded C
我可以在嵌入式 C 中使用函数 malloc 和 delete 吗?例如,我有一个函数,其中使用函数 malloc 在结构上创建了指针。这个函数 return 在 ram 中的地址,我可以使用它。从我的函数退出后,在分配内存的地方,该指针将被删除或为此保留该内存,而不是函数删除终止?
Typedef struct {
Char varA;
Char varB
} myStruct ;
Void myfunc ( void)
{
myStruct * ptrStruct = ( myStruct *) malloc ( sizeof (myStruct)) ;
// Code here
//........
return ;
}
通常,您不应在嵌入式系统中使用 malloc
,因为这样做 没有任何意义 as explained here。特别是,在裸机系统上使用它没有任何意义。
唯一 可以使用动态内存分配的地方是大型托管的多进程系统,其中多个进程共享相同的 RAM。如果您对嵌入式系统的定义是 Android 智能 phone 或便携式 PC,那么可以使用 malloc。
如果您发现自己在其他地方使用它,这几乎可以肯定意味着您的程序设计存在根本性缺陷,而且您不了解堆的工作原理。
此外,几乎每个嵌入式系统编程标准都禁止动态内存分配。
是的,你可以在嵌入式C中使用malloc。一些嵌入式系统有自己封装的内存分配API。 malloc() 是 C 库 API.
内存是从堆中分配的,堆是系统设计者定义的专用内存范围。如果您在函数退出后没有释放分配的内存,则分配的内存将被保留,其他进程将无法使用它。通常,它是内存泄漏。如果你释放分配的内存但之后你仍然使用指针,它是一个野指针并且会导致未知行为。
对于阻止使用动态内存的嵌入式系统,没有什么特别的。
但是您可能需要通过多种方式为其提供支持,例如:
- 您需要确保链接器为动态堆分配足够的space。某些链接器脚本可能已经在堆栈和任何其他保留分配之后自动将所有剩余内存分配给堆。
- 您可能需要实施低级存根以允许库访问堆内存 - 例如在 newlib 库中,您需要实施
sbrk_r()
才能使 malloc()
等正常工作。
- 在多线程系统中,您可能需要实施互斥存根以确保安全的堆分配。如果库不提供这样的存根,那么
malloc()
/free()
等在这样的环境中使用是不安全的,你应该编写在外部断言锁的包装函数。
然而,您可能会选择避免在嵌入式系统中使用动态内存(或至少是标准库实现的动态内存)的原因有很多:
- 标准分配方案具有不适合硬实时系统的非确定性时序。
- 您需要优雅地处理每次分配失败的可能性。安全地处理潜在的非确定性 运行 时间错误比简单地让编译器告诉您在构建时内存不足要复杂得多。
- 你需要防范内存泄漏;任何系统都是如此,但没有 OS 来管理内存耗尽和终止泄漏进程,您的系统将如何表现?
- 如果没有互斥存根或包装函数,标准库堆管理可能不是线程安全的。
- 破坏堆的错误不太可能立即影响执行,通常只会在执行新的堆操作时导致可观察到的失败,从而在与实际原因无关的时间和位置导致不确定的行为 - 使它们很难诊断。这同样适用于任何系统,但交叉托管嵌入式系统中的调试工具通常不如自托管系统复杂。
我可以在嵌入式 C 中使用函数 malloc 和 delete 吗?例如,我有一个函数,其中使用函数 malloc 在结构上创建了指针。这个函数 return 在 ram 中的地址,我可以使用它。从我的函数退出后,在分配内存的地方,该指针将被删除或为此保留该内存,而不是函数删除终止?
Typedef struct {
Char varA;
Char varB
} myStruct ;
Void myfunc ( void)
{
myStruct * ptrStruct = ( myStruct *) malloc ( sizeof (myStruct)) ;
// Code here
//........
return ;
}
通常,您不应在嵌入式系统中使用 malloc
,因为这样做 没有任何意义 as explained here。特别是,在裸机系统上使用它没有任何意义。
唯一 可以使用动态内存分配的地方是大型托管的多进程系统,其中多个进程共享相同的 RAM。如果您对嵌入式系统的定义是 Android 智能 phone 或便携式 PC,那么可以使用 malloc。
如果您发现自己在其他地方使用它,这几乎可以肯定意味着您的程序设计存在根本性缺陷,而且您不了解堆的工作原理。
此外,几乎每个嵌入式系统编程标准都禁止动态内存分配。
是的,你可以在嵌入式C中使用malloc。一些嵌入式系统有自己封装的内存分配API。 malloc() 是 C 库 API.
内存是从堆中分配的,堆是系统设计者定义的专用内存范围。如果您在函数退出后没有释放分配的内存,则分配的内存将被保留,其他进程将无法使用它。通常,它是内存泄漏。如果你释放分配的内存但之后你仍然使用指针,它是一个野指针并且会导致未知行为。
对于阻止使用动态内存的嵌入式系统,没有什么特别的。
但是您可能需要通过多种方式为其提供支持,例如:
- 您需要确保链接器为动态堆分配足够的space。某些链接器脚本可能已经在堆栈和任何其他保留分配之后自动将所有剩余内存分配给堆。
- 您可能需要实施低级存根以允许库访问堆内存 - 例如在 newlib 库中,您需要实施
sbrk_r()
才能使malloc()
等正常工作。 - 在多线程系统中,您可能需要实施互斥存根以确保安全的堆分配。如果库不提供这样的存根,那么
malloc()
/free()
等在这样的环境中使用是不安全的,你应该编写在外部断言锁的包装函数。
然而,您可能会选择避免在嵌入式系统中使用动态内存(或至少是标准库实现的动态内存)的原因有很多:
- 标准分配方案具有不适合硬实时系统的非确定性时序。
- 您需要优雅地处理每次分配失败的可能性。安全地处理潜在的非确定性 运行 时间错误比简单地让编译器告诉您在构建时内存不足要复杂得多。
- 你需要防范内存泄漏;任何系统都是如此,但没有 OS 来管理内存耗尽和终止泄漏进程,您的系统将如何表现?
- 如果没有互斥存根或包装函数,标准库堆管理可能不是线程安全的。
- 破坏堆的错误不太可能立即影响执行,通常只会在执行新的堆操作时导致可观察到的失败,从而在与实际原因无关的时间和位置导致不确定的行为 - 使它们很难诊断。这同样适用于任何系统,但交叉托管嵌入式系统中的调试工具通常不如自托管系统复杂。