V525. The code containing the collection of similar blocks. Check items X, Y, Z, ... in lines N1, N2, N3,

16.09.2011

The analyzer detected code that might contain a misprint. This code can be split into smaller similar fragments. Although they look similar, they differ in some way. It is highly probable that this code was created with the Copy-Paste method. The V525 message is generated if the analyzer suspects that some element was not fixed in the copied text. The error might be located in one of the lines whose numbers are listed in the V525 message.

Disadvantages of the V525 message:

1) This diagnostic rule is based on heuristic methods and often produces false alarms.

2) Implementation of the rule's heuristic algorithm is complicated and occupies more than 1000 lines of C++ code. That is why it is difficult to describe in documentation. So it may be hard for the user to understand why the V525 message was generated.

3) The diagnostic message refers not to one line but several lines. The analyzer cannot point out only one line since the error may be in any of them.

Advantages of the V525 message:

1) It can detect errors which are too hard to notice during code review.

Let's study an artificial sample at first:

...
float rgba[4];
rgba[0] = object.GetR();
rgba[1] = object.GetG();
rgba[2] = object.GetB();
rgba[3] = object.GetR();

The 'rgba' array presents color and transparency of some object. When writing the code that fills the array, we wrote the line "rgba[0] = object.GetR();" at first. Then we copied and changed this line several times. But in the last line, we missed some changes, so it is the 'GetR()' function which is called instead of the 'GetA()' function. The analyzer generates the following warning on this code:

V525: The code containing the collection of similar blocks. Check items 'GetR', 'GetG', 'GetB', 'GetR' in lines 12, 13, 14, 15.

If you review lines 12, 13, 14 and 15, you will find the error. This is the correct code:

rgba[3] = object.GetA(); 

Now let's study several samples taken from real applications. The first sample:

tbb[0].iBitmap = 0; 
tbb[0].idCommand = IDC_TB_EXIT; 
tbb[0].fsState = TBSTATE_ENABLED; 
tbb[0].fsStyle = BTNS_BUTTON; 
tbb[0].dwData = 0; 
tbb[0].iString = -1; 
...
tbb[6].iBitmap = 6; 
tbb[6].idCommand = IDC_TB_SETTINGS; 
tbb[6].fsState = TBSTATE_ENABLED; 
tbb[6].fsStyle = BTNS_BUTTON; 
tbb[6].dwData = 0; 
tbb[6].iString = -1;
 
tbb[7].iBitmap = 7; 
tbb[7].idCommand = IDC_TB_CALC; 
tbb[7].fsState = TBSTATE_ENABLED; 
tbb[7].fsStyle = BTNS_BUTTON; 
tbb[6].dwData = 0; 
tbb[7].iString = -1;

The code fragment is far not complete. More than half of it was cut out. The fragment was being written through copying and editing the code. No wonder that an incorrect index was lost in such a large fragment. The analyzer generates the following diagnostic message: "The code containing the collection of similar blocks. Check items '0', '1', '2', '3', '4', '5', '6', '6' in lines 589, 596, 603, 610, 617, 624, 631, 638". If we review these lines, we will find and correct the index '6' repeated twice. This is the correct code:

tbb[7].iBitmap = 7; 
tbb[7].idCommand = IDC_TB_CALC; 
tbb[7].fsState = TBSTATE_ENABLED; 
tbb[7].fsStyle = BTNS_BUTTON; 
tbb[7].dwData = 0; 
tbb[7].iString = -1;

The second sample:

pPopup->EnableMenuItem(
  ID_CONTEXT_EDITTEXT,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_CLOSEALL, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_CLOSE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_SAVELAYOUT, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_RESIZE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_REFRESH, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_EDITTEXT, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_SAVE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_EDITIMAGE,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_CLONE,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);

It is very difficult to find an error in this code while reviewing it. But there is an error here: the state of the same menu item 'ID_CONTEXT_EDITTEXT' is modified twice. Let's mark the two repeated lines:

------------------------------
pPopup->EnableMenuItem(
  ID_CONTEXT_EDITTEXT,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
------------------------------
pPopup->EnableMenuItem(
  ID_CONTEXT_CLOSEALL, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_CLOSE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_SAVELAYOUT, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_RESIZE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_REFRESH, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
------------------------------
pPopup->EnableMenuItem(
  ID_CONTEXT_EDITTEXT, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
------------------------------
pPopup->EnableMenuItem(
  ID_CONTEXT_SAVE, MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_EDITIMAGE,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);
pPopup->EnableMenuItem(
  ID_CONTEXT_CLONE,MF_GRAYED|MF_DISABLED|MF_BYCOMMAND);

Maybe it is a small error and one of the lines is just unnecessary. Or maybe the programmer forgot to change the state of some other menu item.

Unfortunately, the analyzer often makes a mistake while carrying out this diagnosis and generates false alarms. This is an example of code causing a false alarm:

switch (i) {
  case 0: f1 = 2; f2 = 3; break;
  case 1: f1 = 0; f2 = 3; break;
  case 2: f1 = 1; f2 = 3; break;
  case 3: f1 = 1; f2 = 2; break;
  case 4: f1 = 2; f2 = 0; break;
  case 5: f1 = 0; f2 = 1; break;
}

The analyzer does not like a correct column of numbers: 2, 0, 1, 1, 2, 0. In such cases, you may enable the warning suppression mechanism by typing the comment //-V525 in the end of the line:

switch (i) {
  case 0: f1 = 2; f2 = 3; break; //-V525
  case 1: f1 = 0; f2 = 3; break;
  case 2: f1 = 1; f2 = 3; break;
  case 3: f1 = 1; f2 = 2; break;
  case 4: f1 = 2; f2 = 0; break;
  case 5: f1 = 0; f2 = 1; break;
}

If there are too many false alarms, you may disable this diagnostic rule in the analyzer's settings. We will also appreciate if you write to our support service about cases when false alarms are generated and we will try to improve the diagnosis algorithm. Please attach corresponding code fragments to your letters.

You can look at examples of errors from real projects which were detected by this diagnostic message.