1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" 2 "http://www.w3.org/TR/html4/strict.dtd"> 3 <html> 4 <head> 5 <title>List of potential checkers</title> 6 <link type="text/css" rel="stylesheet" href="content.css"> 7 <link type="text/css" rel="stylesheet" href="menu.css"> 8 <script type="text/javascript" src="scripts/menu.js"></script> 9 <script type="text/javascript" src="scripts/dbtree.js"></script> 10 </head> 11 <body> 12 13 <div id="page"> 14 15 <!-- menu --> 16 <!--#include virtual="menu.html.incl"--> 17 <!-- page content --> 18 <div id="content"> 19 <h1>List of potential checkers</h1> 20 21 <p>This page contains a list of potential checkers to implement in the static analyzer. If you are interested in contributing to the analyzer's development, this is a good resource to help you get started. The specific names of the checkers are subject to review, and are provided here as suggestions.</p> 22 23 <!-- ========================= allocation/deallocation ======================= --> 24 <h3>allocation/deallocation</h3> 25 <table class="checkers"> 26 <col class="namedescr"><col class="example"><col class="progress"> 27 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 28 29 <tr><td><span class="name">memory.LeakNeverReleased<br> 30 (C, C++)</span><br><br> 31 Memory may be never released, potential leak of memory 32 </td><td> 33 <pre> 34 #include <stdlib.h> 35 36 int f() {}; 37 38 void test() { 39 int *p1 = (int*)malloc(sizeof(int)); // warn 40 int *p2 = new int; // warn 41 int x = f(); 42 if (x==1) 43 return; 44 delete p2; 45 } 46 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15237">PR15237</a> 47 </td></tr> 48 49 <tr><td><span class="name">memory.MismatchedFree 50 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> 51 Mismatched deallocation function is used 52 </td><td><pre> 53 #include <stdlib.h> 54 55 void test() { 56 int *p1 = new int; 57 int *p2 = new int[1]; 58 59 free(p1); // warn 60 free(p2); // warn 61 } 62 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15238">PR15238</a> 63 </td></tr> 64 65 <tr><td><span class="name">memory.MismatchedDelete 66 <br>(C, C++)</span><br><br> 67 Mismatched deallocation function is used 68 </td><td><pre> 69 #include <stdlib.h> 70 71 void test() { 72 int *p1 = new int; 73 int *p2 = new int[1]; 74 int *p3 = (int*)malloc(sizeof(int)); 75 76 delete[] p1; // warn 77 delete p2; // warn 78 delete p3; // warn 79 } 80 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15238">PR15238</a> 81 </td></tr> 82 83 <tr><td><span class="name">memory.MultipleDelete 84 <br>(C++)</span><br><br> 85 Attempt to deallocate released memory 86 </td><td><pre> 87 #include <new> 88 89 void test() { 90 int *p1 = new int; 91 int *p2 = new(p1) int; 92 int *p3 = p1; 93 delete p1; 94 delete p1; // warn 95 delete p2; // warn 96 delete p3; // warn 97 } 98 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15237">PR15237</a> 99 </td></tr> 100 101 102 <tr><td><span class="name">memory.LeakPtrValChanged 103 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> 104 Potential memory leak: a pointer to newly allocated data loses its original 105 value 106 </td><td><pre> 107 #include <stdlib.h> 108 109 void f(const int *); 110 void g(int *); 111 112 void test() { 113 int *p1 = new int; 114 p1++; // warn 115 int *p2 = (int *)malloc(sizeof(int)); 116 p2 = p1; // warn 117 int *p3 = new int; 118 f(p3); 119 p3++; // warn 120 int *p4 = new int; 121 f(p4); 122 p4++; // ok 123 } 124 </pre></td><td class="aligned">done at r174678 (C case) 125 </td></tr> 126 127 128 <tr><td><span class="name">memory.DeallocateNonPtr 129 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> 130 Deallocation function is applied to non-pointer 131 </td><td><pre> 132 #include <stdlib.h> 133 134 class A { 135 int *p; 136 public: 137 operator int *() { return p; } 138 }; 139 140 void test() { 141 A a; 142 delete a; // warn 143 free(a); // warn 144 const char *s = "text"; 145 delete s; // warn 146 free(s); // warn 147 } 148 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15237">PR15237</a> 149 </td></tr> 150 151 152 <tr><td><span class="name">memory.LeakEvalOrder<br> 153 (C, C++)</span><br><br> 154 Potential memory leak: argument evaluation order is undefined, g() may never be called 155 </td><td><pre> 156 #include <stdlib.h> 157 158 void f1(int, int); 159 void f2(int*, int*); 160 int g(int *) { throw 1; }; 161 int h(); 162 163 void test() { 164 f1(g(new int), h()); // warn 165 f1(g((int *)malloc(sizeof(int))), h()); // warn 166 f2(new int, new int); 167 } 168 </pre></td><td class="aligned"></td></tr> 169 170 <tr><td><span class="name">memory.DstBufferTooSmall 171 <br>(C, C++)</span><br><br> 172 Destination buffer too small 173 </td><td><pre> 174 #include <string.h> 175 176 void test() { 177 const char* s1 = "abc"; 178 char *s2 = new char; 179 strcpy(s2, s1); // warn 180 181 int* p1 = new int[3]; 182 int* p2 = new int; 183 memcpy(p2, p1, 3); // warn 184 } 185 </pre></td><td class="aligned"></td></tr> 186 187 <tr><td><span class="name">memory.NegativeArraySize 188 <br>enhancement to experimental.security.MallocOverflow<br>(C, C++) 189 </span><br><br> 190 'n' is used to specify the buffer size may be negative 191 </td><td><pre> 192 #include <stdlib.h> 193 194 void test() { 195 int *p; 196 int n1 = -1; 197 p = new int[n1]; // warn 198 } 199 </pre></td><td class="aligned"></td></tr> 200 201 </table> 202 203 <!-- ======================= constructors/destructors ====================== --> 204 <h3>constructors/destructors</h3> 205 <table class="checkers"> 206 <col class="namedescr"><col class="example"><col class="progress"> 207 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 208 209 <tr><td><span class="name">ctordtor.ExptInsideDtorExplicit<br> 210 (C++)</span><br><br> 211 It is dangerous to let an exception leave a destructor. Using try..catch will 212 solve the problem. 213 </td><td><pre> 214 void f(); 215 216 class A { 217 A() {} 218 ~A() { throw 1; } // warn 219 }; 220 </pre></td><td class="aligned"></td></tr> 221 222 <tr><td><span class="name">ctordtor.ExptInsideDtorImplicit<br> 223 (C++)</span><br><br> 224 Calls to functions inside a destructor that are known to throw exceptions is 225 dangerous. Using try..catch will solve the problem. 226 </td><td><pre> 227 void f() { throw 1; }; 228 229 class A { 230 A() {} 231 ~A() { f(); } // warn 232 }; 233 </pre></td><td class="aligned"></td></tr> 234 235 </table> 236 237 <!-- ============================== exceptions ============================= --> 238 <h3>exceptions</h3> 239 <table class="checkers"> 240 <col class="namedescr"><col class="example"><col class="progress"> 241 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 242 243 <tr><td><span class="name">exceptions.ThrowSpecButNotThrow 244 <br>(C++)</span><br><br> 245 Function prototype has throw(T) specifier but the function do not throw 246 </td><td><pre> 247 void f() throw(int) { // warn 248 } 249 </pre></td><td class="aligned"></td></tr> 250 251 <tr><td><span class="name">exceptions.NoThrowSpecButThrows 252 <br>(C++)</span><br><br> 253 An exception is throw from a function having the throw() specifier 254 </td><td><pre> 255 void f() throw() { 256 throw(1); // warn 257 } 258 </pre></td><td class="aligned"></td></tr> 259 260 <tr><td><span class="name">exceptions.ThrownTypeDiffersSpec 261 <br>(C++)</span><br><br> 262 The type of a thrown exception differs from those specified in the throw(T) 263 specifier 264 </td><td><pre> 265 struct S{}; 266 void f() throw(int) { 267 S s; 268 throw (s); // warn 269 } 270 </pre></td><td class="aligned"></td></tr> 271 272 </table> 273 274 <!-- ========================= smart pointers ============================== --> 275 <h3>smart pointers</h3> 276 <table class="checkers"> 277 <col class="namedescr"><col class="example"><col class="progress"> 278 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 279 280 <tr><td><span class="name">smartptr.SmartPtrInit<br> 281 (C++)</span><br><br> 282 C++03: auto_ptr should store a pointer to an object obtained via new as allocated 283 memory will be cleaned using delete<br> 284 C++11: one should use unique_ptr<T[]> to keep a pointer to memory 285 allocated by new[]<br> 286 C++11: to keep a pointer to memory allocated by new[] in a shared_ptr one 287 should use a custom deleter that calls delete[] 288 </td><td><pre> 289 #include <stdlib.h> 290 #include <memory> 291 292 void test() { 293 std::auto_ptr<int> p1(new int); // Ok 294 std::auto_ptr<int> p2(new int[3]); // warn 295 std::auto_ptr<int> 296 p3((int *)malloc(sizeof(int))); // warn 297 } 298 </pre></td><td class="aligned"></td></tr> 299 300 </table> 301 302 <!-- ========================= undefined behavior ========================== --> 303 <h3>undefined behavior</h3> 304 <table class="checkers"> 305 <col class="namedescr"><col class="example"><col class="progress"> 306 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 307 308 <tr><td><span class="name">undefbehavior.ExitInDtor 309 <br>(C++)</span><br><br> 310 Undefined behavior: std::exit is called to end the program during the 311 destruction of an object with static storage duration 312 </td><td><pre> 313 #include <cstdlib> 314 315 class A { 316 public: 317 ~A() { 318 std::exit(1); // warn 319 } 320 }; 321 322 A a; 323 </pre></td><td class="aligned"></td></tr> 324 325 <tr><td><span class="name">undefbehavior.LocalStaticDestroyed 326 <br>(C++)</span><br><br> 327 Undefined behavior: function containing a definition of static local object is 328 called during the destruction of an object with static storage duration so that 329 flow of control passes through the definition of the previously destroyed 330 static local object 331 </td><td><pre> 332 void f(); 333 334 class A { 335 public: 336 ~A() { 337 f(); // warn 338 } 339 }; 340 341 class B {}; 342 343 A a; 344 345 void f() { 346 static B b; // <- 347 } 348 </pre></td><td class="aligned"></td></tr> 349 350 <tr><td><span class="name">undefbehavior.UseAfterRelease 351 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> 352 Pointer to deleted object is referenced (The effect of using an invalid pointer 353 value is undefined) 354 </td><td><pre> 355 #include <stdlib.h> 356 357 void test() { 358 int *p = new int; 359 delete p; 360 int i = *p; // warn 361 } 362 363 </pre></td><td class="aligned"></td></tr> 364 365 <tr><td><span class="name">undefbehavior.ZeroAllocDereference 366 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br> 367 The effect of dereferencing a pointer returned as a request for zero size is 368 undefined 369 </td><td><pre> 370 #include <stdlib.h> 371 372 int *p = new int[0]; 373 int i = p[0]; // warn 374 </pre></td><td class="aligned"></td></tr> 375 376 <tr><td><span class="name">undefbehavior.DeadReferenced 377 <br>(C++)</span><br><br> 378 Undefined behavior: the following usage of the pointer to the object whose 379 lifetime has ended can result in undefined behavior 380 </td><td><pre> 381 // C++03 382 #include <new> 383 384 class A { 385 public: 386 int i; 387 void f() {}; 388 }; 389 390 class B : public A { 391 }; 392 393 void test() { 394 B *b = new B; 395 new(b) A; 396 b->i; // warn 397 b->f(); // warn 398 static_cast<A*>(b); // warn 399 dynamic_cast<A*>(b); // warn 400 delete b; // warn 401 } 402 403 // C++11 404 #include <new> 405 406 class A { 407 public: 408 int i; 409 void f() {}; 410 }; 411 412 class B : public A { 413 public: 414 ~B() {}; 415 }; 416 417 void test() { 418 A *a = new A; 419 new(a) B; 420 a->i; // warn 421 a->f(); // warn 422 B *b = new B; 423 new(b) A; 424 b->i; // warn 425 b->f(); // warn 426 static_cast<A*>(b); // warn 427 dynamic_cast<A*>(b); // warn 428 delete b; // warn 429 } 430 </pre></td><td class="aligned"></td></tr> 431 432 <tr><td><span class="name">undefbehavior.ObjLocChanges 433 <br>(C++)</span><br><br> 434 Undefined behavior: the program must ensure that an object occupies the same 435 storage location when the implicit or explicit destructor call takes place 436 </td><td><pre> 437 #include <new> 438 439 class T { }; 440 struct B { 441 ~B(); 442 }; 443 444 void test() { 445 B *b1 = new B; 446 B b2; 447 new (b1) T; 448 new (&b2) T; 449 delete b1; // warn 450 } // warn 451 </pre></td><td class="aligned"></td></tr> 452 453 <tr><td><span class="name">undefbehavior.ExprEvalOrderUndef 454 <br>(C, C++03)</span><br><br> 455 Undefined behavior: a scalar object shall have its stored value modified at 456 most once by the evaluation of an expression 457 </td><td><pre> 458 void test () { 459 int i = 0; 460 int v[1] = {0}; 461 i = v[i++]; // warn 462 i = ++i + 1; // warn 463 } 464 </pre></td><td class="aligned"></td></tr> 465 466 <tr><td><span class="name">undefbehavior.StaticInitReentered 467 <br>(C)</span><br><br> 468 Undefined behavior: static declaration is re-entered while the object is being 469 initialized 470 </td><td><pre> 471 int test(int i) { 472 static int s = test(2*i); // warn 473 return i+1; 474 } 475 </pre></td><td class="aligned"></td></tr> 476 477 <tr><td><span class="name">undefbehavior.ConstModified 478 <br>(C, C++)</span><br><br> 479 Undefined behavior: const object is being modified 480 </td><td><pre> 481 #include <stdlib.h> 482 483 class X { 484 public : 485 mutable int i; 486 int j; 487 }; 488 class Y { 489 public : 490 X x; 491 Y(); 492 }; 493 494 void test() { 495 const int *ciq = 496 (int *)malloc(sizeof(int)); 497 int *iq = const_cast<int *>(ciq); 498 *iq = 1; // warn 499 500 const Y y; 501 Y* p = const_cast<Y*>(&y); 502 p->x.i = 1; // ok 503 p->x.j = 1; // warn 504 } 505 </pre></td><td class="aligned"></td></tr> 506 507 <tr><td><span class="name">undefbehavior.DeadDestructed 508 <br>(C++)</span><br><br> 509 Undefined behavior: the destructor is invoked for an object whose lifetime 510 has ended 511 </td><td><pre> 512 class A { 513 public: 514 void f() {}; 515 A() {}; 516 ~A() {}; 517 }; 518 519 void test() { 520 A a; 521 a.~A(); 522 } // warn 523 </pre></td><td class="aligned"></td></tr> 524 525 <tr><td><span class="name">undefbehavior.MethodCallBeforeBaseInit 526 <br>(C++)</span><br><br> 527 Undefined behavior: calls member function but base not yet initialized 528 </td><td><pre> 529 class A { 530 public : 531 A(int ); 532 }; 533 class B : public A { 534 public : 535 int f(); 536 B() : A(f()) {} // warn 537 }; 538 </pre></td><td class="aligned"></td></tr> 539 540 <tr><td><span class="name">undefbehavior.MemberOrBaseRefBeforeCtor 541 <br>(C++)</span><br><br> 542 C++ Undefined behavior: non-static member or base class of non-POD class type 543 is referred before constructor begins execution<br> 544 C++11 Undefined behavior: non-static member or base class of a class with a 545 non-trivial constructor is referred before constructor begins execution 546 </td><td><pre> 547 // C++03 548 struct POD { 549 int i; 550 }; 551 552 struct non_POD : public POD { 553 int j; 554 POD pod; 555 }; 556 557 extern POD pod; 558 extern non_POD non_pod; 559 560 int *p1 = &non_pod.j; // warn 561 int *p2 = &non_pod.pod.i; // warn 562 int *p3 = &pod.i; // ok 563 POD *p4 = &non_pod; // warn 564 565 POD a; 566 non_POD b; 567 568 struct S { 569 int *k; 570 non_POD non_pod; 571 S() : k(&non_pod.j) {} // warn 572 }; 573 574 // C++11 575 struct trivial { 576 int i; 577 }; 578 579 struct non_trivial: public trivial { 580 non_trivial() {}; 581 int j; 582 trivial pod; 583 }; 584 585 extern trivial t; 586 extern non_trivial nt; 587 588 int *p1 = &nt.j; // warn 589 int *p2 = &nt.i; // warn 590 int *p3 = &t.i; // ok 591 trivial *p4 = &nt; 592 593 trivial t; 594 non_trivial nt; 595 596 struct S { 597 int *k; 598 non_trivial nt; 599 S() : k(&nt.j) {} // warn 600 }; 601 </pre></td><td class="aligned"></td></tr> 602 603 <tr><td><span class="name">undefbehavior.MemberRefAfterDtor 604 <br>(C++)</span><br><br> 605 C++03: Undefined behavior: non-static member of non-POD class type is referred 606 after destructor ends execution<br> 607 C++11: Undefined behavior: non-static member of a class with a non-trivial 608 destructor is referred after destructor ends execution 609 </td><td><pre> 610 // C++03 611 struct non_POD { 612 virtual void f() {}; 613 }; 614 615 void test() { 616 non_POD *non_pod = new non_POD(); 617 non_pod->~non_POD(); 618 non_pod->f(); // warn 619 } 620 621 // C++11 622 struct S { 623 ~S() {}; 624 void f() {}; 625 }; 626 627 void test() { 628 S *s = new S(); 629 s->~S(); 630 s->f(); // warn 631 } 632 </pre></td><td class="aligned"></td></tr> 633 634 <tr><td><span class="name">undefbehavior.CtorForeignCall 635 <br>(C++)</span><br><br> 636 Undefined behavior: call to virtual function of an object under construction 637 whose type is neither the constructors own class or one of its bases 638 </td><td><pre> 639 class A { 640 public: 641 virtual void f() {}; 642 }; 643 644 class B { 645 public: 646 B(A* a) { a->f(); } // warn 647 }; 648 649 class C : public A, B { 650 public: 651 C() : B((A*)this) {} 652 }; 653 </pre></td><td class="aligned"></td></tr> 654 655 <tr><td><span class="name">undefbehavior.CtorForeignCast 656 undefbehavior.CtorForeignTypeid 657 <br>(C++)</span><br><br> 658 Undefined behavior: the operand of typeid/dynamic_cast is an object under 659 construction whose type is neither the constructors own class or one of its 660 bases 661 </td><td><pre> 662 #include <typeinfo> 663 664 class A { 665 public: 666 virtual void f() {}; 667 }; 668 669 class B { 670 public: 671 B(A* a) { 672 typeid(*a); // warn 673 dynamic_cast<B*>(a); //warn 674 } 675 }; 676 677 class C : public A, B { 678 public: 679 C() : B((A*)this) {} 680 }; 681 </pre></td><td class="aligned"></td></tr> 682 683 <tr><td><span class="name">undefbehavior.MemberRefInCatch 684 undefbehavior.BaseRefInCatch 685 <br>(C++)</span><br><br> 686 Undefined behavior: referring to any non-static member or base class of an 687 object in the handler for a function-try-block of a constructor or destructor 688 for that object results in undefined behavior 689 </td><td><pre> 690 class C { 691 int i; 692 public : 693 C() 694 try 695 : i(1) {} 696 catch (...) 697 { 698 i=2; // warn 699 } 700 }; 701 </pre></td><td class="aligned"></td></tr> 702 703 <tr><td><span class="name">undefbehavior.ReturnAtCatchEnd 704 <br>(C++)</span><br><br> 705 Undefined behavior: a function returns when control reaches the end of a 706 handler. This results in undefined behavior in a value-returning 707 function 708 </td><td><pre> 709 int test() try { 710 } 711 catch(int) { 712 } // warn 713 </pre></td><td class="aligned"></td></tr> 714 715 <tr><td><span class="name">undefbehavior.AutoptrsOwnSameObj 716 <br>(C++03)</span><br><br> 717 Undefined behavior: if more than one auto_ptr owns the same object at the same 718 time the behavior of the program is undefined. 719 </td><td><pre> 720 #include <memory> 721 722 void test() { 723 int *data = new int; 724 std::auto_ptr<int> p(data); 725 std::auto_ptr<int> q(data); // warn 726 } 727 </pre></td><td class="aligned"></td></tr> 728 729 <tr><td><span class="name">undefbehavior.BasicStringBoundAccess 730 <br>(C++03)</span><br><br> 731 Undefined behavior: out-of-bound basic_string access 732 </td><td><pre> 733 void test() { 734 std::basic_string<char> s; 735 char c = s[10]; // warn 736 } 737 </pre></td><td class="aligned"></td></tr> 738 739 <tr><td><span class="name">undefbehavior.BasicStringBoundModification 740 <br>(C++)</span><br><br> 741 Undefined behavior: out-of-bound basic_string modification 742 </td><td><pre> 743 void test() { 744 std::basic_string<char> s; 745 s[10] = 0; // warn 746 } 747 </pre></td><td class="aligned"></td></tr> 748 749 <tr><td><span class="name">undefbehavior.EosDereference 750 <br>(C++)</span><br><br> 751 Undefined behavior: the result of operator*() on an end of stream is 752 undefined 753 </td><td><pre> 754 #include <vector> 755 756 void test() { 757 std::vector<int> v; 758 int i = *v.end(); // warn 759 *v.end() = 0; // warn 760 } 761 </pre></td><td class="aligned"></td></tr> 762 763 <tr><td><span class="name">undefbehavior.QsortNonPOD 764 undefbehavior.QsortNonTrivial 765 <br>C++</span><br><br> 766 C++03: Undefined behavior: the objects in the array passed to qsort are of 767 non-POD type<br> 768 C++11: Undefined behavior: the objects in the array passed to qsort are of 769 non-trivial type 770 </td><td><pre> 771 // C++03 772 #include <cstdlib> 773 774 struct non_POD { 775 int i; 776 non_POD(int ii) : i(ii) {} 777 }; 778 779 non_POD values[] = { non_POD(2), non_POD(1) }; 780 781 int compare(const void *a, 782 const void *b) { 783 return ( (*(non_POD*)a).i - 784 (*(non_POD*)b).i ); 785 } 786 787 void test() { 788 qsort(values, 2, sizeof(non_POD), 789 compare); // warn 790 } 791 792 // C++11 793 #include <cstdlib> 794 795 struct S {}; 796 797 struct trivial_non_POD : public S { 798 int i; 799 }; 800 801 struct non_trivial { 802 int i; 803 non_trivial() {} 804 }; 805 806 trivial_non_POD tnp[2]; 807 non_trivial nt[2]; 808 809 int compare1(const void *a, 810 const void *b) { 811 return ( (*(trivial_non_POD *)a).i - 812 (*(trivial_non_POD *)b).i ); 813 } 814 815 int compare2(const void *a, 816 const void *b) { 817 return ( (*(non_trivial *)a).i - 818 (*(non_trivial *)b).i ); 819 } 820 821 void test() { 822 qsort(tnp, 2, sizeof(trivial_non_POD), 823 compare1); // ok 824 qsort(nt, 2, sizeof(non_trivial), 825 compare2); // warn 826 } 827 </pre></td><td class="aligned"></td></tr> 828 829 <tr><td><span class="name">undefbehavior.ThrowWhileCopy 830 <br>C++</span><br><br> 831 Undefined behavior: copy constructor/assignment operator can throw an exception. 832 The effects are undefined if an exception is thrown. 833 </td><td><pre> 834 struct S { 835 int i, j; 836 S (const S &s) { 837 i = s.i; 838 throw 1; // warn 839 j = s.j; 840 }; 841 S &operator=(const S &s) { 842 i = s.i; 843 throw 1; // warn 844 j = s.j; 845 } 846 }; 847 </pre></td><td class="aligned"></td></tr> 848 849 <tr><td><span class="name">undefbehavior.ValarrayArgBound 850 <br>(C++)</span><br><br> 851 Undefined behavior: the value of the second argument is greater than the number 852 of values pointed to by the first argument 853 </td><td><pre> 854 #include <valarray> 855 856 struct S { 857 int i; 858 S(int ii) : i(ii) {}; 859 }; 860 861 void test(void) { 862 S s[] = { S(1), S(2) }; 863 std::valarray<S> v(s,3); // warn 864 } 865 </pre></td><td class="aligned"></td></tr> 866 867 <tr><td><span class="name">undefbehavior.ValarrayLengthDiffer 868 <br>(C++)</span><br><br> 869 Undefined behavior: valarray operands are of different length 870 </td><td><pre> 871 // C++03 872 #include <valarray> 873 874 void test(void) { 875 std::valarray<int> a(0, 1), b(0, 2); 876 std::valarray<bool> c(false, 1); 877 a = b; // warn 878 a *= b; // warn 879 a = a * b; // warn 880 c = a == b; // warn 881 b.resize(1); 882 a = b; // OK 883 } 884 885 // C++11 886 #include <valarray> 887 888 void test(void) { 889 std::valarray<int> a(0, 1), b(0, 2); 890 std::valarray<bool> c(false, 1); 891 a = b; // ok 892 a *= b; // ok 893 a = a * b; // warn 894 c = a == b; // warn 895 b.resize(1); 896 a = b; // OK 897 } 898 </pre></td><td class="aligned"></td></tr> 899 900 <tr><td><span class="name">undefbehavior.ValarrayZeroLength 901 <br>(C++)</span><br><br> 902 Undefined behavior: calling sum()/min()/max() method of an array having zero 903 length, the behavior is undefined 904 </td><td><pre> 905 #include <valarray> 906 907 void test(void) { 908 std::valarray<int> v(0, 0); 909 v.sum(); // warn 910 v.min(); // warn 911 v.max(); // warn 912 } 913 </pre></td><td class="aligned"></td></tr> 914 915 <tr><td><span class="name">undefbehavior.ValarrayBadIndirection 916 <br>(C++)</span><br><br> 917 Undefined behavior: element N is specified more than once in the 918 indirection 919 </td><td><pre> 920 #include <valarray> 921 922 void test() { 923 size_t addr[] = {0, 1, 1}; // N is 1 924 std::valarray<size_t>indirect(addr, 3); 925 std::valarray<int> a(0, 5), b(1, 3); 926 a[indirect] = b; //warn 927 a[indirect] *= b; //warn 928 } 929 </pre></td><td class="aligned"></td></tr> 930 931 <tr><td><span class="name">undefbehavior.IosBaseDestroyedBeforeInit 932 <br>(C++)</span><br> 933 <br>Undefined behavior: ios_base object is destroyed before initialization have 934 taken place. basic_ios::init should be call to initialize ios_base 935 members 936 </td><td><pre> 937 #include <ios> 938 939 using namespace std; 940 template <class T, class Traits = std::char_traits<T>> 941 class my_stream1 : public std::basic_ios<T, Traits> { 942 }; 943 944 template <class T, class Traits = std::char_traits<T>> 945 class my_stream2 : public std::basic_ios<T, Traits> { 946 class my_streambuf : public std::basic_streambuf<T, Traits> { 947 }; 948 public: 949 my_stream2() { 950 this->init(new my_streambuf); 951 } 952 }; 953 954 void test() { 955 my_stream1<char> *p1 = new my_stream1<char> 956 my_stream2<char> *p2 = new my_stream2<char> 957 delete p1; // warn 958 delete p2; // ok 959 } 960 </pre></td><td class="aligned"></td></tr> 961 962 <tr><td><span class="name">undefbehavior.IosBaseUsedBeforeInit 963 <br>(C++11)</span><br><br> 964 Undefined behavior: ios_base object is used before initialization have taken 965 place. basic_ios::init should be call to initialize ios_base members 966 </td><td><pre> 967 #include <ios> 968 969 using namespace std; 970 template <class T, class Traits = std::char_traits<T>> 971 class my_stream1 : public std::basic_ios<T, Traits> { 972 }; 973 974 template <class T, class Traits = std::char_traits<T>> 975 class my_stream2 : public std::basic_ios<T, Traits> { 976 class my_streambuf : public std::basic_streambuf<T, Traits> { 977 }; 978 public: 979 my_stream2() { 980 this->init(new my_streambuf); 981 } 982 }; 983 984 void test() { 985 my_stream1<char> *p1 = new my_stream1<char> 986 my_stream2<char> *p2 = new my_stream2<char> 987 p1->narrow('a', 'b'); // warn 988 p2->narrow('a', 'b'); // ok 989 delete p1; // warn 990 delete p2; // ok 991 } 992 </pre></td><td class="aligned"></td></tr> 993 994 <tr><td><span class="name">undefbehavior.MinusOnePosType 995 <br>(C++)</span><br><br> 996 Undefined behavior: passing -1 to any streambuf/istream/ostream member that 997 accepts a value of type traits::pos_type result in undefined behavior 998 </td><td><pre> 999 #include <fstream> 1000 1001 class my_streambuf : public std::streambuf { 1002 void f() { 1003 seekpos(-1); // warn 1004 } 1005 }; 1006 1007 void test() { 1008 std::filebuf fb; 1009 std::istream in(&fb); 1010 std::ostream out(&fb); 1011 std::filebuf::off_type pos(-1); 1012 in.seekg(pos); // warn 1013 out.seekp(-1); // warn 1014 } 1015 </pre></td><td class="aligned"></td></tr> 1016 </table> 1017 1018 <!-- ============================ different ================================ --> 1019 <h3>different</h3> 1020 <table class="checkers"> 1021 <col class="namedescr"><col class="example"><col class="progress"> 1022 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr> 1023 </thead> 1024 1025 <tr><td><span class="name">different.ArgEvalOrderUndef 1026 <br>(C)</span><br><br> 1027 Errors because of the order of evaluation of function arguments is undefined 1028 </td><td><pre> 1029 void f(int, int); 1030 1031 void test() { 1032 int i = 0; 1033 int v[1] = {0}; 1034 f(v[i], i++); // warn 1035 } 1036 </pre></td><td class="aligned"></td></tr> 1037 1038 <tr><td><span class="name">different.IdenticalExprBinOp 1039 <br>(C)</span><br><br> 1040 There are identical sub-expressions to the left and to the right of the 1041 operator 1042 </td><td><pre> 1043 #define A 1 1044 #define B 1 1045 1046 bool isNan(double d) { 1047 return d != d; // ok 1048 } 1049 1050 int f(); 1051 1052 void test() { 1053 int i = 0; 1054 if (i != 0 && i != 0) {} // warn 1055 1056 if(i == A || i == B) {} // ok 1057 1058 if (++i != 0 && ++i != 0) {} // ok 1059 1060 if (f() && f()) {} // ok 1061 } 1062 </pre></td><td class="aligned"></td></tr> 1063 1064 <tr><td><span class="name">different.FuncPtrInsteadOfCall 1065 <br>(C)</span><br><br> 1066 Possibly a function call should be used instead of a pointer to function 1067 </td><td><pre> 1068 int f(); 1069 1070 void test() { 1071 if (f == 0) {} // warn 1072 } 1073 </pre></td><td class="aligned"></td></tr> 1074 1075 <tr><td><span class="name">different.IdenticalCondIfElseIf 1076 <br>(C)</span><br><br> 1077 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a 1078 probability of logical error presence 1079 </td><td><pre> 1080 void test() { 1081 int i = 7; 1082 if (i == 1) {} 1083 else if (i == 1) {} // warn 1084 } 1085 </pre></td><td class="aligned"></td></tr> 1086 1087 <tr><td><span class="name">SuccessiveAssign 1088 <br>(C)</span><br><br> 1089 Successive assign to a variable 1090 </td><td><pre> 1091 void test() { 1092 int i=0; 1093 i=1; 1094 i=2; // warn 1095 } 1096 </pre></td><td class="aligned"></td></tr> 1097 1098 <tr><td><span class="name">different.NullDerefStmtOrder 1099 <br>enhancement to core.NullDereference<br>(C)</span><br><br> 1100 Dereferencing of the null pointer might take place. Checking the pointer for 1101 null should be performed first 1102 </td><td><pre> 1103 struct S { 1104 int x; 1105 }; 1106 1107 S* f(); 1108 1109 void test() { 1110 S *p1 = f(); 1111 int x1 = p1->x; // warn 1112 if (p1) {}; 1113 1114 S *p2 = f(); 1115 int x2 = p2->x; // ok 1116 } 1117 </pre></td><td class="aligned"></td></tr> 1118 1119 <tr><td><span class="name">different.NullDerefCondOrder 1120 <br>enhancement to core.NullDereference<br>(C)</span><br><br> 1121 Dereferencing of the null pointer might take place. Checking the pointer for 1122 null should be performed first 1123 </td><td><pre> 1124 struct S{bool b;}; 1125 1126 S* f(); 1127 1128 void test() { 1129 S *p = f(); 1130 if (p->b && p) {}; // warn 1131 } 1132 </pre></td><td class="aligned"></td></tr> 1133 1134 <tr><td><span class="name">different.IdenticalStmtThenElse 1135 <br>(C)</span><br><br> 1136 The 'else' statement is equivalent to the 'then' statement 1137 </td><td><pre> 1138 void test() { 1139 int i; 1140 if (i==1) { 1141 i++; 1142 } 1143 else { // warn 1144 i++; 1145 } 1146 } 1147 </pre></td><td class="aligned"></td></tr> 1148 1149 <tr><td><span class="name">different.MultipleAccessors 1150 <br>(C++)</span><br><br> 1151 multiple accessors met for 'class::field' 1152 </td><td><pre> 1153 class A { 1154 int i; 1155 int j; 1156 public: 1157 int getI() { return i; } 1158 int getJ() { return i; } // warn 1159 void setI(int& ii) { i = ii; } 1160 void setJ(int& jj) { i = jj; } // warn 1161 }; 1162 </pre></td><td class="aligned"></td></tr> 1163 1164 <tr><td><span class="name">different.AccessorsForPublic 1165 <br>(C++)</span><br><br> 1166 Accessors exist for 'class::field'. Should this field really be public? 1167 </td><td><pre> 1168 class A { 1169 public: 1170 int i; // warn 1171 int getI() { return i; } 1172 void setI(int& ii) { i = ii; } 1173 }; 1174 </pre></td><td class="aligned"></td></tr> 1175 1176 <tr><td><span class="name">different.LibFuncResultUnised 1177 <br>(C, C++)</span><br><br> 1178 Calling 'f' ignoring its return value is of no use (* create the list of known 1179 system/library/API functions falling into this category) 1180 </td><td><pre> 1181 #include <vector> 1182 1183 void test() { 1184 std::vector<int> v; 1185 v.empty(); // warn 1186 } 1187 </pre></td><td class="aligned"></td></tr> 1188 1189 <tr><td><span class="name">different.WrongVarForStmt 1190 <br>(C, C++)</span><br><br> 1191 Possibly wrong variable is used in the loop/cond-expression of the 'for' 1192 statement. Did you mean 'proper_variable_name'? 1193 </td><td><pre> 1194 void test() { 1195 int i; 1196 int j; 1197 for (j=0; j<3; ++i); // warn 1198 for (int j=0; i<3; ++j); // warn 1199 } 1200 </pre></td><td class="aligned"></td></tr> 1201 1202 <tr><td><span class="name">different.FloatingCompare 1203 <br>(C)</span><br><br> 1204 Comparing floating point numbers may be not precise 1205 </td><td><pre> 1206 #include <math.h> 1207 1208 void test() { 1209 double b = sin(M_PI / 6.0); 1210 if (b == 0.5) // warn 1211 b = 0; 1212 } 1213 </pre></td><td class="aligned"></td></tr> 1214 1215 <tr><td><span class="name">different.BoolCompare 1216 <br>maybe merge with experimental.core.BoolAssignment<br>(C, C++)</span><br><br> 1217 Comparing boolean to a value other then 0 or 1 1218 </td><td><pre> 1219 void test() { 1220 int i; 1221 if (0 < i < 3) {}; // warn 1222 bool b; 1223 if (b == 3) {}; // warn 1224 } 1225 </pre></td><td class="aligned"></td></tr> 1226 1227 <tr><td><span class="name">different.BitwiseOpBoolArg 1228 <br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br> 1229 bool value is used at the left/right part of the & (|) operator. Did you mean 1230 && (||) ? 1231 </td><td><pre> 1232 int f(); 1233 1234 void test() { 1235 bool b = true; 1236 if (b & f()) {} // warn 1237 } 1238 </pre></td><td class="aligned"></td></tr> 1239 1240 <tr><td><span class="name">different.LabelInsideSwitch 1241 <br>(C)</span><br><br> 1242 Possible misprint: label found inside the switch() statement. (* did you mean 1243 'default'?) 1244 </td><td><pre> 1245 void test() { 1246 int c = 7; 1247 switch(c){ 1248 case 1: 1249 c += 1; break; 1250 defalt: // warn 1251 c -= 1; break; 1252 } 1253 } 1254 </pre></td><td class="aligned"></td></tr> 1255 1256 <tr><td><span class="name">different.IdenticalCondIfIf 1257 <br>(C)</span><br><br> 1258 The conditions of two subsequent 'if' statements are identical 1259 </td><td><pre> 1260 void test() { 1261 int c = 7; 1262 if (c > 5) // <- 1263 c += 1; 1264 if (c > 5) // warn 1265 c -= 1; 1266 } 1267 </pre></td><td class="aligned"></td></tr> 1268 1269 <tr><td><span class="name">different.CondOpIdenticalReturn 1270 <br>(C)</span><br><br> 1271 The return expressions of the '?:' operator are identical 1272 </td><td><pre> 1273 void test() { 1274 unsigned a; 1275 a = a > 5 ? a : a; // warn 1276 } 1277 </pre></td><td class="aligned"></td></tr> 1278 1279 <tr><td><span class="name">different.UnaryPlusWithUnsigned 1280 <br>(C)</span><br><br> 1281 Using 'unary +' with unsigned is meaningless 1282 </td><td><pre> 1283 void test() { 1284 unsigned a; 1285 a = +a; // warn 1286 } 1287 </pre></td><td class="aligned"></td></tr> 1288 1289 <tr><td><span class="name">different.LogicalOpUselessArg 1290 <br>(C)</span><br><br> 1291 The second operand of the && operator has no impact on expression result 1292 </td><td><pre> 1293 void test() { 1294 unsigned a; 1295 if (a<7 && a<10) {}; // warn 1296 } 1297 </pre></td><td class="aligned"></td></tr> 1298 1299 <tr><td><span class="name">different.SameResLogicalExpr 1300 <br>(C)</span><br><br> 1301 The expression always evaluates to true/false 1302 </td><td><pre> 1303 void test() { 1304 int i=0; 1305 if (i!=0) {}; // warn 1306 if (i==0 && i==1) {}; // warn 1307 if (i<0 || i>=0) {}; // warn 1308 } 1309 </pre></td><td class="aligned"></td></tr> 1310 1311 <tr><td><span class="name">different.SameResUnsignedCmp 1312 <br>(C)</span><br><br> 1313 Comparison of unsigned expression 'op expr' is always true/false 1314 </td><td><pre> 1315 void test() { 1316 unsigned u; 1317 if (u < -1) {}; // warn 1318 if (u >= 0) {}; // warn 1319 } 1320 </pre></td><td class="aligned"></td></tr> 1321 1322 <tr><td><span class="name">different.OpPrecedenceAssignCmp 1323 <br>(C)</span><br><br> 1324 Comparison operation has higher precedence then assignment. Bool value is 1325 assigned to variable of type 'type'. Parenthesis may bee required around an 1326 assignment 1327 </td><td><pre> 1328 int f(); 1329 1330 void test() { 1331 bool b; 1332 int x, y; 1333 if((b = x != y)) {} // ok 1334 if((x = f() != y)) {} // warn 1335 } 1336 </pre></td><td class="aligned"></td></tr> 1337 1338 <tr><td><span class="name">different.OpPrecedenceIifShift 1339 <br>(C)</span><br><br> 1340 ?: has lower precedence then << 1341 </td><td><pre> 1342 #include <iostream> 1343 1344 void test() { 1345 int a; 1346 std::cout << a ? "a" : "b"; // warn 1347 a << a>7 ? 1 : 2; // warn 1348 } 1349 </pre></td><td class="aligned"></td></tr> 1350 1351 <tr><td><span class="name">different.ObjectUnused 1352 <br>(C++)</span><br><br> 1353 The object was created but is not being used<br><br> 1354 The exception object was created but is not being used. Did you mean 1355 'throw std::exception();'? 1356 </td><td><pre> 1357 #include <exception> 1358 1359 struct S { 1360 int x, y; 1361 S(int xx, int yy) : x(xx), y(yy) { 1362 } 1363 S(int xx) { 1364 S(xx, 0); // warn 1365 } 1366 }; 1367 1368 void test() { 1369 S(0, 0); // warn 1370 std::exception(); // warn 1371 } 1372 </pre></td><td class="aligned"></td></tr> 1373 1374 <tr><td><span class="name">different.StaticArrayPtrCompare 1375 <br>(C)</span><br><br> 1376 Pointer to static array is being compared to NULL. May the subscripting is 1377 missing 1378 </td><td><pre> 1379 void test() { 1380 int a1[1]; 1381 if (a1 == 0) {}; // warn 1382 1383 int a2[1][1]; 1384 if (a2[0]) {}; // warn 1385 } 1386 </pre></td><td class="aligned"></td></tr> 1387 1388 <tr><td><span class="name">different.ConversionToBool 1389 <br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br> 1390 Odd implicit conversion from 'type' to 'bool' 1391 </td><td><pre> 1392 bool test() { 1393 return 1.; // warn 1394 return ""; // warn 1395 } 1396 </pre></td><td class="aligned"></td></tr> 1397 1398 <tr><td><span class="name">different.ArrayBound 1399 <br>enhancement to experimental.security.ArrayBound[v2]<br>(C, C++)</span><br><br> 1400 Out-of-bound dynamic array access 1401 </td><td><pre> 1402 #include <stdlib.h> 1403 1404 void test() { 1405 int *p2 = new int[1]; 1406 if(p2[1]) {}; // warn 1407 int i = 1; 1408 if(p2[i]) {}; // warn 1409 } 1410 </pre></td><td class="aligned"></td></tr> 1411 1412 <tr><td><span class="name">different.StrcpyInputSize 1413 <BR>enhancement to experimental.unix.cstring.OutOfBounds<br>(C)</span><br><br> 1414 Buffer copy without checking size of input 1415 </td><td><pre> 1416 void test(char* string) { 1417 char buf[24]; 1418 strcpy(buf, string); // warn 1419 } 1420 </pre></td><td class="aligned"></td></tr> 1421 1422 <tr><td><span class="name">different.IntegerOverflow 1423 <br>(C)</span><br><br> 1424 Integer overflow 1425 </td><td><pre> 1426 #include <limits.h> 1427 1428 int f(int x) { 1429 return INT_MAX+1; // warn 1430 } 1431 1432 void test() { 1433 int x = INT_MAX+1; // warn 1434 f(INT_MAX+1); // warn 1435 1436 int y = INT_MAX/2+1; // warn 1437 x = y*2; // warn 1438 } 1439 </pre></td><td class="aligned"></td></tr> 1440 1441 <tr><td><span class="name">different.SignExtension 1442 <br>(C)</span><br><br> 1443 Unexpected sign extension might take place 1444 </td><td><pre> 1445 void f(unsigned int i); 1446 int g(); 1447 1448 unsigned int test() { 1449 long long sll; 1450 unsigned long long ull = sll; // warn 1451 long sl; 1452 unsigned long ul = sl; // warn 1453 int si; 1454 unsigned int ui = si; // warn 1455 short ss; 1456 unsigned short us = ss; // warn 1457 signed char sc; 1458 unsigned char uc = sc; // warn 1459 f(si); // warn 1460 ui = g(); // warn 1461 return si; // warn 1462 } 1463 </pre></td><td class="aligned"></td></tr> 1464 1465 <tr><td><span class="name">different.NumericTruncation 1466 <br>(C)</span><br><br> 1467 Numeric truncation might take place 1468 </td><td><pre> 1469 void f(int i); 1470 int g(); 1471 1472 int test() { 1473 unsigned long long ull; 1474 long long sll; 1475 unsigned long ul = ull; // warn 1476 long sl = sll; // warn 1477 unsigned int ui = ul; // warn 1478 int si = sl; // warn 1479 unsigned short us = ui; // warn 1480 short ss = si; // warn 1481 unsigned char uc = us; // warn 1482 signed char sc = uc; // warn 1483 f(sll); // warn 1484 ss = g(); // warn 1485 return sll; // warn 1486 } 1487 </pre></td><td class="aligned"></td></tr> 1488 1489 <tr><td><span class="name">different.MissingCopyCtorAssignOp 1490 <br>(C, C++)</span><br><br> 1491 The class has dynamically allocated data members but do not define a copy 1492 constructor/assignment operator 1493 </td><td><pre> 1494 class C { // warn 1495 int *p; // <- 1496 public: 1497 C() { p = new int; } 1498 ~C() { delete p; } 1499 }; 1500 </pre></td><td class="aligned"></td></tr> 1501 1502 </table> 1503 1504 <!-- ============================ WinAPI =================================== --> 1505 <h3>WinAPI</h3> 1506 <table class="checkers"> 1507 <col class="namedescr"><col class="example"><col class="progress"> 1508 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 1509 1510 <tr><td><span class="name">WinAPI.CreateProcess 1511 <br>(C)</span><br><br> 1512 After calling CreateProcess(), ensure that process and thread handles get closed 1513 (* for the given example: examine data flow from pi, pi.hProcess and pi.hThread) 1514 </td><td><pre> 1515 #include <windows.h> 1516 1517 void test() { 1518 STARTUPINFO si; 1519 PROCESS_INFORMATION pi; 1520 BOOL fSuccess; 1521 fSuccess = CreateProcess( 1522 NULL, TEXT("MyProgram.exe"), NULL, NULL, 1523 TRUE, 0, NULL, NULL, &si, &pi); 1524 } // warn 1525 </pre></td><td class="aligned"></td></tr> 1526 1527 <tr><td><span class="name">WinAPI.LoadLibrary 1528 <br>(C)</span><br><br> 1529 Calling LoadLibrary without a fully qualified path may allow to load a DLL from 1530 arbitrary location 1531 </td><td><pre> 1532 #include <windows.h> 1533 1534 void test() { 1535 HINSTANCE h = LoadLibrary("X.dll"); // warn 1536 } 1537 </pre></td><td class="aligned"></td></tr> 1538 1539 <tr><td><span class="name">WinAPI.WideCharToMultiByte 1540 <br>(C)</span><br><br> 1541 Buffer overrun while calling WideCharToMultiByte 1542 </td><td><pre> 1543 #include <windows.h> 1544 1545 void test() 1546 { 1547 wchar_t ws[] = L"abc"; 1548 char s[3]; 1549 int res1 = WideCharToMultiByte( 1550 CP_UTF8, 0, ws, -1, s, 1551 3, NULL, NULL); // warn 1552 int res2 = WideCharToMultiByte( 1553 CP_UTF8, 0, ws, -1, s, 1554 3, NULL, NULL); // ok 1555 if (res2 == sizeof(s)) 1556 s[res2-1] = 0; 1557 else 1558 s[res2] = 0; 1559 } 1560 </pre></td><td class="aligned"></td></tr> 1561 1562 </table> 1563 1564 <!-- =========================== optimization ============================== --> 1565 <h3>optimization</h3> 1566 <table class="checkers"> 1567 <col class="namedescr"><col class="example"><col class="progress"> 1568 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead> 1569 1570 <tr><td><span class="name">optimization.PassConstObjByValue 1571 <br>(C, C++)</span><br><br> 1572 Optimization: It is more effective to pass const n-th parameter by reference to 1573 avoid unnecessary object copying 1574 </td><td><pre> 1575 struct A { 1576 int a[20]; 1577 int b; 1578 }; 1579 1580 bool FirstIsZero(const struct A a) { // warn 1581 return a.a[0] == 0; 1582 } 1583 </pre></td><td class="aligned"></td></tr> 1584 1585 <tr><td><span class="name">optimization.PostfixIncIter 1586 <br>(C++)</span><br><br> 1587 Optimization: It is more effective to use prefix ++ with iterator here 1588 </td><td><pre> 1589 #include <vector> 1590 1591 void test() { 1592 std::vector<int> v; 1593 std::vector<int>::const_iterator it; 1594 for(it = v.begin(); 1595 it != v.end(); it++) {}; // warn 1596 } 1597 </pre></td><td class="aligned"></td></tr> 1598 1599 <tr><td><span class="name">optimization.MultipleCallsStrlen 1600 <br>(C)</span><br><br> 1601 Optimization: multiple calls to strlen for a given string in the given 1602 expression. It is more effective to hold strlen result in a temporary 1603 variable 1604 </td><td><pre> 1605 #include <string.h> 1606 1607 void test() { 1608 const char* s = "abc"; 1609 if (strlen(s) > 0 && 1610 strlen(s) < 7) {}; // warn 1611 } 1612 </pre></td><td class="aligned"></td></tr> 1613 1614 <tr><td><span class="name">optimization.EmptyCstrDetect 1615 <br>(C)</span><br><br> 1616 Optimization: it is more efficient to use "str[0] != '\0'" to identify an empty 1617 string 1618 </td><td><pre> 1619 #include <string.h> 1620 1621 void test() { 1622 const char* s = "abc"; 1623 if (strlen(s) > 0) {}; // warn 1624 } 1625 </pre></td><td class="aligned"></td></tr> 1626 1627 <tr><td><span class="name">optimization.StrLengthCalculation 1628 <br>(C, C++)</span><br><br> 1629 Optimization: it is more efficient to use string::length() method to calculate 1630 string length 1631 </td><td><pre> 1632 #include <string> 1633 #include <string.h> 1634 1635 void test() { 1636 std::string s; 1637 if (strlen(s.c_str()) != 0) {}; // warn 1638 } 1639 </pre></td><td class="aligned"></td></tr> 1640 1641 <tr><td><span class="name">optimization.EmptyContainerDetect 1642 <br>(C, C++)</span><br><br> 1643 Optimization: It is more efficient to use container.empty() to identify an 1644 empty container 1645 </td><td><pre> 1646 #include <list> 1647 1648 void test() { 1649 std::list<int> l; 1650 if (l.size() != 0) {}; // warn 1651 } 1652 </pre></td><td class="aligned"></td></tr> 1653 1654 </table> 1655 1656 <br> 1657 </div> <!-- page --> 1658 </div> <!-- content --> 1659 </body> 1660 </html> 1661