수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1694835
  • Today | 580
  • Yesterday | 606

Programming/C++2008/04/26 18:20

C++ Preprocessor: Always Assert Your Code Is Right

Site : http://www.devarticles.com/c/a/cplusplu ··· right%2F

Are you looking for a way to speed up the debugging process in C++? This article explains how to use asserts to do just that, showing that not all macros are evil.

If a man begins with certainties, he shall end in doubts;

But if he will be content to begin with doubts,

 He shall end in certainties.

[Francis Bacon 1561-1626]

Assertive Programming

If there is one thing I have learned over the past few years, it is not to underestimate the power of assert(). It comes with your compiler and can be found either in cassert or assert.h.

The reason I love assert is because it looks after me and helps me find bugs I was sure weren’t there. I mean, we all write bugfree software, right? Yeah right. Well there have been many Kodak moments when an assert fired on something I was dead sure could never happen; I should be a rich man as the look on my face was priceless.

If you are not familiar with asserts, you should start using them right now. Use  assert to check that your code is working the way you expect it to or be prepared to pay the price. No not for my face, but for long nights behind the debugger, ticking away possible problem sources until you have your own Kodak moment.

When do you use assert, you ask? Simple… whenever you can use it to verify the truth of a situation: ‘this pointer can never be null’, ‘this number is never smaller than zero’, ‘there is always at least one customer stored in this list’, ‘this code won’t be used the next millennium, two digits are fine’.

Use proper error handling when you can check for things that can go wrong. Use asserts on things you are sure can’t go wrong.

Trust me… the sillier the assert… the more valuable it is. I tested this once myself, grinning, thinking ‘this is ridiculous, want to bet it will never fire?’, only to have it triggered a couple of months later! And because the assert was so preposterous and silly I immediately knew which conditions were breaking my code.

assert.

  1. To state or express positively, affirm: asserted his innocence
  2. To defend or maintain (one’s rights, for example)

The important thing to remember is that asserts are only compiled into your code when the NDEBUG macro is not defined. So in the final optimized version of your application, they are not there to bloat or to slow things down! The only investment you have to make is typing them out while you are working on those classes and functions. It will pay you back greatly when it helps you shorten the time it takes to track down bugs.

Face it… we all write code on assumptions we make about the situation the code will be running in. Assert you are in that situation, because your code base will grow beyond the picture you have of it in your mind.

Implementing Assert

Though we will be implementing our customized version of assert here, all you need to do is include assert.h and you are ready to use the assert macro that comes with it:

The __assert helper function prints an error message to stderr and the program is halted by calling abort(). It is possible that the implementation that comes with your compiler varies slightly, but you get the idea.

Lets use a simple example function:

In the unfortunate situation that the pointer to string is NULL, execution will halt and you will be offered the possibility of opening the debugger and jumping to the location in the source where the assertion failed. This can be very handy as you can examine the call stack, memory, registers, and so forth, and are likely to catch the perpetrator red handed!

Implementing a Simplified Assert

Although I am ranting about why you should use assert, this article is aimed at showing you how to implement your own version using preprocessor macros.

Here is a very basic version that doesn’t even halt execution:

