Upgrade to Pro — share decks privately, control downloads, hide ads and more …

More terrible tips for C++ programmers! Part 3,...

PVS-Studio
September 01, 2023

More terrible tips for C++ programmers! Part 3, tips 11-15

We're posting more terrible tips for C++ programmers from the PVS-Studio co-owner and CMO Andrey Karpov. They are part of his free online book that contains 60 terrible tips!
For a full list with detailed explanations, see the following link: https://pvs-studio.com/en/blog/posts/cpp/1053/

PVS-Studio

September 01, 2023
Tweet

More Decks by PVS-Studio

Other Decks in Programming

Transcript

  1. 60 terrible tips for a C++ programmer Part 3 Tips

    11-15 Andrey Karpov Co-owner and CMO pvs-studio.com
  2. Introduction Today we’ll take a look at five more terrible

    tips for a C++ programmer: tips 11-15. You can view the previous tips in earlier presentations. They are made to be educational and entertaining – so I hope you’ll have a good time and learn something new. The tips are a part of my online book. Want to see all tips? Click here: 60 terrible tips for a C++ programmer.
  3. Contents: tips 11-15 • Terrible tip N11. The compiler is

    to blame for everything • Terrible tip N12. Feel free to use argv • Terrible tip N13. Undefined behavior is just a scary story • Terrible tip N14. double == double • Terrible tip N15. memmove is a superfluous function
  4. If something does not work, most likely the compiler is

    acting up. Try swapping some variables and code lines. Terrible tip N11. The compiler is to blame for everything
  5. Sure, errors may occur in compilers and get in the

    way, but in 99% of cases, there are errors in code rather than the compiler. Most frequently, the problems are caused by the misuse of the C++ language subtleties or undefined behavior. Terrible tip N11. The compiler is to blame for everything
  6. The analyzer found an error here. Most likely, the developer

    will be absolutely sure they have encountered a bug in the compiler. But pay attention to the third argument of the memset function! The sizeof operator calculates the size of the pointer, and not the size of the class. As a result, only part of the class is zeroed out. Terrible tip N11. The compiler is to blame for everything TprintPrefs::TprintPrefs(IffdshowBase *Ideci, const TfontSettings *IfontSettings) { memset(this, 0, sizeof(this));// This doesn’t // seem to help after // optimization. dx = dy = 0; isOSD = false; xpos = ypos = 0; align = 0; linespacing = 0; sizeDx = 0; sizeDy = 0; ... } The correct calculation of the class size should look like this. memset(this, 0, sizeof(*this));
  7. So how do you figure out whether it’s your mistake

    or a bug in the compiler? Here’s a handy checklist of things to do before blaming the compiler: • Ask your skilled teammates to review your code; • Look carefully if the compiler does not issue warnings to your code, and try these keys: -Wall, -pedantic; • Check the code with a static analyzer. For example, PVS-Studio; • Check the code with a dynamic analyzer; • If you know how to work with the assembler, look at the assembler listing generated for the code by the compiler. Think why the file is the way it is; • Reproduce an error with a minimal code example and ask a question on Stack Overflow. Terrible tip N11. The compiler is to blame for everything
  8. There's no time to explain — immediately use the command

    line arguments. Like that, for example: char buf[100]; strcpy(buf, argv[1]);. Checks are only for those who don't feel too confident about their own or their teammates' coding skills. Terrible tip N12. Feel free to use argv
  9. What can happen? Well, not just buffer overflow! Data processing

    without prior checks opens a Pandora's box full of vulnerabilities. Terrible tip N12. Feel free to use argv
  10. If you want to delve deeper, check out these links:

    Shoot yourself in the foot when handling input data; CWE-20: Improper Input Validation; Taint analysis (taint checking); V1010. Unchecked tainted data is used in expression. Terrible tip N12. Feel free to use argv
  11. Undefined behavior is just a scary bedtime story for children.

    Undefined behavior doesn't exist in real life. If the program works as you expected, it doesn't contain bugs. And there's nothing to discuss here, that's that. Everything is fine. Terrible tip N13. Undefined behavior is just a scary story
  12. In reality, undefined behavior is something that many developers struggle

    with. Here are some reading materials: Undefined behavior. What Every C Programmer Should Know About Undefined Behavior. Part 1, part 2, part 3. How deep the rabbit hole goes, or C++ job interviews at PVS-Studio. Undefined behavior is closer than you think. Undefined behavior, carried through the years. Null Pointer Dereferencing Causes Undefined Behavior. Undefined Behavior Is Really Undefined. With Undefined Behavior, Anything is Possible. Philosophy behind Undefined Behavior. Wrap on integer overflow is not a good idea. An example of undefined behavior caused by absence of return. YouTube. C++Now 2018: John Regehr "Closing Keynote: Undefined Behavior and Compiler Optimizations". YouTube. Towards optimization-safe systems: analyzing the impact of undefined behavior. And then just google "undefined behavior" and keep enjoying it :) Terrible tip N13. Undefined behavior is just a scary story
  13. Feel free to use the operator == to compare floating-point

    numbers. If there is such an operator, you need to use it. Terrible tip N14. double == double
  14. The first comparison A == 0.5 is true. The second

    comparison B == 0.5 may be both true and false. The result of the B == 0.5 expression depends upon the CPU, the compiler's version and the flags being used. This is a better version of the code. In this case, the comparison with the error presented by DBL_EPSILON is true because the result of the sin function lies within the range [-1, 1]. There is no single correct answer as what’s the best way to compare double type variables. In most cases you can do the following: double A = 0.5; if (A == 0.5) // True foo(); double B = sin(M_PI / 6.0); if (B == 0.5) // ???? foo(); double B = sin(M_PI / 6.0); if (std::abs(b - 0.5) < DBL_EPSILON) foo(); if (std::abs(a - b) <= DBL_EPSILON * std::max(std::abs(a), std::abs(b))) { }
  15. There is much information about ways to compare floating point

    numbers. Go ahead and dive in! Bruce Dawson. Comparing floating point numbers, 2012 Edition. Andrey Karpov. 64-bit programs and floating-point calculations. Wikipedia. Floating point. CodeGuru Forums. C++ General: How is floating point representated? Boost. Floating-point comparison algorithms. Terrible tip N14. double == double
  16. memmove is a redundant function. Use memcpy always and everywhere.

    Terrible tip N15. memmove is a superfluous function
  17. The role of the memmove and memcpy functions is identical.

    However, there is an important difference. If the memory areas passed through the first two parameters partially overlap, the memmove function guarantees that the copy result is correct. In the case of memcpy, the behavior is undefined. Let's say, you need to shift five bytes of memory by three bytes, as shown in the picture. Then: memmove – there is no problem with copying overlapping areas, the content will be copied correctly; memcpy – there will be a problem. The source values of these two bytes will be overwritten and not saved. Therefore, the last two bytes of the sequence will be the same as the first two. Terrible tip N15. memmove is a superfluous function
  18. So, why are there so many jokes about it if

    the behavior of these functions is so different? Turns out that the authors of many projects overlook some information about these functions in the documentation. For more reading, visit the following pages: memcpy() vs memmove() Glibc change exposing bugs Linux manual page Terrible tip N15. memmove is a superfluous function
  19. I hope you found these tips fun to read –

    and maybe learned something new. We’ll post a new PowerPoint dedicated to the terrible tips pretty soon. We’ll cover tips 16-20. If you want to read all the tips as soon as you can – we’ve posted a complete list of 60 terrible tips here. Conclusion