5.5.19 · HinglishEmbedded Systems & Real-Time Software

MISRA C — rules for safety-critical C code

3,291 words15 min readRead in English

5.5.19 · Coding › Embedded Systems & Real-Time Software

MISRA C ek software development guidelines ka set hai jo C programming language ke liye Motor Industry Software Reliability Association (MISRA) ne banaya hai. Iska maqsad embedded systems mein, khaaskar automotive, aerospace, aur medical devices jaise safety-critical applications mein, code ki safety, security, portability, aur reliability badhana hai.

Version note: Yeh note MISRA C:2012 (current baseline, baad ke Amendments/Technical Corrigenda ke saath) follow karta hai. Rule numbers purane MISRA C:2004 se alag hain; jahan koi rule versions ke beech badla hai, wahan explicitly bataya gaya hai.

MISRA C Kyun Exist Karta Hai

Car ke braking system ya medical device mein, ek bhi bug jaan le sakta hai. MISRA C, C ke "dangerous" parts ko restrict karta hai taaki ek safer subset mile jo zyada predictable aur verifiable ho.

The 80/20 Insight

Safety-critical C bugs ka 80% C ki 20% features se aata hai: unchecked pointers, implicit conversions, dynamic memory, aur implementation-defined behavior. MISRA inhi specific features ko eliminate ya constrain karta hai.

Core Philosophy

Key Rule Categories

Neeche saare rule numbers MISRA C:2012 ke hain jab tak alag na bataya jaye.

1. Prohibited Language Features

Rule 21.3 (Required): <stdlib.h> ke memory allocation aur deallocation functions use nahi hone chahiye

Kyun? Dynamic allocation kar sakta hai:

  • Runtime par fail (out of memory)
  • Memory ko unpredictably fragment karna
  • Timing non-determinism create karna (heap management overhead)
  • Memory leaks banana agar cleanup fail ho

Iske badle kya karein? Static allocation ya stack allocation use karein jisme compile-time par bounds pata hon:

// NO - MISRA violation
int *buffer = malloc(size * sizeof(int));
 
// YES - MISRA compliant
#define MAX_BUFFER 256
int buffer[MAX_BUFFER];

Rule 10.1 / 10.3 (Required): Incompatible "essential types" ke beech operands / assignment constrained hain

MISRA C:2012 ek essential type model use karta hai (ek operand essentially Boolean, character, signed, unsigned, enum, ya floating hota hai). Rules 10.1 aur 10.3 in types ko un tareekon se mix karna forbid karte hain jo silently data lose karte hain ya signedness change karte hain.

Kyun? Implicit conversions silently data lose kar sakte hain ya signedness change kar sakte hain:

// NO - implicit int to unsigned conversion
unsigned int u = -1;  // Wraps to 0xFFFFFFFF!
 
// YES - explicit, reviewer sees intent
unsigned int u = 0xFFFFFFFFU;  // Value visible and intentional

2. Pointer Safety

Rule 18.1 (Required): Ek pointer jo pointer operand par arithmetic se result kare, usi array ka element address kare jisme woh pointer operand hai

First principles se Derivation:

  1. Ek pointer ek memory address hold karta hai:
  2. Pointer arithmetic: matlab
  3. Yeh tabhi valid hai jab same array ke andar ya ek past the end point kare
  4. Problem: Compiler arbitrary pointers ke liye compile time par array bounds verify nahi kar sakta
  5. MISRA solution: Sirf un pointers par arithmetic allow karo jo provably arrays mein point karte hain

Yeh step kyun? Is restriction ke bina, aap accidentally memory ke end se bahar ja sakte ho:

int x = 42;
int *p = &x;
p++;  // MISRA VIOLATION - p now points to undefined memory!

Rule 18.7 (Required): Automatic storage wale object ka address kisi aur object mein copy nahi hona chahiye jo pehle object ke khatam hone ke baad bhi exist kare

