1 / 22

Typical Error Patterns in C++

Typical Error Patterns in C++. Presented by: Eui-Seok Kim SVD Inc., Seoul, Korea www.svd.co.kr. Unsafe Codes. Arrays & pointers in interfaces void* Variadic functions union Casts Implicit conversions Naked new/delete Why does C++ allow them? Compatibility with C Performance

emma-cortez
Download Presentation

Typical Error Patterns in C++

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Typical Error Patterns in C++ Presented by: Eui-Seok KimSVD Inc.,Seoul, Korea www.svd.co.kr

  2. Unsafe Codes • Arrays & pointers in interfaces • void* • Variadic functions • union • Casts • Implicit conversions • Naked new/delete • Why does C++ allow them? • Compatibility with C • Performance • Direct access to hardware

  3. Arrays & Pointers in Interfaces • Old-time C programmers using C++ are the heaviest users of arrays and pointers. • No alternative for the C standard library. • SPARROW detects various error patterns of this kind. • They are evil! • Dangling references(?) void g() { int* p = new int; int& r = *p; delete p; ++r; // oops! }

  4. void* • What is the type of an object pointed by a void*? Compilers have no idea. • Explicit casts are required to convert a void* to another pointer type. • Functions in the C standard library • memcpy, memmove, memcmp, memset • fread, fwrite • malloc, calloc, realloc, free • bsearch, qsort • C++ provides more type-safe alternatives.

  5. Variadic functions • Compilers cannot check the number and types of parameters. You're on your own. • Functions in the C standard library • printf, scanf • Example Original code: float value; scanf("%e", &value); The type of value has been changed. double value; scanf("%e", &value); // oops! • C++ provides more type-safe stream classes.

  6. union • You have to keep track of current type. • Contains POD-type objects only. • Example union U { int i; char* s; }; void f(U& u) { printf("%s", u.s); } void g() { U u; u.i = 0; f(u); // oops! }

  7. Casts • "And if you've got a lot of casts in the code, there's something wrong." - Bjarne Stroustrup • Pointer and reference casts are evil! • Blunt C-style casts: "Shut up, compiler!" void f(int** a); void g() { int a[10][10]; f( (int**)a ); // oops! } • Even C++-style casts won't save you much, except that you can locate them easily.

  8. Implicit Conversions • Standard conversions • Arithmetic conversion to narrower type • Conversion of signed type into unsigned type • Conversions between integral and floating-point type • Conversion of string literal into a non-const char* • User-defined conversions • Conversion by constructor • Conversion functions • Should be used with great care (explicit keyword)

  9. Implicit Conversions • Examples void f(char* s) { s[0] = 'j'; } void g() { char* s = "hello"; f(s); // oops! } const char* str = "hello"; int len = -1; assert(strlen(str) > len); // assertion fails!

  10. Implicit Conversions • Examples template <typename T> class Array { public: Array(int size); T& operator[](int); Array<T>& operator=(const Array<T>&); //... }; Array<double> a(10); a[0] = 0; a[1] = 1; a[2] = 4; a[3] = 9; a[4] = 16; a = 25; // oops! CString s("hello"); // from Microsoft ATL CString class s - "o"; // what the hell is this?

  11. Naked new/delete • Common errors • delete'ing new[]'ed memory • delete[]'ing new'ed memory • double delete'ing • delete'ing non-heap memory • not delete'ing • mixing new/delete with malloc/free • checking for NULL after new operation int* p = new int; // throws std::bad_alloc int* q = new(std::nothrow) int; // returns NULL

  12. new/delete: Safety Issues • Evil pointer operations • Not exception-safe • Memory leakage • Use std::vector or std::string instead.

  13. Resource Management: RAII • Resource acquisition is initialization • Encapsulated • Resource-agnostic • memory • files • sockets • locks • images… • Deterministic • Examples • stream classes in the standard library • std::auto_ptr • std::tr1::shared_ptr • ScopeGuard (http://www.ddj.com/cpp/184403758)

  14. Resource Management: RAII C Way: What a mess! C++ Way: RAII excerpt from http://en.wikipedia.org

  15. Rule of the Big Three • A class with a destructor needs… • a copy constructor • an assignment operator • Mostly resource-acquiring classes • Make it clear if the class is noncopyable. class MyClass { public: MyClass(int v) : value_(new int(v)) {} ~MyClass() { delete value_; } private: int* value_; }; int main() { MyClass c1(0); MyClass c2(c1); } // delete twice

  16. Initialization Order in Constructor • Initialization follows the member declaration order, not the initialization order. template <typename T> class Array { public: explicit Array(int size) : size_(size), capacity_(size_ + 10), data_(new T[capacity_]) { } // ... private: T* data_; int capacity_; int size_; };

  17. Default Arguments • They can lead to unintended results. Things get even worse when used in constructors. class Point { public: Point(double x = 0.0, double y = 0.0) : x_(x), y_(y) { } private: double x_, y_; }; int main() { Point p = (1.0, 2.0); // what is the value of p.x_ and p.y_? return 0; }

  18. Arrays and Inheritance struct B { B() : i_(0) { } int i_; }; struct D : public B { D() : j_(1) { } int j_; }; void f(B* pb) { int i = pb[1].i_; assert(i == 0); // assertion fails! } int main() { D d[10]; f(d); }

  19. STL containers and iterators • Invalid subscript (vector, string, deque) • Iterator to an invalidated object list<int>::iterator f() { list<int> l; return l.begin(); } void g() { vector<int> v(2); vector<int>::iterator it = v.begin(); v.reserve(1024); } • Dereferencing a "null" iterator or iterator to the one-past-the-last element set<int> s; set<int>::iterator in, it = s.find(0); cout << *in; cout << *it;

  20. STL containers and iterators • Runaway iterators list<int> a, b; list<int>::iterator p = find(a.begin(), b.end(), 100); • Iterators to an erased elements list<int>::iterator q = a.begin(); b.erase(q); • Iterators to destroyed containers list<int>* pl = new list<int>; list<int>::iterator p = pl->begin(); delete pl; cout << *p; // oops! • Got enough space? vector<int> u(10), v, w; copy(u.begin(), u.end(), v.begin()); copy(u.begin(), u.end(), back_inserter(w)); // ok

  21. STL containers and iterators • Iterators are generalized pointers. • Most array- or pointer-related issues have iterator counterpart. • Iterators don't know the containers they are pointing at.

  22. More Information • Bjarne Stroustrup, The C++ Programming Language • Scott Meyers, [More] Effective C++ • Scott Meyers, Effective STL • Herb Sutter, [More] Exceptional C++ • Stephen Dewhurst, C++ Gotchas • Bjarne Stroustrup's Homepage http://www.research.att.com/~bs/homepage.html • Herb Sutter's Homepage http://www.gotw.ca/ • C++ FAQ Lite http://www.parashift.com/c++-faq-lite/

More Related