220 likes | 353 Views
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
E N D
Typical Error Patterns in C++ Presented by: Eui-Seok KimSVD 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 • Direct access to hardware
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! }
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.
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.
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! }
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.
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)
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!
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?
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
new/delete: Safety Issues • Evil pointer operations • Not exception-safe • Memory leakage • Use std::vector or std::string instead.
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)
Resource Management: RAII C Way: What a mess! C++ Way: RAII excerpt from http://en.wikipedia.org
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
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_; };
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; }
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); }
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;
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
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.
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/