Forum: Mikrocontroller und Digitale Elektronik Problem mit MISRA-Regeln 12.2 und 12.4


von Michael S. (michael8192)


Lesenswert?

Hallo zusammen,

Bei folgendem Programmcode erhalte ich die Regelverletzung Nr. 12.2 und 
12.4 gemäss MISRA-C (2004), die ich mir nicht erklären kann bzw. ich 
nicht weiss, wie ich das beheben könnte. Das Regelwerk bezüglich diesen 
Punkten habe ich gelesen, aber die bringen mich auch nicht weiter, was 
ich konkret verändern müsste.
Vielleicht habt ihr eine Idee?
Besten Dank.
1
[ MISRA 12.2 ] The value of an expression shall be the same under any order of evaluation that the standard permits.
2
->Line No :  27  :  while( ( get_a( ) == OFF ) && ( ( get_b( ) == ON ) || ( get_c( ) == ON ) ) )
3
4
[ MISRA 12.4 ] The right-hand operand of a logical && or || operator shall not contain side effects. 
5
->Line No :  27  :  while( ( get_a( ) == OFF ) && ( ( get_b( ) == ON ) || ( get_c( ) == ON ) ) )
Codebeispiel (ist nicht wirklich sinnvoll und dient nur zum Test der 
Regelverletzung):
1
typedef  signed  int int32_t;
2
3
#define     OFF     0U
4
#define     ON      1U
5
6
7
int32_t main( void );
8
void    get_a( void );
9
void    get_b( void );
10
void    get_c( void );
11
12
int32_t main( void )
13
{
14
    int32_t a = OFF;
15
    int32_t b = OFF;
16
    int32_t c = OFF;
17
18
    while( ( get_a( ) == OFF ) && ( ( get_b( ) == ON ) || ( get_c( ) == ON ) ) )
19
    {
20
21
    }
22
23
    return 0U;
24
}
25
26
void get_a( void )
27
{
28
    if( a == OFF )
29
    {
30
    }
31
    else
32
    {
33
        a = OFF;
34
    }
35
}
36
37
void get_b( void )
38
{
39
    if( b == OFF )
40
    {
41
        b = ON;
42
    }
43
    else
44
    {
45
    }
46
}
47
48
void get_c( void )
49
{
50
    if( c == OFF )
51
    {
52
        c = ON;
53
    }
54
    else
55
    {
56
    }
57
}

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

get_b() wird nicht aufgerufen wenn get_a() == OFF nicht wahr ist usw. 
Sobald der Ausdruck in einem if false wird, werden weitere Teile nicht 
aufgerufen.

Deshalb ist folgendes auch möglich:
1
char * c;
2
3
if((NULL != c) && *c)
4
  access_to_c_is_never_a_null_pointer_access();

Matthias

von Michael S. (michael8192)


Lesenswert?

Sorry, der Code ist so wie oben natürlich Käse...
1
typedef  signed  int int32_t;
2
3
#define     OFF     0U
4
#define     ON      1U
5
6
7
int32_t main( void );
8
int32_t get_a( void );
9
int32_t get_b( void );
10
int32_t get_c( void );
11
12
    int32_t a = OFF;
13
    int32_t b = OFF;
14
    int32_t c = OFF;
15
16
int32_t main( void )
17
{
18
19
20
    while( ( get_a( ) == OFF ) && ( ( get_b( ) == ON ) || ( get_c( ) == ON ) ) )
21
    {
22
23
    }
24
25
    return 0U;
26
}
27
28
int32_t get_a( void )
29
{
30
    if( a == OFF )
31
    {
32
    }
33
    else
34
    {
35
        a = OFF;
36
    }
37
  return a;
38
}
39
40
int32_t get_b( void )
41
{
42
    if( b == OFF )
43
    {
44
        b = ON;
45
    }
46
    else
47
    {
48
    }
49
  return b;
50
}
51
52
int32_t get_c( void )
53
{
54
    if( c == OFF )
55
    {
56
        c = ON;
57
    }
58
    else
59
    {
60
    }
61
  return c;
62
}

von Michael S. (michael8192)


Lesenswert?

@Matthias,

danke für Deinen Tipp, so in etwa stand das auch in der Regel, nur was 
könnte ich da anders machen? Die Codezeile mit der while-Schleife 
umschreiben geht sicher, nur sollte es auch möglichst wenig 
Programmspeicher beanspruchen, wegen µC.

von benwilliam (Gast)


Lesenswert?

es geht nur darum das in der while-schleife methoden stehen und nicht 
ausschließlich variablen oder konstanten.
was get_a, get_b, get_c machen ist egal es ist einfahc allgemein 
schlechter stil methoden in kontrollstrukturen auf zu rufen. (also auch 
bei IFs möglichst vermeiden)

was zwar nicht schön ist aber dir hier helfen müsste wäre:
1
int32_t a = get_a();
2
int32_t b = get_b();
3
int32_t c = get_c();
4
5
while( ( a == OFF ) && ( ( b == ON ) || ( c == ON ) ) )
6
{
7
8
}

von Michael S. (michael8192)


Lesenswert?

Aha, besten Dank.

ich habe das so mal ausprobiert, und die Regelverletzung ist weg. Leider 
ist das nur eine von vielen (verschiedenen) Codezeilen mit der gleichen 
Regelverletzung, die ich nun alle umarbeiten muss. (Ich habe das 
Programm nicht selbst geschrieben und muss nur die Prüfung durchführen). 
Aber das Problem an sich habe ich jetzt denke ich erkannt.

von Thosch (Gast)


Lesenswert?

benwilliam schrieb:
> was zwar nicht schön ist aber dir hier helfen müsste wäre:
das ist aber nicht äquivalent zum oben angeführten Code!
Dein Code führt stets alle 3 Funktionen aus, aber nur einmal...

Die Funktionsaufrufe müßten dann auch noch in die Schleife,
sonst wird sie entweder nie durchlaufen oder zur Endlosschleife.
1
int32_t a = get_a();
2
int32_t b = get_b();
3
int32_t c = get_c();
4
5
while( ( a == OFF ) && ( ( b == ON ) || ( c == ON ) ) )
6
{
7
    a = get_a();
8
    b = get_b();
9
    c = get_c();
10
}

Gruß,
Thosch

von Μαtthias W. (matthias) Benutzerseite


Lesenswert?

Hi

@benwilliam
Dein Code ist aber nicht identisch zu dem von Michael S. In deinem Fall 
werden die drei Funktionen immer aufgerufen. Im Fall von Michael eben 
nicht. Sollten die drei Methoden keine Seiteneffekte haben (z.B. eine 
globale Variabel verändern) ist das kein Problem. Falls doch muss man 
mit gestaffelten if-Abfragen arbeiten.

[c]
while(1)
  if(OFF == get_a( ))
    if(ON == get_b( ))
      if(ON == get_c( ))
        break;
[c/]

Matthias

von benwilliam (Gast)


Lesenswert?

Thosch schrieb:
>
> Die Funktionsaufrufe müßten dann auch noch in die Schleife,
> sonst wird sie entweder nie durchlaufen oder zur Endlosschleife.


wer lesen kann ist klar im Vorteil!
ich brauch ganz dringend Wochenende

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.