inlining and function static variables

Discussion in 'C++' started by publictom@blueyonder.co.uk, May 17, 2005.

  1. Guest

    I just happened to read item 47, "Control Flow", in Exceptional C++ by
    Herb Sutter (which is based on Guru of the Week 12), just after reading
    item 33, "Use Inlining Judiciously", in Effective C++ by Scott Meyers.
    Now I'm a little confused.

    Scott Meyers says that if an inline function can't be inlined by the
    compiler it is treated like a normal non-inlined function. However, he
    says that there is an older behaviour where compilers would treat the
    function as static, so there would be multiple copies of it, one in
    each translation unit that uses the function. He says the latter
    behaviour is non-standard but (was at the time, 1998...?) widespread
    enough that you should be aware of it.

    Skipping to Herb Sutter's book, published 2 years later, there is the
    following code:

    // [This declaration comes from some other header file]
    extern int fileIdCounter;
    ....
    // Helpers to automate class invariant checking.
    template<class T>
    inline void AAssert( T& p )
    {
    static int localFileId = ++fileIdCounter;
    if( !p.Invariant() )
    {
    cerr << "Invariant failed: file " << localFileId
    << ", " << typeid(p).name()
    << " at " << static_cast<void*>(&p) << endl;
    assert( false );
    }
    }

    This is at the start of a chunk of example code designed to illustrate
    things that can go wrong with control flow. The only problem that the
    book points out with the variable localFileId is that fileIdCounter
    might not be initialised by the time the first copy of localFileId is
    initialised. (Aside: Aren't function static variables initialised the
    first time the function is executed, ie. after all globals are
    initialised? I'm not sure I understand this problem)

    It seems to me, though, that aside from the problem of the order of
    initialisation, this code would only work as intended if the function
    was not successfully inlined, and then only on a compiler that followed
    the incorrect (according to Meyers) behaviour of treating the
    non-inlined inline function as local to the translation unit.

    If the function was successfully inlined, or if the compiler followed
    the standard behaviour of treating the function as a normal non-inlined
    function if it can't inline it, wouldn't there just be a single copy of
    localFileId, initialised once, in the whole program, thus defeating the
    object of using it to identify the file? Although this would be a
    control flow problem, "Exception C++" doesn't mention it, and neither
    do any of the posts I could find for the corresponding Guru of the
    Week, so I think I must have misunderstood something.

    I was wondering whether the fact the function is a template might have
    some effect, but I found this:
    "A namespace scope template function has internal linkage if it is
    explicitly declared static. No other template function has internal
    linkage. The inline function specifier does not affect the linkage of a
    template function."
    at
    http://publib.boulder.ibm.com/infoc...om.ibm.vacpp6m.doc/compiler/ref/tutmplat3.htm.

    Can anyone help?
     
    , May 17, 2005
    #1
    1. Advertising

  2. wrote:
    > // [This declaration comes from some other header file]
    > extern int fileIdCounter;


    This variable is defined elsewhere.

    > ...
    > // Helpers to automate class invariant checking.
    > template<class T>
    > inline void AAssert( T& p )
    > {
    > static int localFileId = ++fileIdCounter;
    > if( !p.Invariant() )
    > {
    > cerr << "Invariant failed: file " << localFileId
    > << ", " << typeid(p).name()
    > << " at " << static_cast<void*>(&p) << endl;
    > assert( false );
    > }
    > }
    >
    > This is at the start of a chunk of example code designed to illustrate
    > things that can go wrong with control flow. The only problem that the
    > book points out with the variable localFileId is that fileIdCounter
    > might not be initialised by the time the first copy of localFileId is
    > initialised. (Aside: Aren't function static variables initialised the
    > first time the function is executed, ie. after all globals are
    > initialised? I'm not sure I understand this problem)


    It's called "static initialisation order fiasco". Look it up.

    > It seems to me, though, that aside from the problem of the order of
    > initialisation, this code would only work as intended if the function
    > was not successfully inlined, and then only on a compiler that followed
    > the incorrect (according to Meyers) behaviour of treating the
    > non-inlined inline function as local to the translation unit.
    >
    > If the function was successfully inlined, or if the compiler followed
    > the standard behaviour of treating the function as a normal non-inlined
    > function if it can't inline it, wouldn't there just be a single copy of
    > localFileId, initialised once, in the whole program, thus defeating the
    > object of using it to identify the file?


    Actually the purpose wasn't to identify the file, but rather to identify
    an instantiation of 'AAssert' for all T, probably.

    There will be a single copy of 'localFieldId' for every instantiation of
    'AAssert'. This is required by the Standard (14.8/2).

    > [..]


    V
     
    Victor Bazarov, May 17, 2005
    #2
    1. Advertising

  3. Guest

    > It's called "static initialisation order fiasco". Look it up.

    Yes, I realised after posting that if the function was called by the
    constructor of a static object then there would be a problem. I didn't
    know that situation had a name. Thanks.

    >Actually the purpose wasn't to identify the file, but rather to

    identify
    an instantiation of 'AAssert' for all T, probably.

    It would certainly work for that. It seems a funny thing to do, though.
    Working out the type for which the template was instantiated from the
    ID would be tricky, wouldn't it? It would depend on the order in which
    the different instantiations of AAsert are called for the first time.
    This seems unnecessary since the code already spits out the name of the
    type for which the template function is instantiated.
    Also, the variable is called localFileId, not localTypeId or something.
     
    , May 17, 2005
    #3
  4. wrote:
    > [...]
    > This seems unnecessary since the code already spits out the name of the
    > type for which the template function is instantiated.
    > Also, the variable is called localFileId, not localTypeId or something.


    It could just be left-over from the old days when it was intended to
    identify the file in which the function was "instantiated" from a header
    of something...
     
    Victor Bazarov, May 17, 2005
    #4
  5. Guest

    Oh. The typeid operator would give the dynamic type rather than the
    static type, so they would give different information.

    Outputing typeid<T>.name() would show the type the function was
    instantiated for, though, and would be a lot simpler than the counter.
     
    , May 17, 2005
    #5
  6. Guest

    Oh. The typeid operator would give the dynamic type rather than the
    static type, so they would give different information.

    Outputing typeid(T).name() would show the type the function was
    instantiated for, though, and would be a lot simpler than the counter.
     
    , May 17, 2005
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ronald Fischer
    Replies:
    3
    Views:
    581
    Roedy Green
    Jul 20, 2004
  2. Alex
    Replies:
    6
    Views:
    423
  3. Gianni Mariani

    inlining function objects

    Gianni Mariani, Feb 23, 2004, in forum: C++
    Replies:
    7
    Views:
    389
  4. Mat Booth

    Function Pointers and Inlining

    Mat Booth, Mar 22, 2005, in forum: C++
    Replies:
    8
    Views:
    366
    Rolf Magnus
    Mar 22, 2005
  5. Nikos Chantziaras

    Function inlining in C (not C99)

    Nikos Chantziaras, Aug 12, 2003, in forum: C Programming
    Replies:
    5
    Views:
    400
    Malcolm
    Aug 14, 2003
Loading...

Share This Page