(Note: MISRA C:2004 mein closely related restriction Rule 17.6 thi.)

Kyun? Dangling pointer prevention:

int* get_local(void) {
    int local = 10;
    return &local;  // VIOLATION - local destroyed on return
}

3. Type Safety

Rule 10.1 (Required): Bitwise/shift operators essentially signed type ke operands par apply nahi hone chahiye

(MISRA C:2004 mein analogous rule Rule 12.7 thi.)

Derivation:

  1. &, |, ^, <<, >> jaise bitwise ops values ko bit patterns ki tarah treat karte hain
  2. Signed integers ke liye, bit pattern two's complement representation par depend karta hai
  3. Problem: Sign bit + right shift = implementation-defined (arithmetic vs logical shift)
  4. Example: (-1) >> 1 compiler par depend karta hua -1 ya 0x7FFFFFFF ho sakta hai

Solution: Sirf unsigned types par bitwise ops use karo jahan bit pattern standardized ho:

// NO - MISRA violation
int mask = 0xFF;
int result = value & mask;  // signed operands
 
// YES - MISRA compliant  
unsigned int mask = 0xFFU;
unsigned int result = value & mask;

4. Control Flow Restrictions

Rule 15.6 (Required): Iteration/selection statement ka body ek compound statement hona chahiye (braces mein enclosed)

Kyun? "Dangling else" bug rokta hai aur structure explicit banata hai:

// NO - MISRA violation
if (condition)
    action1();
    action2();  // Nested lagta hai lekin hai NAHI!
 
// YES - intent is clear
if (condition) {
    action1();
}
action2();  // Obviously not nested

Rule 15.5 (Advisory): Ek function ka end mein single point of exit hona chahiye

Important version distinction: MISRA C:2004 mein single-exit Required tha (old Rule 14.7, "A function shall have a single point of exit"). MISRA C:2012 ne isse Advisory guideline (Rule 15.5) tak relax kiya — multiple returns permitted hain, lekin single exit ab bhi recommended hai kyunki yeh cleanup aur verification ko simplify karta hai.

Derivation (kyun advice ab bhi valid hai):

  1. Multiple returns multiple exit paths create karte hain
  2. Har exit path ko cleanup verification chahiye (mutexes unlock karo, files close karo)
  3. return statements ke saath, jagah cleanup miss ho sakti hai
  4. Single exit → cleanup ek jagah hoti hai → correctness verify karna asaan
// Permitted in C:2012, but Advisory Rule 15.5 discourages early returns
int process(int x) {
    if (x < 0) return -1;
    if (x == 0) return 0;
    return x * 2;
}
 
// Single-exit style preferred by Rule 15.5 (Advisory)
int process(int x) {
    int result;
    if (x < 0) {
        result = -1;
    } else if (x == 0) {
        result = 0;
    } else {
        result = x * 2;
    }
    return result;
}

Rule Classification System

(MISRA C:2004 mein sirf do categories thein: Required aur Advisory. Mandatory category C:2012 mein nayi hai.)

Example: Complete MISRA-Compliant Function

Scenario: Temperature sensor read karo aur Celsius mein convert karo, bounds checking ke saath.

/* MISRA C:2012 compliant temperature conversion */
#include <stdint.h>
 
#define TEMP_MIN (-40)
#define TEMP_MAX (125)
#define ADC_MAX_VALUE (4095U)  /* 12-bit ADC */
 
/* Rule 8.2 (Required): function types shall be in prototype form
   Rule 8.7 (Advisory): objects/functions used only in one file
   should have internal linkage (static) */
static int16_t read_temperature(uint16_t adc_value);
 
