October 6th, 2024

The Strict Aliasing Situation Is Pretty Bad (2016)

Strict aliasing rules in C and C++ can hinder compiler optimizations and lead to undefined behavior when pointers are misused. Using the -fno-strict-aliasing flag and checking tools is recommended.

Read original articleLink Icon
The Strict Aliasing Situation Is Pretty Bad (2016)

The article discusses the implications of strict aliasing rules in C and C++, which can hinder compiler optimizations due to the potential for pointers to alias. The strict aliasing rule allows compilers to assume that pointers of different types do not point to the same memory location, enabling better optimization. However, this can lead to undefined behavior when programmers cast pointers inappropriately, such as accessing a floating-point value through an integer pointer. The article highlights several issues arising from strict aliasing, including broken physical subtyping in struct-based inheritance, challenges with chunking optimizations, and the potential for unexpected behavior when using non-character types like int8_t and uint8_t. It emphasizes that many C programs may inadvertently violate these rules, leading to unpredictable results, especially when optimizations are enabled. The author suggests that static and dynamic checking tools are necessary to ensure code correctness and recommends using the -fno-strict-aliasing flag when writing correctness-oriented C code. Overall, the article underscores the need for caution when dealing with strict aliasing in C and C++ to avoid subtle bugs and undefined behavior.

- Strict aliasing rules can prevent compiler optimizations due to potential pointer aliasing.

- Violating strict aliasing can lead to undefined behavior in C and C++ programs.

- Many existing C programs may inadvertently break strict aliasing rules.

- Using the -fno-strict-aliasing flag is advisable for correctness-oriented C code.

- Static and dynamic checking tools are essential for ensuring code correctness.

Link Icon 6 comments
By @jandrewrogers - 3 months
This is an issue that is ignored by just about everyone in practice. The reality is that most developers have subconsciously internalized the compiler behavior and assume that will always hold. And they are mostly right, I’ve only seen a few cases where this has caused a bug in real systems over my entire career. I try, to the extent possible, to always satisfy the requirements of strict aliasing when writing code. It is difficult to determine if I’ve been successful in this endeavor.

Here is why I don’t blame the developers: writing fast, efficient systems code that satisfies the requirements of strict aliasing as defined by C/C++ is surprisingly difficult. It has taken me years to figure out the technically correct incantations for every weird edge case such that they always satisfy the requirements of strict aliasing. The code gymnastics in some cases are entirely unreasonable. In fairness, recent versions of C++ have been adding ways to express each of these cases directly, eliminating the need to use obtuse incantations. But we still have huge old code bases that assume compiler behavior, as was the practice for decades.

I am not here to attribute blame, I think it the causes are pretty diffuse honestly. This is just a part of the systems world we failed to do well, and it impacts the code we write every day. I see strict aliasing violations in almost every code base I look at.

By @sapiogram - 3 months
Has anyone measured the performance impact of the -fno-strict-aliasing flag? How much real-world performance are we really gaining from all this mess?
By @icedchai - 3 months
I learned C on the Amiga, back in the late 80's, and the OS made heavy use of "OO-ish" physical subtyping with structs everywhere. I don't think anybody even thought about strict aliasing violations.
By @RossBencina - 3 months
Interesting that the article doesn't even entertain the obvious solution: remove strict aliasing requirements from the standards.
By @Gabriel54 - 3 months
Forgive me my ignorance, but if I write

  int foo(int *x) {
    *x = 0;
    // wait until another thread writes to *x
    return *x;
  }

Can the C compiler really optimize foo to always return 0? That seems extremely unintuitive to me.
By @dang - 3 months
Discussed at the time:

The Strict Aliasing Situation Is Pretty Bad - https://news.ycombinator.com/item?id=11288665 - March 2016 (67 comments)