Top Banner
Typical Error Patterns in C++ Presented by: Eui-Seok Kim SVD Inc., Seoul, Korea www.svd.co.kr
22

Typical Error Patterns in C++

Jan 02, 2016

Download

Documents

emma-cortez

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 - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Typical Error Patterns in C++

Typical Error Patterns in C++

Presented by:

Eui-Seok KimSVD Inc.,

Seoul, Korea

www.svd.co.kr

Page 2: Typical Error Patterns in C++

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

Page 3: Typical Error Patterns in C++

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!}

Page 4: Typical Error Patterns in C++

void* What is the type of an object pointed by a void*? Co

mpilers 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.

Page 5: Typical Error Patterns in C++

Variadic functions Compilers cannot check the number and types of para

meters. 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.

Page 6: Typical Error Patterns in C++

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!}

Page 7: Typical Error Patterns in C++

Casts "And if you've got a lot of casts in the code, there's s

omething 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.

Page 8: Typical Error Patterns in C++

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)

Page 9: Typical Error Patterns in C++

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!

Page 10: Typical Error Patterns in C++

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 classs - "o"; // what the hell is this?

Page 11: Typical Error Patterns in C++

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_allocint* q = new(std::nothrow) int; // returns NULL

Page 12: Typical Error Patterns in C++

new/delete: Safety Issues

Evil pointer operations Not exception-safe Memory leakage Use std::vector or std::string instead.

Page 13: Typical Error Patterns in C++

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)

Page 14: Typical Error Patterns in C++

Resource Management: RAII

C Way: What a mess!

C++ Way: RAII

excerpt from http://en.wikipedia.org

Page 15: Typical Error Patterns in C++

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

Page 16: Typical Error Patterns in C++

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_;};

Page 17: Typical Error Patterns in C++

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;}

Page 18: Typical Error Patterns in C++

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);}

Page 19: Typical Error Patterns in C++

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;

Page 20: Typical Error Patterns in C++

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

Page 21: Typical Error Patterns in C++

STL containers and iterators Iterators are generalized pointers. Most array- or pointer-related issues have iterator cou

nterpart. Iterators don't know the containers they are pointing at.

Page 22: Typical Error Patterns in C++

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/