static int16_t read_temperature(uint16_t adc_value) {
    int16_t temp;
    uint32_t scaled;  /* wider unsigned intermediate to avoid overflow */
 
    /* Rule 14.4 (Required): controlling expression of 'if' shall have
       essentially Boolean type — here a genuine comparison */
    if (adc_value > ADC_MAX_VALUE) {
        temp = TEMP_MAX;  /* Clamp to maximum */
    } else {
        /* Formula: temp_C = (adc / 4095) * 165 - 40
           Rearranged for integer math: (adc * 165) / 4095 - 40
           Rule 10.4 (Required): both operands of the same essential
           type category — promote to uint32_t before multiply */
        scaled = ((uint32_t)adc_value * 165U) / ADC_MAX_VALUE;
        /* Rule 10.3 (Required): explicit cast on assignment to a
           narrower/other essential type */
        temp = (int16_t)scaled + TEMP_MIN;
    }
 
    /* Single exit — Rule 15.5 (Advisory) satisfied */
    return temp;
}

Har step kyun?

  1. uint16_t adc_value: Fixed-width type (Rule 4.6 Advisory <stdint.h> types prefer karta hai) — platforms par portable
  2. uint32_t scaled: adc_value * 165 mein overflow rokna (16-bit overflow ho jaata)
  3. Explicit casts: Har essential-type conversion visible aur intentional banao (Rules 10.3/10.4)
  4. Pehle bounds check: Computation se pehle safety
  5. Single return: Advisory Rule 15.5 satisfy karta hai

Common Mistakes aur Unhe Fix Kaise Karein

Wrong approach:

uint16_t value = get_sensor();
int8_t small = (int8_t)value;  /* Data loss! value=300 → small=44 */

Kyun sahi lagta hai: Compiler complaint karna band kar deta hai.

Kyun galat hai: Cast warning ko silence karta hai problem fix kiye bina. Aap 16 bits ko 8 bits mein truncate kar rahe ho, data lose ho raha hai.

Fix:

uint16_t value = get_sensor();
if (value > 127U) {  /* Rule 14.4: explicit boolean test */
    /* Handle error - value too large */
    value = 127U;  /* Clamp or return error */
}
int8_t small = (int8_t)value;  /* Now safe */

Kyun sahi lagta hai: Extra checks aur documentation likhna upfront time leta hai.

Kyun galat hai: Production mein bugs ki cost orders of magnitude higher hoti hai:

  • Automotive recall: $1M+ per incident
  • Medical device failure: Lawsuits, deaths, company shutdown
  • Aerospace bug: Mission failure, loss of spacecraft

Math: 0.01 \times \1M \times 10{,}000 = $100M$$

1% bug rate bhi scale par catastrophic hai. MISRA ko 10-100x reduce karta hai.

Kyun sahi lagta hai: Kam rules = kam kaam, aur Mandatory rules se deviate nahi ho sakta.

Kyun galat hai: Required rules MISRA ka bulk banate hain aur decades ki hard-won experience capture karte hain. Inhe skip karna matlab apne bugs se seekhna — aur Required rule se deviate karne ke liye formal documented justification chahiye, silent omission nahi.

Example: Rule 2.1 (Required) unreachable code forbid karta hai, aur Rule 2.2 (Required) dead code (code execute hota hai lekin koi effect nahi) forbid karta hai. Inhe ignore karna:

  • Reviewers ko confuse karta hai
  • Ek real logic error hide kar sakta hai (code accidentally dead hai)
  • Embedded systems mein scarce program memory waste karta hai

(Steel-man / correction: pehle maine "dead code" ko advisory Rule 2.2 about headers ke roop mein mis-cite kiya tha — actually Rule 2.2 (Required) precisely dead code ke baare mein hai, yaani no-effect operations; unreachable code Rule 2.1 hai.)

Fix: Default mein saare rules follow karo, sirf documented reasoning ke saath deviate karo.

Practical Verification Workflow

Source Code
    ↓
Static Analyzer (PC-lint Plus, Coverity, Polyspace, LDRA)
    ↓ (generates violation report)
Deviation Review (Safety team formally justifies each deviation)
    ↓
Code Review (Humans verify analyzer + logic)
    ↓
Unit Tests (Runtime verification)
    ↓
Integration Tests
    ↓
