Upcoming SlideShare
×

How to make fewer errors at the stage of code writing. Part N2.

197 views
139 views

Published on

This is the second article on avoiding certain errors at the early stage of code writing. In the previous post, we have already advised you to avoid a large number of calculations in one expression. However, we should investigate this question in detail. Let's see what's dangerous about complex expressions and how we can avoid many logical errors.

Published in: Technology
0 Likes
Statistics
Notes
• Full Name
Comment goes here.

Are you sure you want to Yes No
• Be the first to comment

• Be the first to like this

Views
Total views
197
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
2
0
Likes
0
Embeds 0
No embeds

No notes for slide

How to make fewer errors at the stage of code writing. Part N2.

1. 1. How to make fewer errors at the stage of code writing. Part N2. Author: Andrey Karpov Date: 29.03.2011 Abstract This is the second article on avoiding certain errors at the early stage of code writing. In the previous post, we have already advised you to avoid a large number of calculations in one expression. However, we should investigate this question in detail. Let's see what's dangerous about complex expressions and how we can avoid many logical errors. Introduction You may read the previous post here. This time we'll take error samples from various famous projects to stress their prevalence. The errors I'm going to demonstrate here were found with the help of the PVS- Studio analyzer during a relatively large term. I have informed developers of almost all the projects about the errors, so I hope they will fix the defects in new code revisions. I'm writing this in introduction because I always receive letters after publishing articles with a request "please inform the project's developers about the errors you've found". 1. Do not use the ternary operation '?:' in compound expressions A ternary conditional operation is written in C/C++ code with the '?:' operator. This is an operation that returns its second or third operand depending on the value of the logical expression defined by the first operand. For example: int minValue = A < B ? A : B; A ternary operation has a very low priority (see the table). Programmers often forget about it and that is why the ternary operation is quite dangerous.
2. 2. Figure 1 - C/C++ operations arranged in priority descending order Note that the '?:' operation has a lower priority than addition, multiplication, bitwise OR operator and so on. Consider this code: int Z = X + (A == B) ? 1 : 2; It works differently than it might seem at first sight. Most likely, the programmer intended to add the X value to number 1 or 2 depending on the (A == B) condition. But actually it is the "X + (A == B)" expression which is the condition. In fact, it is this code written in the project: int Z = (X + (A == B)) ? 1 : 2; While the programmer wanted this to be:
3. 3. int Z = X + (A == B ? 1 : 2); What occurs to you first is that you just should know the priorities of operations. Well, programmers do know them but too insidious is this ternary operation! Not only novices make mistakes with it but experienced programmers as well. You may easily find them even in the most quality code. Here are a couple of examples. V502 Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '*' operator. physics dgminkowskiconv.cpp 1061 dgInt32 CalculateConvexShapeIntersection (...) { ... den = dgFloat32 (1.0e-24f) * (den > dgFloat32 (0.0f)) ? dgFloat32 (1.0f) : dgFloat32 (-1.0f); ... } V502 Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '-' operator. views custom_frame_view.cc 400 static const int kClientEdgeThickness; int height() const; bool ShouldShowClientEdge() const;
4. 4. void CustomFrameView::PaintMaximizedFrameBorder(gfx::Canvas* canvas) { ... int edge_height = titlebar_bottom->height() - ShouldShowClientEdge() ? kClientEdgeThickness : 0; ... } V502 Perhaps the '?:' operator works in a different way than it was expected. The '?:' operator has a lower priority than the '|' operator. vm vm_file_win.c 393 #define FILE_ATTRIBUTE_NORMAL 0x00000080 #define FILE_FLAG_NO_BUFFERING 0x20000000 vm_file* vm_file_fopen(...) { ... mds[3] = FILE_ATTRIBUTE_NORMAL | (islog == 0) ? 0 : FILE_FLAG_NO_BUFFERING; ... } As you may see, errors of this type deserve consideration. That is why I've made a separate paragraph to describe them. They are quite widely-spread. I could give you some more examples but they all are similar. You can avoid such errors if you give up trying to place several operations into a single line of code. Or if you still want to do that, do not be greedy to add parentheses. I will speak of parentheses a bit later. Now let's try to avoid potential errors when using '?:'. Of course the '?:' operator is certainly a syntactic sugar and you can replace it with if in most cases. Among rare exceptions are such tasks as reference initialization: MyObject &ref = X ? A : B;