我在Uno克隆上运行以下程序。
uint32_t counter = 0;
void setup(){ Serial.begin(9600); 而(串行!);}
void loop(){ char * result = malloc(32); sprintf的(结果,…
你为什么不用 String() ,如下面的代码:
String()
uint32_t counter = 0; void setup() { Serial.begin(9600); while(!Serial); } void loop() { Serial.print("{\"n\": "); Serial.print(String(counter)); Serial.println(" }"); delay(100); counter++; }
允许使用malloc(),但对内存非常有限的Arduino不太有用。
Arduino没有操作系统,如果没有足够的内存可以分配,它可能会产生干扰。 (无论如何,为了让Arduino永远奔跑,应该怎么做?)
如果您有Java背景,请避免使用 new 关键字也是如此,这会导致同样的问题。
new
如果您需要内存,请尽早(最好在编译时)获取内存并保留它。
当然, free(result) 反应也是正确的。
free(result)
每一次 loop 被调用,分配32字节的内存。 Arduino Uno没有太多内存,因此它很快耗尽。完成使用后需要释放内存。这是一个类比。
loop
RAM是一块字符串。该字符串具有固定长度。你可以剪下一根绳子,随意使用它。这是分配。如果从字符串中继续剪切32个字节,最终会耗尽。完成使用后,您需要将一段字符串重新粘贴到主字符串上。这是释放。
这是一个非常糟糕的比喻,但我希望你有这个想法!要解决眼前的问题,您可以简单地追加 free(result) 到每次分配时解除分配的函数的末尾。要真正正确地解决问题,您应该在堆栈而不是堆上进行分配。在堆栈上分配时,内存将在作用域的末尾自动释放。要在堆栈上分配32个字节,您只需执行以下操作:
char result[32];
记忆中的 result 只在它的封闭范围内有效( loop 功能)。上面的代码基本上等同于:
result
char result_0; char result_1; char result_2; // ... char result_29; char result_30; char result_31;
堆栈分配比堆分配快得多( malloc 和 free )因为编译器确切知道你正在使用多少内存。这有其缺点。为了堆栈分配内存,编译器需要知道你正在使用多少内存!你不能这样做:
malloc
free
int size = get_a_number_from_somewhere(); char result[size];
因为编译器不知道要分配多少内存。但是这样:
int size = get_a_number_from_somewhere(); char *result = malloc(size); // ... free(result);
完全没问题。
通常,当您需要的内存量是编译时常量时,应该堆栈分配(例如, 32 )否则堆分配。每次你写 malloc ,仔细想想相应的地方 free 应该去。
32