Certification (DO-178C, ISO 26262, IEC 62304)

Key insight: MISRA necessary hai lekin sufficient nahi. Phir bhi chahiye:

  1. Dynamic testing: Saari conditions ke under code run karo
  2. Formal methods: Properties mathematically prove karo (critical sections ke liye)
  3. Code review: Design issues ke liye human judgment (khaaskar undecidable rules ke liye)

Real-World Impact

Regulators MISRA C require ya strongly recommend karte hain kyunki yeh defects ki poori classes ship hone se pehle hi remove kar deta hai:

  • ISO 26262 (automotive) coding standards jaise MISRA C ko language-related faults avoid karne ke means ke roop mein reference karta hai.
  • IEC 62304 (medical device software) aur DO-178C (airborne software) bhi similarly ek restricted, verifiable coding subset expect karte hain.

Illustrative categories jinhein MISRA C target karta hai (defects ke wo types jo industry mein field failures cause karte rahe hain):

  • Unsafe pointer arithmetic / out-of-bounds access (Rule 18.1)
  • Automatic objects ke dangling pointers (Rule 18.7)
  • Implicit sign/width conversions se data loss (Rules 10.x)
  • Unbounded recursion se stack overflow ka risk (Rule 17.2)

Accuracy caveat: Popular retellings kabhi-kabhi specific past automotive incidents ko precise MISRA-rule violations se attribute karti hain. Public investigation findings zyada nuanced hain aur cleanly ek single documented software defect ko ek single MISRA rule se pin nahi karti, isliye hum inhe representative fault classes jinhein MISRA guard karta hai ke roop mein present karte hain, na ki kisi ek company ke code ke baare mein claim ke roop mein.

Diagram: MISRA C Safety Mechanism

Figure — MISRA C — rules for safety-critical C code
Recall Ek 12-saal ke bachche ko explain karo

Socho tum ek LEGO robot bana rahe ho jo har baar perfectly kaam karna chahiye, kyunki yeh ek real car drive karne ya medical machine control karne wala hai. C language aisa hai jaise tumhare paas LEGO pieces ka ek bada dabba ho, lekin kuch pieces sharp hain, kuch asaani se toot jaate hain, aur kuch theek se fit nahi hote.

MISRA C ek rulebook ki tarah hai jo kehti hai: "Toote pieces use mat karo. Sharp wale use mat karo. Sirf un tareekon se pieces connect karo jinhe hum ne million baar test kiya hai." Yeh mean hone ki koshish nahi kar raha — yeh tumhare robot ko car crash karne ya kisi ko hurt karne se rokne ki koshish kar raha hai!

Rules irritating lag sakte hain ("Yeh cool pointer trick kyun nahi use kar sakta?"), lekin har rule exist karta hai kyunki kisi ne, kahin, ek aisa robot banaya jो catastrophically fail hua kyunki unhone woh "cool trick" use ki. MISRA ne unhi galtiyon se seekha taaki tumhe na seekhna pade.

Connections

  • Real-Time Operating Systems (RTOS) — MISRA often combined with RTOS like FreeRTOS for scheduling
  • Static Analysis Tools — Tools like PC-lint Plus, Coverity, LDRA enforce MISRA
  • ISO 26262 — Automotive safety standard that recommends MISRA C compliance
  • DO-178C — Aerospace software standard (recommends MISRA or similar)
  • Memory Safety — MISRA's pointer rules directly address memory vulnerabilities
  • Formal Verification — MISRA-compliant code is easier to verify with tools like Frama-C
  • Embedded C Best Practices — MISRA is the gold standard for embedded guidelines
  • IEC 62304 — Medical device software standard that references MISRA

#flashcards/coding

MISRA C kya hai? :: Software development guidelines ka ek set jo C ke liye unsafe language features restrict karta hai taaki embedded aur safety-critical systems mein safety, reliability, aur verifiability improve ho.

