亲爱的Stackoverflow用户,
我有一个有趣的问题,我希望听到你的意见,也请在任何部分纠正我。
在普通的PC中,内存地址分为3个部分,堆栈,堆,全局,(现在让我们忘记外围),所以如果我继续做一个错误的递归函数,用调用填充堆栈,操作系统将发送stackoverflow的消息,如果我在其中创建一个带有new关键字的无限循环,它会用垃圾数据填充堆,并获得类似segfault的东西,但是如果我在arduino项目中犯了这样的错误怎么办? / p>
try / catch块不在游戏中,所以我试图在loop()中自己实现错误处理,滥用预处理器的愚蠢:
#define THROW(errval) \
ERROR = errval; \
loop()
#define TRY \
if(ERROR == 0)
#define CATCH(err) \
else if(err == ERROR)
#define FINALLY \
if(ERROR != 0)
#define OUT_OF_MEMORY 1
int ERROR = 0;
void random_routine() {
if(/*something goes wrong*/) {
THROW(OUT_OF_MEMORY);
}
}
void start() { Serial.begin(9600); }
void loop() {
TRY {
random_routine();
} CATCH(OUT_OF_MEMORY) {
Serial.println("out of memory");
} FINALLY {
while(true);
}
}
现在你可能不会立即看到这个技巧,所以这就是你在预处理之后得到的:
void random_routine() {
if(/*something goes wrong*/) {
ERROR = 1;
//this call is the body of my exception handling solution
//and the question is about this as well
loop();
}
}
void start() { Serial.begin(9600); }
void loop() {
///TRY-s macro result
if(ERROR == 0) {
random_routine();
///chainable CATCH blocks
} else if(ERROR == 1) {
Serial.println("Out of memory");
}
///FINALLY block
if(ERROR != 0) {
while(true);
}
}
所以我的问题是,如果由于某种原因内存已满,如果函数调用能够被执行怎么办?因为THROW宏总是会调用loop(),这样我的想法就是逃避'从当前的上下文进入无限循环
抱歉我的英文不好
答案 0 :(得分:0)
所以,如果你想退出一个函数并回到你来自的地方,你应该离开这个函数,而不是调用原来的函数!通过从函数返回,或使用setjmp
和longjmp
。
在所有情况下,您还需要担心"如何清理数据"。换句话说,如果你分配内存,那么你需要在离开函数之前释放它,你已经打开了一个文件,你需要关闭它等等。
这些东西是RAII原理非常方便的地方,但它假设您在编译器的知识下保留了这个功能,而不是只是在没有清理的情况下跳回主循环。它迟早会引起问题。
还要注意堆栈溢出的行为是UNDEFINED BEHAVIOR - 它可能会立即崩溃程序,或者它可能导致堆被覆盖,格式化你的硬盘/ SD卡,或者它可能导致守护进程飞出你的鼻子。或者你可以想象的任何其他东西,然后是一些。它是未定义的,你不能依靠它特别做任何事情 - 只是那个"你不应该这样做"。