How to spot undefined behavior

后端 未结 10 511
梦毁少年i
梦毁少年i 2021-01-11 11:45

Is there any way to know if you program has undefined behavior in C++ (or even C), short of memorizing the entire spec?

The reason I ask is that I\'ve noticed a lot

相关标签:
10条回答
  • 2021-01-11 11:57

    Well, this article covers most aspects..

    0 讨论(0)
  • 2021-01-11 11:58

    Static code analysis tools such as PC-Lint can help a lot here

    0 讨论(0)
  • 2021-01-11 12:04

    It's not possible to detect undefined behavior in all cases. For example, consider x = x++ + 1;. If you're familiar with the language, you know it's UB. Now, *p = (*p)++ + 1; is obviously also UB, but what about *q = (*p)++ + 1;? That's UB if q == p, but other than that it's defined (if awkward-looking). In a given program, it might well be possible to prove that p and q will never be equal when reaching that line, but that can't be done in general.

    To help spot UB, use all of the tools you've got. Good compilers will warn for at least the more obvious cases, although you may have to use some compiler options for best coverage. If you have further static analysis tools, use them.

    Code reviews are also very good for spotting such problems. Use them, if you've got more than one developer available.

    0 讨论(0)
  • 2021-01-11 12:08

    clang tries hard to produce warnings when undefined behavior is encountered.

    0 讨论(0)
  • 2021-01-11 12:10

    Good coding standards. Protect you from yourself. Here are some ideas:

    1. The code must compile at the highest warning level... without warnings. (In other words, your code must not set off any warnings at all when set to the highest level.) Turn on the error on warning flag for all projects.

      This does mean some extra work when you use other peoples' libraries since they may not have done this. You will also find there are some warnings which are pointless... turn those off individually as your team decides.

    2. Always use RAII.

    3. Never use C style casts! Never! - I think there's like a couple rare cases when you have to break this but you will probably never find them.

    4. If you must reinterpret_cast or cast to void then use a wrapper to make sure you're always casting to/from the same type. In other words, wrap your pointer/object in a boost::any and cast a pointer to it into whatever you need and on the other side do the same. Why? Because you will always know what type to reinterpret_cast from and the boost::any will enforce that you've cast to the correct type after that. It's the safest you can get.

    5. Always initialize your variables at the point of declaration (or in constructor initializers when in a class).

    There are more but those are some very important ones to start with.

    Nobody can memorize the standard. What we intermediate to advanced C++ programmers do is use constructs we know are safe and protect ourselves from our human nature... and we don't use constructs that are not safe unless we have to and then we take extra care to make sure the danger is all wrapped up in a nice safe interface that is tested to hell and back.

    One important thing to remember which is universal across all languages is to:

    make your constructs easy to use correctly and difficult to use incorrectly

    0 讨论(0)
  • 2021-01-11 12:14

    I think you can use one tool from coverity to spot bugs which are going to lead to undefined behavior.

    I guess you could use theorem provers (i only know Coq) to be sure your program does what you want.

    0 讨论(0)
提交回复
热议问题