Notice that we don’t need a helper function to get information onto the screen. (I am sticking to printf in the following examples, but there is nothing stopping you from using fprintf and stderr instead.) The stringize macro operator (#) names the condition for us in the printf statement, adding quotes as well and the predefined __LINE__ and __FILE__ macros help to identify the location of the assert.

The do { } while ( false ) statement for the unused version of assert, I used to make sure that the user cannot forget to conclude his assert statement with a semicolon. The compiler will optimize it away, and I consider it a slightly better way to say that I am not doing anything.

We are only one step away from halting our application’s execution (don’t forget to include stdlib.h):

In case writeString is called with a NULL pointer now, we are told what went wrong, where it went wrong and the application is halted.

When you are using the Microsoft Visual C++ 7.1 compiler, you’ll be presented with a dialog screen:

After pressing Retry you are presented with more dialogs and finally... you end up in the debugger.

The problem with abort() is that it doesn’t let you resume execution after you’ve concluded that the assert was benign; or maybe you are interested in what happens immediately after the assert? You need to disable the assert (never a good thing), recompile and restart your application.

There are other ways to halt execution and you will have to look in your compiler’s documentation to discover what the correct call is, but with Visual C++ it’s an interrupt call:

When our application halts again on the writeString function, we’ll encounter the following dialog (did you recognize it? We actually came across this dialog when halting the application with the abort() function!) :

It is not a problem to continue execution now, if we think this is responsible… that is you are often recommended to implement your own assert functionality.

Wouldn’t it be nice to be able to add some hints or remarks along with the location of the assert? When the assert fires and you don’t have a debugger available, this message might still tell you what the problem is:



Refining Assert

The simplest solution is to just expand the assert macro and make it accept a message as well as a condition:



Again the stringize operator helps us to stuff the message we want into the printf statement. We could call it a day now, but I am a very lazy coder… I do not want to be forced to put messages into the assert, sometimes I just want to assert.

Of course it is possible to write an ASSERT(condition) and an ASSERTm(condition, message) macro, but did I mention I am a forgetful coder too? I’d much rather have a single ASSERT statement that can do both.

The first thing that comes to mind is the fact I could do this easily with a function:

So maybe if I declared another function:

void NoAssert(bool isOK, char const *message=””) {}

And then defined assert as:

While this seems like a quick solution, I have completely lost my extra debug information! The line information is the same now for every assert… oh… the compiler substitutes __LINE__ with the actual line number it is compiling at that moment, and since we are making a function call – all line numbers lead to the MyAssert function!

Alexandrescu demonstrates a great way around this problem [Alexandrescu]. (It is also a great article showing how you can take assertions to a higher level after this one, by making them throw exceptions!)



For some reason my Visual C++ 7.1 compiler will not accept the __LINE__ macro next to the __FILE__ macro in the code above. The strange thing is that the __FILE__ macro works fine, but with __LINE__ it complains:

It is never easy, but I do not want to give up at this point. Since the macro is expanded as a single line into the place where we are calling it, and since the compiler apparently has no objection to me assigning __LINE__ as a default parameter in a constructor, let's try again:

Now that we have our line information back, we are nearly there; as soon as we add a second assert, the compiler complains that we are redefining the struct MyAssert! If only we could keep the struct declaration local… and again Alexandrescu shows us how [Alexandrescu]:



There is a lot of fun to be had with macros and sometimes it is possible to create the wildest incantations with them [Niebler/Alexandrescu]. I hope you are convinced that despite the fact that they can be considered evil, there is something magical about them as well.

As a final example I will show you how to create personal and customizable debug streams in the next article… all with macros.

References

 [STL] – The Standard Template Library
< comes standard with your compiler but this one is very portable>
http://www.stlport.org

[BOOST] – Boost C++ Libraries
http://www.boost.org

[ACE] – The ADAPTIVE Communication Environment
http://www.cs.wustl/edu/~schmidt/ACE.html

[Niebler] – Eric Niebler
“Conditional Love: FOREACH Redux”
http://www.artima.com/cppsource/foreach.html

[Alexandrescu] – Andrei Alexandrescu
Assertions
http://www.cuj.com/documents/s=8248/cuj ··· xandr%2F

"C++" 카테고리의 다른 글
  • C++ Preprocessor: Always Assert Your Code Is Right (0)2008/04/26
  • C++ Preprocessor: The Code in the Middle (0)2008/04/26
  • C++ Programming Tips (0)2008/04/26
  • C++ Preprocessor: Always Assert Your Code Is Right (0)2007/07/30
  • C++ Preprocessor: The Code in the Middle (0)2007/07/30
2008/04/26 18:20 2008/04/26 18:20
Posted by webdizen
Tags C++Keyword C++, Preprocessor
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/3208

Leave your greetings.

[로그인][오픈아이디란?]

«Prev  1 ... 86 87 88 89 90 91 92 93 94 ... 3009  Next»

RSS HanRSS
Blog Image
webdizen
이곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

Categories

전체 (3009)
Webdizen (141)
Life (6)
Diary (16)
Blog (9)
IDEA (2)
Travel (10)
Book (16)
Photo (7)
Movie (8)
Music (14)
Leisure Sports (10)
Funny (6)
Hardware (121)
Software (120)
Windows (5)
Unix & Linux (120)
Installation (5)
Kernel (10)
System (34)
Develop (22)
X-Window (0)
Applicaton (31)
Security (4)
Framework (2)
Hadoop (2)
Programming (804)
Algorithm & Data Structure (1)
Assembly (38)
UNIX/Linux C (95)
C++ (128)
STL (4)
Java (38)
Win32 API (92)
ATL/COM (44)
MFC (151)
.NET (26)
WCF/WPF (4)
C# (28)
Network Programming (17)
Database Programming (12)
OpenGL / DirectX (13)
Multimedia Programming (0)
Game Programming (21)
Parallel Distributed Progra... (0)
Reverse Engineering (0)
Debugging (9)
Python (1)
Ruby (1)
Ruby on Rails (1)
QT (4)
GTK (0)
JSP (0)
PHP (6)
ASP.NET (6)
ASP (2)
Development (28)
Useful Library (2)
Data Modeling (0)
Database (105)
Oracle (4)
MSSQL (41)
MySQL (2)
Data Warehouse (2)
Data Mining (4)
Network (66)
Web (79)
DHTML (4)
XHTML (1)
Javascript (1)
CSS (1)
AJAX (9)
XML (11)
Flex (1)
Silverlight (3)
Security (91)
DoS (1)
Kernel (10)
Scanning (3)
Sniffing (0)
Spoofing (4)
Overflow (28)
Web (11)
Shell (10)
Format String (14)
Window (2)
Embedded (70)
Multimedia (27)
Mobile (14)
Graphic (24)
Management (633)
Knowledge (581)
Hadoop (0)

Notice

  • 메타 블로그 사이트에 등록
  • 새해 맞이 블로그의 변화
  • 블로그 명칭 변경
  • 도메인(www.webdizen.net) 구...
  • TEXTCUBE 1.6.1로 업그레이드...

Tags

  • 데이터 코드
  • Windows Communication Foundation
  • 패턴인식
  • XP
  • 가치관
  • firefox1.5
  • 구급약
  • 컨트롤 삽입
  • 검색 제한자
  • 미국
  • 프로그래머의 조건
  • termios
  • processor
  • NUMA
  • 고차원
  • Property
  • Volatile
  • Freeware
  • TED
  • 저장소 엔진

Recent Articles

  • 트위터(Twitter)의 시작!.
  • 청년 리더의 조건.
  • 애플의 타블렛 PC - 아이패드....
  • 미래의 인터페이스 - 육감 기....
  • 기초발성법 동영상 강좌.

Recent Comments

  • 경청... 너무나 중요한데.......
    webdizen 14:59
  • 학교 과제물중 쓰레드에 대하....
    장진혁 03/17
  • 관리자만 볼 수 있는 댓글입....
    비밀방문자 03/12
  • 상대방의 이야기를 열심히 경....
    DoNuts 03/03
  • 좋은글 잘 보고 갑니다..
    Und_hacker 01/08

Recent Trackbacks

  • printf,scanf를 이용한 형식....
    yundream의 프로그래밍 이야기 03/10
  • 파일 열기/저장하기 CFileDialog.
    은마군의 나태블록 2009
  • World IT Show 2008.
    상우 :: Oranzie's BLOG 2008
  • cvs서버 설치하기.
    3인3색 2008
  • 속속 공개되는 Google Chart....
    PHP와 Web 2.0 2007

Archive

  • 2010/02 (1)
  • 2010/01 (6)
  • 2009/12 (5)
  • 2009/09 (3)
  • 2009/08 (1)

Calendar

«   2010/03   »
일 월 화 수 목 금 토
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Bookmarks

    • Administration
      • IIS.NET
      • NTFAQ
      • OS의 모든 것
      • 리눅스포털
    • Database
      • SQL Server Central
      • SQL Team
    • Development
      • .NET Heaven
      • ASP Alliance
      • ASP.NET 2.0
      • Bullog.net
      • C# Corner
      • C++ (C PlusPlus.com)
      • C++ Reference
      • CodeGuru
      • CodePlex
      • DebugLab
      • Dev Articles
      • Devpia
      • DotNet Junkies
      • DotNet Zone
      • Driver Online
      • GOSU.NET
      • HOONS 닷넷
      • Joinc 팀블로그
      • KOSR
      • MSDN Home Page
      • OSR Online
      • Sky.ph - 개발자 커뮤니...
      • TAEYO.NET
      • The Code Project
      • WindowsClient.net
      • 김상욱의 개발자 Side
      • 조인시 위키
    • Human Networks
      • belief21c's e-space
      • I think I can
      • Invisible Rover's Blog :D
      • Polarux - Linuxing
      • Rodman®
      • 까만 나비
      • 나를 가꾸는 시간.
      • 단녕
      • 상우 :: Oranzie's BLOG
    • Information Technology
      • Microsoft TechNet
      • 지디넷코리아 - 글로벌...
    • Security
      • FoundStone
      • milw0rm
      • NewOrder
      • OpenRCE
      • Phrack.org
      • Reverse Engineering b1...
      • Reverse Engineering Team
      • RootKit
      • SecurityFocus
      • SecurityXploded by Nag...
      • Wow Hacker
      • Zone-H
Textcube
Louice Studio Inc.
Powered by Textcube. Original designed by Tistory.