Yeh note kaun sa MISRA C version follow karta hai, aur 2004 se classification kaise alag hai?
MISRA C:2012. Isme ek Mandatory category (koi deviation allowed nahi) add ki gayi hai jo purani Required aur Advisory categories ke upar hai jo MISRA C:2004 mein thein.
MISRA C (Rule 21.3) dynamic memory allocation (malloc/free) kyun prohibit karta hai?
Dynamic allocation runtime par fail ho sakti hai, memory ko unpredictably fragment kar sakti hai, timing non-determinism introduce kar sakti hai, aur memory leaks create kar sakti hai — ye sab safety-critical real-time systems mein unacceptable hain.
MISRA C:2012 ki teen rule categories kya hain?
Mandatory (follow karna zaroori, koi deviation nahi), Required (follow karo, formal documentation ke saath deviation allowed), aur Advisory (recommended best practices).
MISRA pointer arithmetic ko same array ke andar kyun restrict karta hai (Rule 18.1)?
Allocated memory ke end se bahar undefined regions mein jaane se rokne ke liye, jo crashes aur security vulnerabilities cause karta hai jo compile time par catch nahi ho sakte.
Essentially signed types par bitwise operators MISRA mein kyun nahi hone chahiye?
Kyunki signed integers par bitwise/shift operations sign bit involve karte hain aur implementation-defined behavior produce karte hain (jaise arithmetic vs logical right shift), code non-portable ho jaata hai.
Kya MISRA C:2012 mein single-point-of-exit Mandatory hai?
Nahi. Yeh MISRA C:2004 mein Required tha (old Rule 14.7) lekin MISRA C:2012 mein sirf Advisory (Rule 15.5) hai — multiple returns permitted hain, single exit sirf recommended hai.
MISRA C:2012 mein automatic (local) object ka address return karne se kaun sa rule rokta hai?
Rule 18.7 (Required) — automatic object ka address object khatam hone ke baad persist nahi karna chahiye. (C:2004 mein related rule 17.6 thi.)
MISRA explicit type casts kyun require karta hai?
Implicit essential-type conversions silently data lose kar sakti hain, signedness change kar sakti hain, ya alag compilers par alag behave kar sakti hain — explicit casts programmer ki intent reviewers aur tools ke liye visible banate hain.
Rule 15.6 (saare control-statement bodies par braces) kaunsi problem rokta hai?
"Dangling else" bug aur indentation-based confusion jahan code nested lagta hai lekin hota nahi, jo maintenance ke dauran logic errors lead karta hai.
MISRA C:2012 Rules 2.1 aur 2.2 kis baare mein hain?
Rule 2.1 unreachable code forbid karta hai; Rule 2.2 dead code (no-effect operations) forbid karta hai. Dono Required hain.
MISRA C ka ISO 26262 jaise safety standards se kya relation hai?
ISO 26262 (automotive), IEC 62304 (medical), aur DO-178C (aerospace) language-related faults avoid karne ke hisse ke roop mein MISRA C jaisa restricted coding standard reference ya recommend karte hain.
MISRA C ke zyaadatar rules ko "decidable" kyun kaha jaata hai?
Kyunki zyaadatar rules is tarah design hain ki static analysis tools automatically check kar sakein; ek minority undecidable classify hai aur human judgement require karti hai.
MISRA C ke peechhe 80/20 insight kya hai?
Safety-critical C bugs ka 80% C ki 20% features se aata hai (pointers, implicit conversions, dynamic memory, undefined behavior), isliye MISRA unhi specific features ko restrict karta hai.

Concept Map

creates

include

include

include

constrains

defines

guided by

enables

ensures

Rule 21.3 bans

replaced by

Rule 10.x uses

achieves

C language power and risk

Dangerous features

Pointers and implicit conversions

Dynamic memory

Undefined behavior

MISRA C:2012

Safer C subset

Core principles

Static analysis checkable

Predictability across compilers

Static or stack allocation

Essential type model

Safety and reliability