Title: CS 204 Advanced Programming
1CS 204Advanced Programming
- Info, Expectations,Style, Debugging
2Info
- Topics
- advanced object-oriented programming techniques
and programming with classes - function overloading, templated classes,
inheritance, - pointers,
- debugging and profiling,
- reusable software (using/creating libraries),
- visual/GUI programming
- programming in UNIX/Linux environments (make
files, shell scripts), - exception handling (SW interrupts),
- multi-threaded programming and synchronization,
- real-time network programming (hardware
interrupts, pipes, sockets) - internet programming
3Info
- Text Book Tapestry (Chp. 9-13)
- Beginning Visual C by I. Horton (Chp. 4-18)
- Webpage http//people/berrin/cs204/
- We will use WEBCT only to submit/collect
homeworks and discussions. Questions that may
interest other students should be asked on Webct
so that the answer benefits all. - Grading
- Midterm1 25 Midterm2 25 Final 35
Homeworks 15 - Passing grade You must have 35 or higher in your
total average and 30 or higher in the final exam,
in order to pass the course!
4Labs and TAs
- Lab Schedule Thursday 0540 pm - 0730 pm
- Until further notice, you can go to any section
you want - Tas will go over course material from the past
week and help with that weeks homework in the
lab time. - Please respect Tas time and do not ask them
questions on email or outside office time at
their office. Send all question to WEBCT! - More about all these rules on the course website.
5Homeworks
- Through WebCT only. Anything else will be
ignored/deleted. - Label your homework as
- studentid-FirstnameLastname-hw3.zip
- 5519-AhmetGül-hw1.zip
- Failure to do so will lose you points.
- Write your name inside the files as well
- Do not use unknown or uncommon file types that we
may not be able to open (doc, rtf, pdf, ps, zip
are fine) rar is not fine. - You may submit your homework multiple times, and
you may also submit late (see below), so make all
your submissions there.
6Homeworks
- Late penalty 10pts/day, up to 2 days (unless
otherwise specified). Check webct due dates. - Do not push submission deadlines (last 15 min),
or else submit as late. - Any missing files in your submission (even std.
libraries etc.) will lose you points. - For complete submission requirements, check the
website!
7Preprocessor, Compiler, Linker
8Preprocessor
- A preprocessor is a program that takes your
source file and outputs an intermediate file
(translation unit) before compilation, processing
commands starting with character - include statments contents of the include file
is inserted into the translation unit - define statements to define a preprocessor
variable - ifdef statements code in between the ifdef
statements are conditionally inserted
Class dice cout ltlt n DoSmthg()
include dice.h ifdef _ DEBUGFLAG cout
ltlt n endif DoSmthg()
9Preprocessor
- To prevent multiple inclusions of a header file,
we put other preprocessor directives to include
the file once - In this example, once dice.h is included _DICE_H
is defined, hence later include dice.h
statements wont have any effect on the
translation unit. - ifndef _DICE_H
- define _DICE_H
- .
- .
- endif
10Compiler
- The input to the compiler is the translation unit
generated by the preprocessor from a single
source file (e.g. main.cpp). - The compiler generates an object file (main.obj).
11Linker
- Combines all necessary object files and libraries
together to create an executable program. - Some of the object files may be combined together
to form libraries. - It is very advantageous to use libraries as they
are pre-tested code - Making libraries of your class
- make your project as statically linked library,
as opposed to a console application - no main function
- output is a lib file, e.g. taps.lib
12Static versus Dynamic (shared) Libraries
- When you compile a program, the libraries you
link statically are linked into the final
executable by the linker (remember that they are
pre- compiled) - Dynamic libraries are libraries that have the
library name embedded into the executable but the
library itself is not linked to the final
executable. Instead, when your program is
started, a program in the system (called a
dynamic loader) checks out which shared libraries
were linked with the program, loads them to
memory, and attaches them to the copy of your
program in memory.
13Advantages and Disadvantages of Dynamic (shared)
Libraries
- Advantages
- Since the library is not compiled into the
executable the executables tend to be smaller. - If you have a lot of programs that utilize the
same library - you might be able to save considerable disk space
- you only need to upgrade the library and then all
the programs that use it go on as if nothing has
changed - If the name of the library changes you can just
create a symbolic link to the old library name
and your code works just fine. - Disadvantages
- Launching your program (the one that uses the
library) is a bit slower
14Dynamic (shared) Libraries Details that you may
skip
- Shared libraries are linked into the program in
two stages. First, during compile time, the
linker verifies that all the symbols (again,
functions, variables and the like) required by
the program, are either linked into the program,
or in one of its shared libraries. However, the
object files from the dynamic library are not
inserted into the executable file. Instead, when
the program is started, a program in the system
(called a dynamic loader) checks out which shared
libraries were linked with the program, loads
them to memory, and attaches them to the copy of
the program in memory. - (Dis)Advantages The complex phase of dynamic
loading makes launching the program slightly
slower, but this is a very insignificant
drawback, that is out-weighted by a great
advantage - if a second program linked with the
same shared library is executed, it can use the
same copy of the shared library, thus saving a
lot of memory. For example, the standard "C"
library is normally a shared library, and is used
by all C programs. Yet, only one copy of the
library is stored in memory at any given time.
This means we can use far less memory to run our
programs, and the executable files are much
smaller, thus saving a lot of disk space as well.
- Special Drawback there is one drawback to this
arrangement. If we re-compile the dynamic library
and try to run a second copy of our program with
the new library, we'll soon get stuck - the
dynamic loader will find that a copy of the
library is already stored in memory, and thus
will attach it to our program, and not load the
new (modified) version from disk. There are ways
around this too
15Good Programming practices, Style, Debugging
- You will be responsible from the style/practice
guidelines listed here for all future
homeworks/projects.
16Programming
- Time spent as a software engineer will be spent
mostly on - maintaining and improving/upgrading code
- 80-90 time
- Yours or others
- Avg. of lines per application
- 1.2 million!
- It has to be written well so that
upgrading/maintaining is manageable - Some old programs are not improved because noone
understands the code!
17Good Programming Habits Overview
- Develop and test your code incrementally
- Code defensively
- Use modular code
- Include debugging code
- Include comments
18MUST Programming Habits Comments
- How much? Enough for someone to be able to
understand/modify your code in the future - When? Comment when first writing, then as you
test and seal code - You must use sufficient comments as illustrated
in the next slide in each of your homework
submissions from now on (penalty up to 20pts
over a 100pts-homework) - Slide 13 show some different comment styles, but
the fact that you must use comments for each
program unit remains unchanged - program header (10-20lines)
- each function and major section (5-10lines)
- each variable (1line)
- each paragraph (1line)
19MUST Programming Habits Comments
- /
- Purpose This program is a CD title maker.
- Usage cdmake songlist.txt
- Author Berrin Yanikoglu
- Date 22/2/2005
- Any known bugs It works fine for txt files but
crashes on empty input files - References Any source used besides the ones you
used etc.
/ - ...
- int totalTime //total time of the songs in CD in
seconds - ...
- /
- This function computes the remaining length in
the CD, after - writing all the songs in the input file.
- Input ...
- Returns ...
-
/ - int RemainingLength(....)
-
On the top (program)
For simple comments and variable explanations
For multiline comments and major section
headings
20Examples for various comment styles
21Good Programming Habits Naming Conventions
- - Naming Style suggestions
- balanceOwed //alternating - good for normal
vars - RecordsInFile //capitalized - good for Global
variables - MAX_STUDENT_NUM //all caps - good for constants
- See http//www.totse.com/en/technology/computer_te
chnology/hungnote.html - for a very structured convention that is used by
many software professional - if you are interested.
22Good Programming Habits Indentation...
- - - Indentation,
- s on the same line or next,
- your code should definitely be indented to
reflect the structure - whatever you choose, adopt and stick to one
format - - Use and location of the
- Use s for clarity - some programmers always use
it even for one line loops - Use s on the same line or next, but be
consistent - for (i0 i lt NUMCLASS i)
- ...
-
- or
- for (i0 i lt NUMCLASS i)
-
- ...
23Good Programming Habits Comments Bad Example
24Good Programming Habits Comments Example
- What you should do
- / swap the two corners /
- / swap the x coordinate /
- temp box1.x
- box1.x box2.x
- box2.x temp
- / swap the y coordinate /
- temp box1.y
- box1.y box2.y
- box2.y temp
-
25Good Programming Habits Clarity
- - - Do not code for compactness
- We are not encoding knowledge clarity is most
important - - Do not use obscure notations
- o 5 value 1
- o --o - o-- res (value 5)
(value 3) - //Use or -- only, on one line // do not even
do this, - even though it looks a little more
- innocent
- Do not confuse compactness with programming
efficiency. - A prime example for efficient programming is to
move out unneccessary code out of loops etc., so
that no extra computation is done. - Compactness refers to how short your code is. You
dont want to make your program unnecessarily
long (e.g. two if statements inside one another,
even if you could test for both at once, just as
clearly) but not so compact that it is cryptic
rule is to put only as much code on one line as
it is still clearly understandable.
26Good Programming Habits Code development
- - Develop and test incrementally
- Rather than writing the whole program first
- I see this as one of the biggest source of
frustration when trying to start a project or
homework. - - Code defensively
- e.g. Check to see if your memory allocation
request is granted or the file is opened... - if (p ! Null)
- ...
- Instead of using
- char x //is it signed (-128-128) or unsigned
(0-255)??? - which will depend on the compiler, it is best
to use the more precise type - unsigned char x
- In general, you should use the type that is
just enough and suitable for a particular
variable.
27Good Programming Habits Code development
- - Others code
- You will often have to deal with!
- Add comments as you understand the code, for your
sake and others in the future. - - Dont ignore warnings
- You should see no warnings when you compile
- E.g. int j - unused variable
- Either change your warning settings (see Warning
levels under Tools/Options) so that it does not
report these type of warnings (but then you are
responsible), so that more important warnings do
not get overlooked in a flood of warnings - Better eliminate them (go fix them)
- i.e. remove that variable etc.
28Debugging
29DebuggingDebug/Release
- You will normally develop under debug mode
(configuration), test, then release (optimized) - When you are developing with Debug option, the
compiler keeps track of symbolic information so
that you can watch over variable values, function
call hierarchy etc., at every step in your code. - Once you are done debugging and you will release
the code to the customer (or teacher), you want
to remove this information so that your
executable is smaller and faster. - You can set the active configuration from
- Project/Settings
- Build/Set Active Configuration
- Choose Debug mode or Optimize (Release mode)
30DebuggingProject Options
- - Setting Include and Source Directories
- You can specify where the compiler should look
for include files by - Tools/Options/Dirs/Source Files
- Specify where the .h and .cpp files should be
looked under - Put it at the end so your include files dont get
prefered over systems - - However, make sure that when you submit your
code, you have all the necessary files under the
project directory! - if you set the include directory location, many
include files will be found under some directory,
(e.g. C/Courses/CS201/Code/) when you develop
your project under another directory (e.g.
C/Courses/CS204/projects/pointers/). This has
the drawback that when you submit your code,
these files will not be in the local directory
and added to the zip. - In order to avoid this, you can look at each file
(right click, and properties) to see where they
are brought from, or you can make sure you have a
local copy under that project folder, or you can
test your homework submission on a separate
computer etc. - Your submitted project must open, find all
necessary files, and build with a few clicks!
31DebuggingDiagnostic Messages
- Sometimes, to debug your program, you will
include some diagnostic messages - e.g.
- void InsertOrdered(...)
- cout ltlt InsertOrdered called with ltlt n
- ...
- cout ltlt p-gtInfo
- ...
-
- void Delete(...)
- cout ltlt Delete called with ltlt n
- ...
- if (p NULL)
- cout ltlt p is NULL
- ...
-
32Debugging
- - When you think you are done debugging, you can
do one of the followings to turn debug statements
off (so that your program runs fast and without
debug messages of course) - 1) remove all this debug code (couts)
- Too much work, plus you may need them again when
some other problem shows up (if you need
debugging later on) - 2) make them conditional from the beginning. For
instance - if (debug 1)
- cout ltlt p-gtInfo
-
- - Then by setting the variable debug to 1 or 0 on
top of the program, or when you call the program,
you can control whether the statements will be
output. - - Tests such as if (debug) are still done
(slows the release version)! - - However this type of debug messages has the
advantage that they are interactive. In other
words you can run your big project and start
testing several aspects and you can have an
option of reading in the debug variable (or
several debug variables) as a parameter and
interactively start/stop outputting diagnostic
messages, without recompiling your code. This may
come in handy only for some big, interactif
projects.
33Debugging
- 3) or similarly you can turn them off. For
instance - if (0)
- cout ltlt p-gtInfo
- -
- 4) Best include debugging code with preprocessor
directives that are defined on top of the
program, or while the program is compiled
(Proj./Settings...). - ifdef _DEBUG
- cout ltlt p-gtInfo
- endif
34Preprocessor Directives under Debug
35Debugging
- ifdef _DEBUG
- cout ltlt p-gtInfo
- endif
- This code will only be compiled if the _DEBUG
flag is set during compilation - - _DEBUG is a standard preprocessor directive
which is defined in the DEBUG configuration, but
not defined in the Release configuration. - - So when the preprocessor parses your code
- - if the _DEBUG prep. directive is defined, it
will remove the ifdef commands and include the
lines between them (cout ltlt p-gtInfo) in your
program. - - if the _DEBUG prep. directive is NOT defined,
the preprocessor will remove the ifdef commands
AND the lines between them (cout ltlt p-gtInfo) out
of your program. So your program will be as if
you have never written those lines (no extra
tests done etc.)
36Debugging
- You can also use your own preprocessor
directives - You can either add them to the preprocessor
directives under Project/Settings/... As _DEBUG
was defined - Or you can define them with define SHORTDBG
etc. in the beginning of the file - //You can define or not define your debug
flags - define SHORTDBG
- //define MAJORDBG
- ...
- ifdef SHORTDBG
- cout ltlt Value of num ltlt num ltlt endl
- endif
- ifdef MAJORDBG
- cout ltlt Value of num ltlt num ltlt endl
- cout ltlt Value of info ltlt info ltlt endl
- cout ltlt Value of t ltlt t ltlt endl
- ...
- endif
37Debugging
- Best you can also make them conditioned on the
automatic flag _DEBUG - ifdef _DEBUG
- define SHORTDBG //this code wont be compiled
under release config - //define MAJORBG //this code wont be compiled
under release config - endif
- This way, if you are running under the release
config., you dont need to turn SHORTDBG or
MAJORDBG off. Since their definition wont even
be compiled, your flags wont be defined.
38Preprocessor Output debug version
n 1 cout ltlt n DoSmthg() DoSmthgElse()
n 1 ifdef _DEBUG cout ltlt
n endif DoSmthg() DoSmthgElse()
_DEBUG is defined as a preprocessor directive
under the Debug build of your code.
39Preprocessor Output release version
n 1 DoSmthg() DoSmthgElse()
n 1 ifdef _DEBUG cout ltlt
n endif DoSmthg() DoSmthgElse()
_DEBUG is not defined as a preprocessor directive
under the release build of your code.
40Debugging Assert statements
- - Use assert statements to check for conditions
that should be true (e.g. preconditions/postcondit
ions of a function) - include ltcassertgt //where assert is defined
- ...
- assert (p ! NULL) //any Boolean expression
- ...
- assert ( i lt j )
- If the inside expression evaluates to true,
execution continues. - If the inside expression evaluates to false,
execution is halted (program aborts). - A message is dumped at this point, something
along the lines of - assert ( i lt j ) at line 543 of file code.c
failed
41DebuggingAssert statements
- - assert statement should not replace checking
and handling errors (e.g. if the file is found or
not) - - provides compact checks for things that should
not happen (e.g. would cause the program crash) - - What to do (free variables etc.) when this
happens? - We will see exception handling in the coming
weeks for a neat organization of error handling
42DebuggingAssert statements
- - The assert statement can be "turned off" by
defining the preprocessor directive NDEBUG before
including cassert" - define NDEBUG // No Debug
- include ltcassertgt
- - If you use the release configuration, NDBUG is
already defined, so you dont need to define it
yourself.
43Preprocessor Directives under Release
44DebuggingAssert statements
- - The assert statement can be "turned off" in the
final build by defining NDEBUG before including
cassert" - //NDEBUG defined by configuration or by you
- include ltcassertgt
- In cassert, NDEBUG preprocessor directive is
checked - If it is defined, the assert statement evaluates
to an empty statement, which is what we want for
the Release version, so the tests do not slow the
program and things that may not cause a crash is
not unnecessarily reported to the customer. - If it is not defined (Debug mode), the assert
statements stay and do the tests as intended.
45assert.h
- ...
- ifdef NDEBUG
- define assert(exp) ((void)0) //define it
to be empty - else
- ...
- define assert(exp) (void) ( (exp)
(_assert(exp, __FILE__, __LINE__), 0) ) - endif / NDEBUG /
- Note You dont need to understand how this code
works but understand the idea of how NDEBUG is
checked and used in assert.h (called by cassert).
46Preprocessor Output debug version
n 1 ifdef _DEBUG cout ltlt
n endif DoSmthg() DoSmthgElse() assert(p gt
0) n
n 1 cout ltlt n DoSmthg() DoSmthgElse()
(void) ( (exp) (_assert(exp, __FILE__,
__LINE__), 0) n
47Preprocessor Output release version
n 1 DoSmthg() DoSmthgElse() void(0)
n
n 1 ifdef _DEBUG cout ltlt
n endif DoSmthg() DoSmthgElse() assert(p gt
0) n
48Debugging Example
- include ltiostreamgt
- include ltcassertgt
- using namespace std
- /
- This program shows various debug alternatives
that students can - play with.
- Author Berrin Yanikoglu
- Date 24/2/2005
- Bugs No known
/ - /
/ - // a function you received from a colleague, you
don't know - //fully what it does
- /
/ - void func1(int n)
49- /
/ - //main function
- /
/ - void main()
-
- char c //to receive user input
- int count 0
- ifdef _DEBUG
- //this code will be executed under the DEBUG
config. only - define DEBUG1 //less detailed debugging
- define DEBUG2 //more detailed debugging
- endif
- ifdef DEBUG1
- //this code will be executed under the DEBUG
config. only - cout ltlt "debugging comment conditioned on
DEBUG1" ltlt endl - endif
50Miscellaneous Info
51DebuggingVC environment
- Read VChelp.doc for some more and go to
recitations for more info and practice on these. - Set a breakpoint
- F9 or Edit/Breakpoints
- Run until next breakpoint
- F5
- Step in F11
- Step out Shift-F11
- Step over F10
- Run to cursor Ctrl-F10
- (see the MSDN library for more details)
- Inspecting variables
- Variables window
- Watch window
- Quick watch
- Cursor over text
- Call stack
52Misc. redirecting input/output
- Directing standard output
- Program/Settings/Debug
- gt ./filename
- The output will go to the file (cout ltlt
statements), so you dont have to cut and paste
the console. - Passing arguments to the program
- Program/Settings/Debug
- lt ./filename 2
- The filename and 2 (in general, any
parameters that you want to use while calling
your program) will be passed in argv to the main
function (as in hw1).
53Misc. libraries
- Creating a statically linked library
- make your project as statically linked library,
as opposed to a console application - Add the files you want to use (Project/Add File/
- No main function
- Build the output is a lib file, e.g. taps.lib
- Using this library
- Create your project (e.g. hw0) that will use this
library - Add a main file etc (that does the work)
- Add the library as another file to the project
(Project/Add File) - Compile
- It is just as adding dice.cpp etc. To the
project, but in one easy step. - You may create a static versus dynamic library,
in general. But we deal with only statically
linked libraries for now (and for hw0).
54Misc. librariesStatic versus Dynamic (shared)
Libraries
- When you compile a program, static libraries are
linked into the final executable by the linker. - Dynamic libraries are libraries that have the
library name embedded into the executable but the
library itself is not compiled into the binary
file. - Instead, when your program is started, a
program in the system (called a dynamic loader)
checks out which shared libraries were linked
with the program, loads them to memory, and
attaches them to the copy of your program in
memory. - Since the library is not compiled into the
executable the executables tend to be smaller. - Upgrading libraries is easier.
- If the name of the library changes you can just
create a symbolic link to the old library name
and your code works just fine. - If you have a lot of programs that utilize the
same library - you might be able to save considerable disk space
- you only need to upgrade the library and then all
the programs that use it go on as if nothing has
changed