简体   繁体   English

在 C/freeRTOS 中使用“goto”停止任务

[英]Using "goto" to stop a task in C/freeRTOS

I'm using a State Machine task to handle the flow of my program.我正在使用状态机任务来处理我的程序流。 When a state is selected (other than STAND BY), the State Machine wake up the associated task with the “xTaskNotifyGive” function as all other tasks are locked by “ulTaskNotifyTake( pdTRUE, portMAX_DELAY);” When a state is selected (other than STAND BY), the State Machine wake up the associated task with the “xTaskNotifyGive” function as all other tasks are locked by “ulTask​​NotifyTake( pdTRUE, portMAX_DELAY);”

During the execution of those state-related tasks, a problem can happen and the state-related task has to stop.在这些状态相关任务的执行过程中,可能会发生问题,状态相关任务必须停止。 In order to do that, a Safety task set a flag “ContinueTask”.为了做到这一点,安全任务设置了一个标志“ContinueTask”。 In the state-related task, we regularly check this flag.在状态相关的任务中,我们会定期检查这个标志。 If it is false, the code following won't be executed.如果为 false,则不会执行以下代码。

For the moment, the structure of the code look like this:目前,代码的结构如下所示:

ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally){
    //some code
}
ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally){
    //some code
}
...
ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally){
    //some code
}

The problem is that if the flag is set up the first time we check it, it will still check it for the next part of the code.问题是,如果标志在我们第一次检查时就被设置了,它仍然会在接下来的代码部分检查它。

On way to solve this is to use a cascade of if/else statements like this:解决这个问题的方法是使用像这样的 if/else 语句的级联:

ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally){
    //code
}
else{
    ContinueTaskInternally = ContinueTaskCopy();
    if (ContinueTaskInternally){
        //code
    }
    else{
        ContinueTaskInternally = ContinueTaskCopy();
        if (ContinueTaskInternally){
            //code
        }
        else{
            ....
        }
    }
}

But if we check this flag a lot of time if the task, the number of indentation will be really high and it won't be readable.但是如果我们在任务中多次检查这个标志,缩进的数量会非常高,并且不可读。

I was wondering if, in this case, it's possible to use the “goto” statement, like this:我想知道,在这种情况下,是否可以使用“goto”语句,如下所示:

ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally) goto exitTask;
//some code

ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally) goto exitTask;
//some code
...

ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally) goto exitTask;
//some code

exitTask:
//code before exiting task

What do you think about it?你怎么看待这件事? I made some research about those "goto" statment but I was not able to determine if it is ok to use as some people disagree on this subject without giving extra explenation why.我对那些“goto”语句进行了一些研究,但我无法确定是否可以使用,因为有些人不同意这个主题而没有给出额外的解释原因。

To me, this is a good situation to use short circuit boolean logic .对我来说,这是使用短路布尔逻辑的好情况。

That is: If the flag is ever set to false , the second part of the && expression will not get evaluated.也就是说:如果标志设置为false&&表达式的第二部分将不会被评估。 The function ContinueTaskCopy() will not be run.函数ContinueTaskCopy()将不会运行。

As long as the flag is true , all code will run.只要标志为true ,所有代码都会运行。
As soon as the flag is false , it will skip all the if-statements and all the ContinueTaskCopy statements until the end of the function.一旦标志为false ,它将跳过所有 if 语句和所有ContinueTaskCopy语句,直到函数结束。

The makes your code look like:这使您的代码看起来像:

bool ContinueTaskInterally = true;

ContinueTaskInternally = ContinueTaskInterally && ContinueTaskCopy();
if (ContinueTaskInternally){
    //some code
}
ContinueTaskInternally = ContinueTaskInterally && ContinueTaskCopy();
if (ContinueTaskInternally){
    //some code
}
...
ContinueTaskInternally = ContinueTaskInterally && ContinueTaskCopy();
if (ContinueTaskInternally){
    //some code
}

Without giving my opinion on the usage of "goto" keyword, I think you can achieve the same behaviour and avoiding cyclomatic complexity using this code:在不对“goto”关键字的使用发表意见的情况下,我认为您可以使用以下代码实现相同的行为并避免圈复杂度:

ContinueTaskInternally = ContinueTaskCopy();
if (ContinueTaskInternally)
{
    //some code
    //...
    ContinueTaskInternally = ContinueTaskCopy();
}
if (ContinueTaskInternally)
{
    //some code
    //...
    ContinueTaskInternally = ContinueTaskCopy();
}
if (ContinueTaskInternally)
{
    //some code
    //...
}
//code before exiting task

Yes.是的。 goto is not recommended, but in your case, it would work.不建议使用goto ,但在您的情况下,它会起作用。 I just want to explain here why is goto non-recommended:我只想在这里解释为什么不推荐使用goto

1. Dynamic memory allocation 1.动态内存分配

If you allocate memory dynamically ( malloc in general, GlobalAlloc on Windows etc.), you may do a code like this:如果您动态分配内存(通常是malloc ,Windows 上的GlobalAlloc等),您可以执行如下代码:

int* something = (int*)malloc(sizeof(int));
// do something
if (condition) goto endProgram;
free(something);
endProgram:
// "something" may haven't been freed

So something will remain allocated.所以something将保持分配。

2. Understanding the code and risk of undefined behavior 2. 理解未定义行为的代码和风险

goto can make your code less readable or pretty non-straightforward. goto可以使您的代码不那么可读或非常不直截了当。 Let's see this example:让我们看看这个例子:

if (condition) goto someLabel;
if (anotherCondition) {
    someLabel:
    // code
    goto abc;
}
for (int i = 0; i < limit; ++i) {
    // some code
    abc:
    // other code
}

So we jump into the second if if condition is true... then we jump to the middle of for ... some code may haven't been executed including setting i to 0 so it is undefined behavior... this code could be rethought without goto .因此,我们跳进第二if如果condition是真的......那么我们跳到中间for ......一些代码可能不会被执行,包括设置i为0,所以它是不确定的行为...此代码可能是重新思考没有goto

In this specific case I think that goto just fits well.在这种特定情况下,我认为 goto 非常适合。 You got the most clear and effectivive solution this way.您通过这种方式获得了最清晰、最有效的解决方案。 Just as for everything else make sure you understand the tools you are using to avoid doing a mess.就像其他所有事情一样,请确保您了解您正在使用的工具,以免弄得一团糟。 And it's rather easy to make a mess and misuse "goto".而且很容易弄乱和误用“goto”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM