Showing posts with label cpp_ODR. Show all posts
Showing posts with label cpp_ODR. Show all posts

Jun 20, 2022

[C++] ODR notes

ODR:
https://eel.is/c++draft/basic.def.odr


All definition across the program should be the same.

It's hard.


e.g.

// size of Person might be different inside the program.
class Person{
    std::string first_;
    std::string last_;
# if HAS_MIDDLE_NAME(VAR)
    std::string middle_;
#endif
};

ODRV can be embedded anywhere(DSO, static library, or executable)

  1. Multiple, conflicting definitions of the same symbol in more than one TU.
  2. Compiling a given header/source file with different compiler settings or #defines
    Debug/Release, (no-)RTTI, mismatched preprocessor values, etc.
  3. Overriding operator new/delete in a DSO, but hiding it from the rest of the program.
    The passing C++ objects across that DSO boundary.
  4. Multple varying copies of a dependency(e.g. Boost, JPEG, zlib, etc.)


ODRV Behaviors

  1. Hard to debug
  2. Hard to reproduce
  3. Exceptions failing to get caught
  4. Crashing in the destructor after passing an object across a DSO boundary.

Jan 13, 2016

[C++] Lambda issues

https://www.reddit.com/r/cpp/comments/40lm8o/lambdas_are_dangerous/
https://www.reddit.com/r/cpp/comments/40scxe/jrbprogramming_a_workaround_for_lambda_odr/

A potential code bloat could be caused by using lambda for template arguments.

However, there's another issue, violating ODR.

Read on the reference, jot down result later...

--------------
Update:
Code taken from: A Workaround for Lambda ODR Violations
 // Based on Richard Smith trick for constexpr lambda
    // via Paul Fultz II (http://pfultz2.com/blog/2014/09/02/static-lambda/)
    template<typename T>
    auto addr(T &&t)
    {
        return &t;
    }

    static const constexpr auto odr_helper = true ? nullptr : addr([](){});

    template <class T = decltype(odr_helper)>
    inline void g() {
        int arr[2] = {};
        std::for_each(arr, arr+2, [] (int i) {std::cout << i << ' ';});
    }


It's still an ODR violation, which is that,
any inline function in the header spread into different TU that
calls g() will have different definition, due to any lambda expression
in a single TU has a different type.


Reference:

Mar 8, 2012

[c++] The One-Definition Rule ,excerpt from C++ template programming appendix A

Affectionately known as the ODR, the one-definition rule is a cornerstone for the well-formed structuring of C++ programs. The most common consequences of the ODR are simple enough to remember and apply:

Define noninline functions exactly once across all files, and define classes and inline functions at most once per translation unitmaking sure that all definitions for the same entity are identical.