Monday, April 14, 2025

First Step in Safety-Critical Software Development

The first action when developing safety-critical software is to add automatic commit checks for compiler warnings and reject the commit if any warnings are present. Enable the highest warning level and treat all warnings as errors.

Common Visual C++ warnings relevant to safety critical systems:

  1. C26451: Arithmetic overflow: Using operator 'op' on a value that may overflow the result (comes from Code Analysis with /analyze). Example: uint64_t c = a + b where a and b are of type uint32_t
  2. C4244: Conversion from ‘type1’ to ‘type2’, possible loss of data. Example: int → char or double → float
  3. C4018: Signed/unsigned mismatch. Can cause logic bugs and unsafe comparisons.
  4. C4701: Potentially uninitialized variable
  5. C4715: Not all control paths return a value
  6. C4013: 'function' undefined; assuming extern returning int
Of course, there is much more that needs to be done; in this blog post, I just wanted to focus on the first step from the perspective of a tech lead.

Saturday, April 12, 2025

UDP vs TCP

When working with real-time systems, it's important to understand how data is sent and received over UDP and TCP. The main reason to use UDP is that it can be 10x faster than TCP, but you have to be aware of its limitations.

UDP (User Datagram Protocol) sends data in discrete packets (called datagrams). Each call to sendto() on the sender side corresponds to exactly one recvfrom() on the receiver side.

  • No connection setup or teardown.
  • No built-in guarantees about delivery, order, or duplication (intermediate routers may retransmit packets if they think the first one was lost).
  • If you call sock.recvfrom(4) and the incoming packet is 9 bytes, you get the first 4 bytes—and the rest are discarded.

Rough Performance Advantage:

  • In short, bursty communications or real-time streaming, UDP can be 2x to 10x faster than TCP due to its lack of handshake, retransmission, and flow control mechanisms.
  • In my test case, UDP returned a DNS response in 42 ms, while TCP took 382 ms — nearly 9x faster.

TCP (Transmission Control Protocol) provides a continuous stream of bytes. It breaks your data into segments under the hood, but applications don’t see those packet boundaries.

  • Reliable: Guarantees delivery, order, and no duplication (if a duplicate packet is received, TCP automatically discards it).
  • Stream-oriented: You send bytes, not messages.
  • If you send b"Message 1", and call sock.recv(4), you might receive b"Mess", and then get the rest (b"age 1") in another call.
If the message might get corrupted during the creation phase rather than during transmission over the network, and you want to add a CRC to detect corruption at the application layer, then UDP might be better because it delivers the entire message, including the CRC, in a single recvfrom call.