traps and pitfalls for vc6, atl, c++ may be obvious ? may be not ? mark bartosik

23
Traps and pitfalls for VC6, ATL, C++ • May be obvious ? • May be not ? Mark Bartosik

Upload: alban-stevens

Post on 17-Dec-2015

223 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Traps and pitfalls for VC6, ATL, C++

• May be obvious ?

• May be not ?

Mark Bartosik

Page 2: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Danagers of _bstr_t

• _bstr_t::_bstr_t(const char * narrow_str)– Unhandled exception 0xC00000FD

because it allocates from the stack 2 x strlen(narrow_str)

• operator const char *() constoperator char *()– both return a pointer to PRIVATE data

const char * p = get_str();

unsigned len = strlen(p); // bang ???#! error ??

Page 3: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Danagers of _bstr_t

• operator const wchar_t *() constoperator wchar_t *()– both return a pointer to PRIVATE data

BSTR p = get_str();

unsigned len = SysStringLen(p); // bang ???#! err??

Page 4: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Alternatives with _bstr_t

• const wchar_t * GetWString() const• const char * GetString() const

• But not realistic. Once the extraction operators exist, you cannot avoid them.

• #pragma depracatedsee Visual Studio .NET

Page 5: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Dangers of CComBSTR

• What is wrong with the following member functions?

operator BSTR() const

BSTR* operator&()

• int a;int * p = &a;

Page 6: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

CComPtr<T> CComQIPtr<T>

• T** operator&()– Gives access to internal data

can cause a leak (if not NULL)

• T& operator*() – Does not access to IUnknown

operator->() returns proxy object with private IUnknown

• operator T*()– Gives implicit access to raw pointer

Page 7: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

_com_ptr_t<T>

• T** operator&()

• T* operator->()Exposes Iunknown, unlike CComPtr & CComQIPtr which return a proxy object

• Behaves like CComQIPtr but uses exceptions for error reporting.Auto declared by #import

Page 8: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

• variant_t : public VARIANT

Page 9: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

How to choose ?

• Consistency is best• Consistently use _bstr_t or CComBSTR• Consistently use CComPtr or _com_ptr_t

If using #import prefer _com_ptr_t• Does the rest of your code use exceptions or magic

return values?• Write your own? (based on CComPtr)

Page 10: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

collections

std::map<unsigned, employee_t>std::map<unsigned, CComPtr<IEmployee> >

std::map<unsigned, CAdapt<CComPtr<IEmployee> > >

Also when erasing elements, don’t saw off the branch that you are sitting on. (General STL rule)

Store objects NOT dumb pointers (smart pointers are objects)Remember that my_collection.erase(iter) invalidates iter.use iter = my_collection.erase(iter)

Don’t forget about the algorithms #include <algorithm>

Page 11: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

#import

• Can use instead of .h, even for implementationImplement the raw_ functions.

• Read the .tlh filesBe careful some functions will return IDispatchPtr others will return IDispatch *. It depends on the IDL.Reading the .tlh is a thinking aid, keep it open in a window.

Page 12: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Debugging

• Prefer __stdcall over __thiscall• Optimizer off• Consider releasing with optimizer off

(except allow inlines for likes of STL)• Symbol files on (PDB not PDB for edit continue),

Link with debug info,Do not separate types

• Debug with Visual Studio .NET

Page 13: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

(more) lifetime management

CObj::foo(){ CSLock __anonymous__(m_critsec); m_sub_object.Release();} // Bang!

CObj::foo(){ IUnknownPtr __anonymous__(this); CSLock __anonymous__(m_critsec); m_sub_object.Release();}

Page 14: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

(more) lifetime management

• Do not mix strong and weak pointers

• What if you need a C++ pointer to a CComObject derived object?

std::pair<COurClass*, UnknownPtr>

orstruct

• {• UnknownPtr strong_ref;

COurClass * weak_ref;• }

Page 15: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Patterns

• Avoid Singleton anti-pattern• Once per what?

Per network? Per sub-net? Per machine? Per apartment ? Per security context ? Per process? Per thread? Per transaction? Per user ? Etc.The ATL singleton is once per process.

• Use a more natural language idiom– C++ globals are naturally per process.– C variables in a shared data seg are naturally per machine– VB module variables are naturally per thread (apartment)– But avoid global pointers to COM objects (issues with CRT and COM

initialization order)

Page 16: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Cyclic references & Connection points

• Wizard generated code is just bad (has some bugs)Also it is synchronoussee www.cuj.com (search for Bartosik)

• Lack of type safety (IDispatch)

Page 17: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Build consideration

• Prefer dynamic link CRT(but there are install issues)

• Avoid creating COM components within a group

Page 18: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Libraries

• STL

• WTL

• boost.org

Page 19: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Leak Browser

• Much of COM is about ownership / lifetime management, but poor C++ language binding, thus the bugs.

• Will find all your leaks• Soon will find all your references to deleted objects• Soon will find all use of uninitialized memory• Contact Bartosik for updates / latest build.

Page 20: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

casts

reinterpret_cast<TO>(from)reinterpret the bit pattern (unsafe and forceful)

dynamic_cast<TO>(from)

runtime check (from must have at least one virtual function). Often a sign of bad design. Why don’t you know the type. dynamic_cast<derived*>(base*)

static_cast<TO>(from)convert only if reasonable

const_cast<TO>(from)remove either const or volatile qualifiers

(TO)c-style cast -- avoid it, like static_cast OR reinterpret_cast optionally combined with const_cast, and can be more forceful than reinterpret_cast.

Page 21: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Compiler settings(use PDB for all)

Page 22: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Linker settings(include debug info)

Page 23: Traps and pitfalls for VC6, ATL, C++ May be obvious ? May be not ? Mark Bartosik

Linker settings(do not separate types)