Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
168 views
in Technique[技术] by (71.8m points)

c++ - Is there a platform or situation where dereferencing (but not using) a null pointer to make a null reference will behave badly?

I'm currently using a library that uses code like

T& being_a_bad_boy()
{
    return *reinterpret_cast<T*>(0);
}

to make a reference to a T without there actually being a T. This is undefined behavior, specifically noted to be unsupported by the standard, but it's not an unheard of pattern.

I am curious if there are any examples or platforms or usages that show that in practice this can cause problems. Can anyone provide some?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Classically, compilers treated "undefined behavior" as simply an excuse not to check for various types of errors and merely "let it happen anyway." But contemporary compilers are starting to use undefined behavior to guide optimizations.

Consider this code:

int table[5];
bool does_table_contain(int v)
{
    for (int i = 0; i <= 5; i++) {
        if (table[i] == v) return true;
    }
    return false;
}

Classical compilers wouldn't notice that your loop limit was written incorrectly and that the last iteration reads off the end of the array. It would just try to read off the end of the array anyway, and return true if the value one past the end of the array happened to match.

A post-classical compiler on the other hand might perform the following analysis:

  • The first five times through the loop, the function might return true.
  • When i = 5, the code performs undefined behavior. Therefore, the case i = 5 can be treated as unreachable.
  • The case i = 6 (loop runs to completion) is also unreachable, because in order to get there, you first have to do i = 5, which we have already shown was unreachable.
  • Therefore, all reachable code paths return true.

The compiler would then simplify this function to

bool does_table_contain(int v)
{
    return true;
}

Another way of looking at this optimization is that the compiler mentally unrolled the loop:

bool does_table_contain(int v)
{
    if (table[0] == v) return true;
    if (table[1] == v) return true;
    if (table[2] == v) return true;
    if (table[3] == v) return true;
    if (table[4] == v) return true;
    if (table[5] == v) return true;
    return false;
}

And then it realized that the evaluation of table[5] is undefined, so everything past that point is unreachable:

bool does_table_contain(int v)
{
    if (table[0] == v) return true;
    if (table[1] == v) return true;
    if (table[2] == v) return true;
    if (table[3] == v) return true;
    if (table[4] == v) return true;
    /* unreachable due to undefined behavior */
}

and then observe that all reachable code paths return true.

A compiler which uses undefined behavior to guide optimizations would see that every code path through the being_a_bad_boy function invokes undefined behavior, and therefore the being_a_bad_boy function can be reduced to

T& being_a_bad_boy()
{
    /* unreachable due to undefined behavior */
}

This analysis can then back-propagate into all callers of being_a_bad_boy:

void playing_with_fire(bool match_lit, T& t)
{
    kindle(match_lit ? being_a_bad_boy() : t);
} 

Since we know that being_a_bad_boy is unreachable due to undefined behavior, the compiler can conclude that match_lit must never be true, resulting in

void playing_with_fire(bool match_lit, T& t)
{
    kindle(t);
} 

And now everything is catching fire regardless of whether the match is lit.

You may not see this type of undefined-behavior-guided optimization in current-generation compilers much, but like hardware acceleration in Web browsers, it's only a matter of time before it starts becoming more mainstream.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...