CS330 : Frequently Asked Questions

Steven J. Zeil

Last modified: Aug 7, 2018
Contents:

This is a collection of questions (and answers!) that have arisen repeatedly in some of my past classes.

1 General Programming Questions

1.1 What’s all this “foo” and “bar” stuff?

There is a long-standing tradition in computer science of using certain words as sample variable/function/whatever names. Just as a mathematician might use “x” or “y” whenever an arbitrary variable name is needed, computer scientists tend to use “foo”, “bar”, and “baz”, in that order. Check out this entry in the Hacker’s Dictionary for a discussion of the origin of these terms.

1.2 I’m not sure I have a correct algorithm to solve this problem. How do I check before writing and debugging the code?

The worst thing you can do is to simply start throwing C++ statements around at random trying to guess at an algorithm design.

  1. Research - is there a known algorithm for addressing this kind of problem? Check your text and the lecture notes. Check the web.

    Even if you find something, you will likely have to adapt it to the details of the problem at hand, but this can get you started.

  2. Work at least a few examples by hand so that you have some simple examples of possible inputs and expected outputs at hand.

  3. Draw pictures of the input and output data structures (i.e., desk checking ). Take note of all the differences between the input and output pictures. Think about the programming steps that would be required to change the input pictures into the output pictures.

  4. Use a systematic procedure for design, such as stepwise refinement, a.k.a. top-down design, to derive a new algorithm that solves your problem.

  5. As you work, update your desk checking pictures to make sure that your algorithm steps are moving you in the right direction.

1.3 My program crashed. How do I find out why?

There’s no easy answer to that. Here’s what I do, though, when faced with a crash that I just don’t understand:

  1. Look at the output produced before the crash. That can give you a clue as to where in the program you were when the crash occurred.

  2. Run the program from within a debugger (or here and here ).

    Don’t worry about breakpoints or single-stepping or any of that stuff at first. Just run it.

    When the crash occurs, the debugger should tell you what line of code in what file eas being executed at the moment of the crash.

    Actually, it’s not quite that simple. There’s a good chance that the crash will occur on some line of code you didn’t actually write yourself, deep inside some system library function that was called by some other system library function that was called by some other … until we finally get back to your own code. That crash occurred because you are using a function but passed it some data that was incorrect or corrupt in some way.

    Your debugger should let you view the entire runtime stack of calls that were in effect at the moment of the crash. So you should be able to determine where the crash occurred. That’s not as good as determining why, but it’s a start.

  3. Take a good look at the data being manipulated at the location of the crash. Are you using pointers? Could some of them be null? Are you indexing into an array? Could your index value be too large or negative? Are you reading from a file? Could the file be at the end already, or might the data be in a different format than you expected?

    If you used a debugger to find the crash locations, you can probably move up and down the stack and to view the values of variables within each active call. This may give a clue about what was happening.

  4. Form some hypotheses (take a guess) as to what was going on at the time of the crash. Then test your hypothesis!

1.4 Why do compilers’ error messages often give the wrong line number, or even the wrong file?

A compiler can only report where it detected a problem. Where you actually committed a mistake may be someplace entirely different.

The vast majority of error messages that C++ programmers will see are

Let’s look at these from the point of view of the compiler.

1.4.1 Syntax errors

Assume that the compiler has read part, but not all, of your program. The part that has just been read contains a syntax error. For the sake of example, let’s say you wrote:

x = y + 2 * x // missing semi-colon

Now, when the compiler has read only the first line, it can’t tell that anything is wrong. That’s because it is still possible, as far as the compiler knows, that the next line of source code will start with a “;” or some other valid expression. So the compiler will never complain about this line.

If the compiler reads another line, and discovers that you had written:

x = y + 2 * x // missing semi-colon
++i;

it still won’t conclude that there’s a missing semi-colon. For all it knows, the “real” mistake might be that you meant to type “+” instead of “++”.

Now, things can be much worse. Suppose that inside a file foo.h you write

class Foo {
    ⋮
   Foo();
   int f();
   // missing };

and inside another file, bar.cpp, you write

#include "foo.h"

int g() { ... }

void h(Foo) { ... }

int main()  { ... }

Where will the error be reported? Probably on the very last line of bar.cpp! Why? Because until then, it’s still possible, as far as the compiler knows, for the missing “};” to come, in which case g, h, and main would just be additional member functions of the class Foo.

So, with syntax errors, you know only that the real mistake occurred on the line reported or earlier, possibly even in an earlier-\#include’d file.

1.4.2 undeclared and undefined symbols

See this discussion.

1.4.3 type errors

When you use the wrong object in an expression or try to apply the wrong operator/function to an object, the compiler may detect this as a type mismatch between the function and the expression supplied as the parameter to that function. These messages seem to cause students the most grief, and yet the compiler is usually able to give very precise descriptions of what is going wrong. The line numbers are usually correct, and the compiler will often tell you exactly what is going wrong. That explanation, however, may be quite lengthy, for three reasons:

  1. Type names, especially when templates are involved, can be very long and messy-looking.

  2. Because C++ allows function overloading (multiple functions with the same name, as long as they take different kinds of parameters), there may be many functions with the same name. The compiler will have to look at each of these to see if any one matches the parameter types you supplied. Some compilers report on each function tried, explaining why it didn’t match the parameters in the faulty call.

  3. If the function call was itself produced by a template instantiation or an inline function, then the problem is detected at the function call (often inside a C++ standard library routine) but the actual problem lies at the place where the template was used/instantiated. So most compilers will list both the line where the error was detected and all the lines where templates were instantiated that led to the creation of the faulty call.

So, to deal with these, look at the error message on the faulty function call. Note what function/operator name is being complained about. Then look at the line where the faulty call occurred. If it’s inside a template or inline function that is not your own code, look back through the “instantiated from” or “called from” lines until you get back into your own code. That’s probably where the problem lies.

Here’s an example taken from a student’s code:

g++ -g -MMD -c testapq.cpp
/usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/../../../../include/g++-3/
stl_relops.h: In function `bool operator ><_Rb_tree_iterator<pair<const 
 PrioritizedNames,int>,pair<const PrioritizedNames,int> &,pair<const 
 PrioritizedNames,int> *> >(const _Rb_tree_iterator<pair<const 
 PrioritizedNames,int>,pair<const PrioritizedNames,int> &,pair<const 
 PrioritizedNames,int> *> &, const _Rb_tree_iterator<pair<const 
 PrioritizedNames,int>,pair<const PrioritizedNames,int> &,pair<const 
 PrioritizedNames,int> *> &)':
adjpq.h:234:   instantiated from `adjustable_priority_queue<
 PrioritizedNames,map<PrioritizedNames,int,CompareNames,allocator<int> >,
 ComparePriorities>::percolateDown(unsigned int)'
adjpq.h:177:   instantiated from `adjustable_priority_queue<PrioritizedNames,
 map<PrioritizedNames,int,CompareNames,allocator<int> >,
 ComparePriorities>::makeHeap()'
adjpq.h:84:   instantiated from here
 /usr/local/lib/gcc-lib/sparc-sun-solaris2.7/2.95.2/../../../../include/
 g++-3/stl_relops.h:43: no match for `const _Rb_tree_iterator<pair<const 
 PrioritizedNames,int>,pair<const PrioritizedNames,int> &,pair<const 
 PrioritizedNames,int> *> & < const _Rb_tree_iterator<pair<const 
 PrioritizedNames,int>,pair<const PrioritizedNames,int> &,pair<const 
 PrioritizedNames,int> *> &'

Now, that may look intimidating, but that’s mainly because of the long type names (due to template use) and the long path names to files from the C++ standard library. Let’s strip that down to the essentials:

g++ -g -MMD -c testapq.cpp
stl_relops.h: In function `bool operator >:
adjpq.h:234:   instantiated from `percolateDown(unsigned int)'
adjpq.h:177:   instantiated from `makeHeap()'
adjpq.h:84:   instantiated from here
stl_relops.h:43 no match for ... < ...

This one is actually worse than most error messages, because it’s easy to miss the “<” operator amidst all the < ... > template markers.

The problem is a “no match for” a less-than operator call in line 43 of a template within the standard library file stl_relops.h. But that template is instantiated from the student’s own code (adjpq.h) and so the thing to do is to look at those three lines (234, 177, and 84) for a data type that is supposed to support a less-than operator, but doesn’t.

1.4.4 const errors

Technically, “const”-ness is part of a type, so while sometimes these get special messages of their own, often they masquerade as ordinary type errors and must be interpreted in the same way.

1.5 What are formal and actual parameters?

The formal parameters of a function are the parameter names that are declared in the function header and that are used when we write the function body. For example, in the code

int sequentialInsert (T a[], unsigned& n, const T& x)
// insert x into sorted position within a,
//   with a already containing n items.
//   Return the position where inserted.
{
  int i = n;
  while ((i > 0) && (x < a[i-1]))
      {
       a[i] = a[i-1];
       i = i - 1;
      }
  a[i] = x;
  ++n;
  return i;
}   

the formal parameters are named a, n, and x. The actual parameters of a call to a function are the values passed by the caller. So, in the call

k =  sequentialInsert (myArray, size-1, value);

the actual parameters are myArray, size-1, and value. Note that formal parameters are always just names. Actual parameters can be simple names or arbitrarily complicated expressions.

2 The C++ Programming Language

2.1 What’s the odd expression with the ‘?’ and ‘:’ ?

You’re probably looking at a conditional expression. It’s a convenient shorthand for an if-then-else structure inside an ordinary expression. A typical example would be

x = (x < 0.0) ? -x : x;

The part before the ‘?’ is the condition and is evaluated first. If the condition is true, then the then-part expression (between the ‘?’ and the ‘:’) is evaluated and the result used as the value of the entire expression. If, however, the condition is false, then the else-part (after the ‘:’) is evaluated and that result is used as the value of the entire expression. This assignment, then, replaces x by its own absolute value. The whole thing, then, is equivalent to

double temp;
if (x < 0.0)
  temp = -x;
else
  temp = x;
x = temp;

A conditional expression can apear inside other expressions, anywhere a value of the same type as its then-part and else-part might appear:

x = sqrt((x < 0.0) ? -x : x);

2.2 How do I convert a string to a character array (or a character array to string)?

To get a character array from a std::string, use the string’s c_str() function:

std::string str;
   ⋮
char* cstr = str.c_str();

You will often see this done with older library functions that were originally designed to work with character arrays and not yet updated to work with strings:

copyFile.cpp
void copyFile (string fileName)
{
   ifstream input (fileName.c_str()); // open an input file;
   ofstream output ("output.txt"); // No c_str() required - "output.txt" is a
                                   //    character array, not a string.
   string line;
   getline (input, line);
   while (input) 
   {
      output << line << endl;
      getline (input, line);
   }   
}

Going in the opposite direction is even simpler. The string class has a constructor for building strings from character arrays, so this takes palce automatically most of the time:

void copyFile (string fileName);
   ⋮
copyFile ("input.dat");  // automatically converted to std::string

2.3 How do I convert a string to a number (or a number to a string)?

There are some quick-and-dirty functions for doing this in <cstdlib> for converting to numbers:

#include <cstdlib>
using namespace std;
   ⋮
int i = atoi("123");
double f = atof("3.14159");

Now, these functions actually convert from character arrays, not strings, so if you have a string you need to convert to a character array:

#include <cstdio>
#include <string>
using namespace std;
   ⋮
string s1 = "123";
string s2 = "3.14159";
   ⋮
int i = atoi(s1.c_str());
double f = atof(s2.c_str());

If you need to go in the other direction, or if you need to deal with strings with unusual formatting, then there is a more general technique. In fact, you can convert any datatype that has << and >> I/O operators to and from strings by reading from and writing into a string. The istringstream is an input stream that reads from a string:

#include <sstream> // provides istringstream and ostringstream
#include <string>
using namespace std;
   ⋮
string s1 = "123 3.14159";
   ⋮
istringstream in (s1); // create a stream reading from s1
int i;
double f;
in >> i >> f;  // i will contain 123 and f will contain 3.14159

The ostringstream is an output stream that writes into a string:

#include <sstream> // provides istringstream and ostringstream
#include <string>
using namespace std;
   ⋮
string s1;
ostringstream out (); // create a stream writing into a string
int i = 245;
double f = 1.2;
out << i << ":" << f;
string s = out.str();  // Retrieve the string we have written
cout << s << endl;     // Prints "245:1.2"

Again, let me point out that this stringstream approach can be used to convert between string and any data type that you can read and write.

2.4 What is the difference between a declaration and a definition?

Pretty much everything that has a “name” in C++ must be declared before you can use it. Many of these things must also be defined, but that can generally be done at a much later time. You declare a name by saying what kind of thing it is:

 const int MaxSize;          // declares a constant
 extern int v;               // declares a variable
 void foo (int formalParam); // declares a function (and a formal parameter)
 typedef Bar* BarPointer;    // declares a type name
 using BarPointer = Bar*;    // declares a type name (same as previous example)

 class Bar{ ... };               // declares a class
 {
    ⋮
    void bar (int formalParam);  // declares a member function within a class
    ⋮
    int z;                       // declares a data member within a class
 };    

In most cases, once you have declared a name, you can write code that uses it. Furthermore, a program may declare the same thing any number of times, as long as it does so consistently. That’s why a single .h file can be included by several different .cpp files that make up a program — most .h files contain only declarations. You define constants, variables, and functions as follows:

 const int MaxSize = 1000;                   // defines a constant
 int v;                                      // defines a variable
 void foo (int formalParam) {++formalParam;} // defines a function
 
 void Bar::bar(int formalParam);  // defines a member function within a class

A definition must be seen by the compiler once and only once in all the compilations that get linked together to form the final program.

A definition is itself also a declaration (exception: member functions within classes).

2.5 What goes in a .h file? What goes in a .cpp file?

The short answer is that a .h file contains shared declarations, a .cpp file contains definitions and declarations that you don’t want to share..

It’s important that you understand difference between declarations and definitions.

Never, ever, ever name a .cpp file in an #include.

That defeats the whole purpose of a C++ program structure.

2.6 What is an inline function?

When we define a function, it is usually compiled into a self-contained unit of code. For example, a function

int foo(int a, int b)
{
  return a+b-1;
}

would compile into a block of code equivalent to

stack[1] = stack[3] + stack[2] - 1; 
jump to address in stack[0]

where the “stack” is the runtime stack a.k.a. the activation stack used to track function calls at the system level, stack[0] is the top value on the stack, stack[1] the value just under that one, and so on. A function call like

  x = foo(y,z+1);

would be compiled into a code sequence along the lines of

push y onto the runtime stack; 
evaluate z+1; 
push the result onto the runtime stack
push (space for the return value) onto the runtime stack 
save all CPU registers
push address RET onto the runtime stack 
jump to start of foo's body 
RET: x = stack[1] 
pop runtime stack 4 times 
restore all CPU registers

As you can see, there’s a fair amount of overhead involved in passing parameters and return address information to a function when making a call. The amount of time spent on this overhead is really all that large. If the function body contains several statements in any kind of loop, then the overhead is probably a negligable fraction of the total time spent on the call.

class Foo {
private:
   int bar;
public:
   int getBar ();
   void setBar (int);
};

int Foo::getBar ()  {return bar;}

void Foo::setBar (int b) {bar = b;}

But many ADTs have member functions that are only one or two lines long, and often trivial lines at that. For these functions, the overhead associated with each call may exceed the time required to do the function body itself. Furthermore, because these functions are often the primary means of accessing the ADT’s contents, sometimes these functions get called thousands of times or more inside the application’s loops.

For these kinds of trivial functions, C++ offers the option of declaring them as inline.

class Foo {
private:
   int bar;
public:
   int getBar () {return bar;}  
   void setBar (int);
};

inline
void Foo::setBar (int b) {bar = b;}

An inline function can be written one of two ways. First, it can be written inside the class declaration. Second, we can place the reserved word inline in front of the function definition written in its usual place outside the class declaration. When we make a call to an inline function, the compiler simply replaces the call by a compiled copy of the function body (with some appropriate renaming of variables to avoid conflicts). So, if we have

inline int foo(int a, int b)
{
  return a+b-1;
}

and we later make a call

  x = foo(y,z+1);

This would be compiled into a code sequence along the lines of

evaluate z+1, storing result in tempB 
evaluate y + tempB - 1, storing result in x

Most of the overhead of making a function call hs been eliminated.

Inline functions can reduce the run time of a program by removing unnecessary function calls, but, used unwisely, may also cause the size of the program to explode. Consequently, they should be used only by frequently-called functions with bodies that take only 1 or 2 lines of code. For larger functions, the times savings would be negligible (as a fraction of the total time) while the memory penalty is more severe, and for infrequently used functions, who cares?

Inlining is only a recommendation from the programmer to the compiler. The compiler may ignore an inline declaration and continue treating it as a conventional function if it prefers. In particular, note that inlining of functions with recursive calls is impossible, as is inlining of most virtual function calls. Many compilers will refuse to inline any function whose body contains a loop. Others may have their own peculiar limitations.

2.7 Why is operator++ sometimes declared with an int parameter?

The ++ and -- operators are unusual in that they can be written in either prefix (++x, --x) or postfix (x++, x--) form. Whether you write ++x or x++, the value of x is increased by 1. But when you write a ++ expression inside another expression, its return value depends on whether you used the prefix or postfix form.

So, for example, the code

int i = 0; 
int j = 0;
cout << ++i << ' ' << j++ << endl;
cout << i << ' ' << j << endl;

would print

1 0
1 1

Now that’s all very well for the builtin ++ for int, but what happens when we write ++ for our own classes? Like most operators, ++ can be thought of as a shorthand for a function named operator++, so it’s not too hard to see that we can say:

class SomethingWeCanIncrement
{
  ⋮
  SomethingWeCanIncrement& operator++ (); 
  ⋮
};

but, somewhat late in the game, the designers of C++ realized that they had neglected to provide a syntax for indicating whether a unary operator was prefix or postfix. This is only a problem for ++ and --, because these are the only operators that can be written in both forms. The solution they came up with is a complete kludge. If you declare

const MyIncrementableClass operator++();
const MyIncrementableClass operator--();

you are declaring the prefix operators. If you declare

MyIncrementableClass operator++(int);
MyIncrementableClass operator--(int);

you are declaring the postfix operators.

What do you do with the int parameter for the postfix operators?

Absolutely nothing! It’s just a dummy parameter used to distinguish the prefix and postfix forms. Finally, note that the prefix forms return a reference. The postfix forms return a non-reference value. That’s because the prefix forms are returning the value that has been incremented/decremented. That value exists, so it’s easy to return:

class MyIncrementableClass {
   ⋮
  const MyIncrementableClass operator++() {
        ⋮
     // do what you need to do to increment it
        ⋮
     return *this;
  }
   ⋮

On the other hand, the postfix form returns the value before the increment/decrement takes place. Usually the only way to do that is to make a copy of that value first, then do the increment, then return the copied value.

class MyIncrementableClass {
   ⋮
  const MyIncrementableClass operator++(int) {
        MyIncrementableClass clone = *this; // save old value
        operator++();                       // increment this
        return clone;                       // return the old value
  }
   ⋮

2.8 What is the Rule of the Big 3?

The Big 3 in C++ class design are the copy constructor, destructor, and assignment operator.

The Rule of the Big 3 states that, if you ever find yourself needing to provide your own version of any one of the Big 3, you should provide your own version of all three.

The C++ compiler will provide its own version of these if the programmer does not do so. However, the compiler-generated versions for a class are usually inappropriate if

  1. The class has data members that are pointers, and
  2. The pointers denote data that should not logically be shared.

Like most such rules, there can be exceptions, but programmers should only violate this rule knowingly and after full consideration of the possible consequences.

2.9 I have other C++ questions.

3 C++ Compilers and IDEs

3.1 How can I install a compiler and IDE on my own PC?

For Windows, OS/X, & Linux PCs:

And another option for Windows 10 only:

Or, from Windows and OS/X, you can run a Linux virtual machine on your PC and install your compiler and IDE there.

3.2 How do I use a make file in Eclipse or Code::Blocks?

A make file contains instructions on how to compile the code of a project. These instructions are interpreted by a program called make, which is covered in CS252. make is what we call a build manager, a program designed to automate the steps in building a software project.

If you have a complicated project, creating a make file can allow you to avoid typing long sequence of commands to compile all of your code.

Alternatively, some instructors provide make files with their assignments. You will recognize these because they are titled makefile or Makefile. Using an instructor-supplied make file can help guarantee that you are compiling your code using the same settings the instructor will use when grading your code.

But most IDEs have their own build managers “built in”. In many cases that will be good enough, particularly if you take the time to set your compiler options to the appropriate values.

But sometimes you will really need to or want to use that make file.

3.2.1 Using make files from the command line.

Assuming that you are on a machine with the make program installed, just type

make

to build your project. If that does not work, try

make all

Type

make clean

to clean up (remove anything produced automatically, leaving the source code unchanged).

“all” and “clean” above are examples of make file targets, options written in to the make file to trigger a series of commands. Actually, there aren’t hard and fast rules on the target names. But most people who write make files set them up so that, by default, make and/or make all builds the project and make clean clean up after it. If those don’t work for you, you’ll have to ask the author of the make file or read it yourself.

3.2.2 Using make files from Eclipse

When you create a C++ project in Eclipse, among your early options is create an “Executable” or a “Makefile project”. Choose “Makefile project” … “Empty Project”. (“Empty” in this case means that you already have a makefile and some C++ code and don’t want Eclipse to set up a “hello-world” style starter for you.)

If you have already created your project as an “Executable” (which means that you requested that Eclipse use its own built-in build manager), this is easily remedied.

  1. Take note of what directory the project is stored in. If you aren’t sure, use Project -> Properties to find out.

  2. In the Project Explorer list on the left, right-click on your existing C++ project and select “Delete”.

    Now, we only want to delete the project settings from Eclipse, not your source code. So when the box pops up to confirm the deletion, make sure that the “Delete project contents on disk” is not checked.

  3. Now go back and add that same directory as a new C++ Empty Makefile project, as described earlier.

3.2.3 Using make files in Code::Blocks

  1. Create your C++ project as usual.

  2. Then go to Project -> Properties -> Project settings, and by “Makefile:”, make sure that the file listed is the appropriate location and spelling of of your make file, then put a check in the “This is a custom Makefile” box.

  3. Now go to the “Build targets” tab.

    By default, Code::Blocks uses make file targets “Debug” and “Release”, but those are rarely seen in practice.

    Use the Add button to add the “real” targets of your makefile. (As noted earlier, “all” and “clean” are among the most common, but you may have to read the make file to be sure.)

    Optionally, you can use the “Delete” button to remove the “Debug” and “Release” targets.

  4. Under “Output filename”, enter the name (and location) of the executable produced by the makefile.

    • If you don’t know how to read make files, you may have to run it once to find out.

  5. Click OK to save the setting changes.

To compile your code, go to the Build menu and then Select target to select “all”. Then click the usual build button.

To clean up your project directory, go to the Build menu and then Select target to select “clean”. Then click the same build button.

3.3 How do I activate C++11 features when compiling?

By now, much of the C++ code you are likely to encounter will make use of features introduced in the C++ 2011 standard (or 2014 – there is also a 2017 standard, but compilers have not caught up with that). Most compilers default to the 1998 language definition. You will need to be sure that you are compiling with the appropriate options set.

In the GNU g++ and Clang compiler suites, the relevant compiler option to activate C++11 features is

-std=c++11

If you are typing your compiler commands directly at the command line, just add this.

But, more likely, you are using some sort of builder, either make or an IDE (Code::Blocks or Eclipse) or a makefile invoked from an IDE.

3.3.1 make Files

If you are using make, your makefile will generally have a list of options provided explicitly for your uses of g++. Just add -std=c++11 to that list.

3.3.2 CodeBlocks

  1. From the Settings menu, select “Compiler…”

  2. You should be on the “Global compiler settings” tab. If not, select it.

  3. Put a checkmark by the option:

      Have g++ follow ... C++11 ISO ...
    
  4. Click OK to accept the changes. Then from the “Project” menu select “Project Clean”, then rebuild your project.

3.3.3 Eclipse (default C++ builder)

If you are using Eclipse and specified “C++ project”, you have requested that Eclipse use its default builder. You set your compilation options from the project settings menu.

  1. Right-click on your project and select “Properties” or select “Properties” from the “Project” menu.

  2. Click on “C/C++ Build” then “Settings”. Select the “…C++ Compiler” that you are using.

  3. Select “Dialect”, and choose “ISO C++11”.

  4. Click OK to accept the changes. Then from the “Project” menu select “Project Clean”, then rebuild your project.

3.3.4 Eclipse (makefile project)

If you are using Eclipse and specified “Makefile project with existing code”, you have requested that Eclipse run “make” to build your code. Edit your makefile as described above.

You may find, however, that the Eclipse editor reports errors as you are editing your code that do not actually arise when you compile/build. That may be because the Eclipse editor is using pre-2011 rules. To fix,

  1. Right-click on your project and select “Properties” or select “Properties” from the “Project” menu.

  2. Select “C/C++ General” => “Preprocessor Include Paths…”. Look at the “Providers” tab. Look for the entry that seems to most directly describe your compiler (e.g., “CDT GCC Built-in Compiler Settings CygWin” or “CDT GCC Built-in Compiler Settings MinGW”) and use the “MoveUp” button to position this at the top of the list

  3. Click OK to accept the changes. Then from the “Project” menu select “C/C++ Index” => “Rebuild”. Repeat the rebuild if necessary.

  4. From the “Project” menu select “Project Clean”, then rebuild your project.

3.4 How do I set compiler flags and options?

For most assignments, I recommend the following options:

-g -std=c++11 -Wall -D_GLIBCXX_DEBUG -fsanitize=address

If you are typing your compiler commands directly at the command line, just add this.

But, more likely, you are using some sort of builder, either make or an IDE (Code::Blocks or Eclipse) or a makefile invoked from an IDE.

3.4.1 make Files

If you are using make, your makefile will generally have a list of options provided explicitly for your uses of g++. Edit them to match the above.

3.4.2 CodeBlocks

  1. From the Settings menu, select “Compiler…”

  2. You should be on the Global compiler settings tab. If not, select it. Within that, look for a “Compiler Flags” tab. Again, you are probably already on it. If not, select it.

  3. Put a checkmark by each of the following:

       Have g++ follow ... C++11 ISO ...
    
       Enable all common compiler warnings
    
       Enable extra compiler warnings
    
       Enable Effective-C++ warnings
    
  4. Now go to the #defines tab. In the text box enter, on a line by itself,

       _GLIBCXX_DEBUG
    

    Be sure to get both of the underscore (_) characters in there.

  5. Click OK to accept the changes. Then from the “Project” menu select “Project Clean”, then rebuild your project.

3.4.3 Eclipse (default C++ builder)

If you are using Eclipse and specified “C++ project”, you have requested that Eclipse use its default builder. You set your compilation options from the project settings menu.

  1. Right-click on your project and select “Properties” or select “Properties” from the “Project” menu.

  2. Click to open the “C/C++ Build” list, then click on “Settings”. Select the “…C++ Compiler” that you are using.

  3. Select “Dialect”, and choose “ISO C++11”.

  4. Select “Warnings” annd check the options for -Wall and -Wextra.

  5. Select “Miscellaneous” and add -Weffc++ to the “Other flags”.

  6. Select “Preprocessor” and, on the “Defined symbols” box, use the icon with the green plus sign to add

        _GLIBCXX_DEBUG
    

    Be sure to get both of the underscore (_) characters in there.

  7. Click OK to accept the changes. Then from the “Project” menu select “Project Clean”, then rebuild your project.

3.4.4 Eclipse (makefile project)

If you are using Eclipse and specified “Makefile project with existing code”, you have requested that Eclipse run “make” to build your code. Edit your makefile accordingly.

You may find, however, that the Eclipse editor reports errors as you are editing your code that do not actually arise when you compile/build. That may be because the Eclipse editor is using pre-2011 rules. To fix,

  1. Right-click on your project and select “Properties” or select “Properties” from the “Project” menu.

  2. Select “C/C++ General” => “Preprocessor Include Paths…”. Look at the “Providers” tab. Look for the entry that seems to most directly describe your compiler (e.g., “CDT GCC Built-in Compiler Settings CygWin” or “CDT GCC Built-in Compiler Settings MinGW”) and use the “MoveUp” button to position this at the top of the list

  3. Click OK to accept the changes. Then from the “Project” menu select “C/C++ Index” => “Rebuild”. Repeat the rebuild if necessary.

  4. From the “Project” menu select “Project Clean”, then rebuild your project.

3.5 How do I supply command line parameters when executing my programs?

Often you will be writing programs that take “command line parameters” as part of their inputs.

Of course, if you are executing a program from the command line, you just type the parameter values on the command line (hence the name!), e.g.,

./myProgram ../testData/myTestData.txt 23

But what if you are launching your program from an IDE?

3.5.1 Code::Blocks

Before running your program, from the Project menu, select “Set programs' arguments...”. In the “Program Arguments” box, enter your parameters, one per line. Click OK when done.

Run the program.

3.5.2 Eclipse

  1. After you have successfully compiled your code, click on your executable binary in the Project Explorer). Then, from the Run menu, select Run configurations...

    You’ll see a list of different project types, one of which should be “C/C++ Application”.

    • Underneath that, you might already have a configuration for this program (Clicking on a configuration will show you what project and what executable file it is associated with.

    • If not, select “C/C++ Application”, then at the cop of the columm click on "_New launch configuration`".

  2. On the “Arguments” tab, enter your command line parameters into the “Program Arguments” box.

  3. Click Run to save these arguments and launch your program.

Video of this procedure (for Java, but the procedure is similar)

3.6 How do I get my program to read from a file instead of from the keyboard?

At the command line, this is called input redirection and is done by appending

< location_of_input_file 

to the end of the command launching the program. You can read more about this in CS252, and it works the exact same way in a Windows command-line session.

What if you are launching your program from an IDE?

3.6.1 Code::Blocks

Can’t really be done.

What you can, do, however, is to

  1. Open your file of input text in the Code::Blocks editor.

  2. Run the program.

  3. Then, when it pauses for input, instead of typing the input directly, copy-and-paste lines of text from the input file in the editor into the running program.

    • You can usually copy-and-paste many lines of input at once, because the underlying run-time system will simply buffer up unused input until later input statements are reached.

3.6.2 Eclipse

After you have successfully compiled your code, click on your executable binary in the Project Explorer). Then, from the Run menu, select Run configurations...

You’ll see a list of different project types, one of which should be “C/C++ Application”.

On the “Common” tab, under “Standard input and output”, click to select the “Input” box, then use one of the three buttons on the line below to selectthe file of input data you want supplied as the standard input.

Click Run to save these arguments and launch your program.

4 C++ Error Messages

4.1 AddressSanitizer: attempting free on address which was not malloc()-ed

The Address Sanitizer (activated when compiling with a -fsanitize=... option) has detected that the program attempted to delete a block of memory that

Examine the message details for the source code files and locations at which the problem was detected.

4.2 AddressSanitizer: heap-buffer-overflow

The Address Sanitizer (activated when compiling with a -fsanitize=... option) has detected that the program attempted to access data in a block of memory that has been properly allocated. This can be caused by any of

This error is often detected well after the offending action has taken place, making it fairly difficult to debug.

4.3 AddressSanitizer: heap-use-after-free

The Address Sanitizer (activated when compiling with a -fsanitize=... option) has detected that the program attempted to access data in a block of memory that has been deleted.

4.4 AddressSanitizer: NullPointerAccess

The Address Sanitizer (activated when compiling with a -fsanitize=... option) has detected that the program attempted to retrieve or store data via a null pointer.

Examine the message details for the source code files and locations at which the problem was detected.

4.5 AddressSanitizer: SEGV

SEGV stands for segmentation error.

4.6 attempt to subscript container with out-of-bounds index

Indicates that one of the std: library container functions has detected an attempt to access or store data that is out of range (e.g., trying to get the N’th item from a vector that only holds N-1 items).

The remainder of the error message will list files and line numbers that may help you trace the point at which the problem was detected.

4.7 attempt to dereference a singular iterator.

Indicates that one of the std: library container functions has detected an attempt to access or store data via an unitialized iterator or an iterator that does not denote a valid position within a container.

4.8 attempt to dereference a past-the-end iterator.

Indicates that one of the std: library container functions has detected an attempt to access or store data via an unitialized iterator or an iterator that does not denote a valid position within a container.

4.9 …discards qualifiers…

The message

In some-function-name, passing const some-type-name … discards qualifiers

occurs when you try to pass a const object to a function that might try to change the object’s value. For example, if you have a class C:

class C {
public:
   C();
   int foo ();
   void bar (std::string& s);
   ⋮  
}

and you try to compile the following code:

void baz (const C& c1, C& c2, const std::string& str)
{
  int i = c1.foo();   // error!
  int j = c2.foo();
  c2.bar(str);        // error!
    ⋮

then a C++ compiler should flag the 1st and 3rd line indicated above. The g++ compiler will say something along the lines of

In function 'void baz(const C&, C&, const std::string&)': 
   passing 'const C' as 'this' argument of 'int C::foo()' discards qualifiers 

In function 'void baz(const C&, C&, const std::string&)':
  passing 'const std::string' as argument 1 of 
  'void C::bar(std::string&)' discards qualifiers

The first message complains that you have passed a const object as the left-hand parameter (implicitly named this) to the function foo, which has not promised to leave that parameter unchanged. You have, in effect, tried to discard the “qualifier” (the word “const”) in the const C& datatype. The second message makes a similar complaint about the string parameter being passed to bar. Again, the object being passed is marked as const, but the declaration of bar suggests that bar is allowed to change the string it receives as a parameter. To get rid of this message, you must examine what it is you are trying to do and determine whether:

4.10 LeakSanitizer: detected memory leaks

The LeakSanitizer (activated when compiling with a -fsanitize=... option) has detected that the program allocated blocks of memory that were never properly deleted.

Examine the message details for the source code files and locations at which the memory was allocated. (Of course the messages can’t tell you where you are missing a delete statment, because they can’t point to code that you haven’t written!)

4.11 need typename before…, also “warning: … is implicitly a typename” or “warning: implicit typename is deprecated”?

This error arises in certain uses of template parameters (or of names that are typedef’d in terms of a template parameter. For example,

template <class Container, class T>
void fillContainer (Container& c, T value)
{
   Container::iterator b = c.begin();
   Container::iterator e = c.end();
   fill (b, e, value);
}

will probably get one of these messages from g++ complaining about the mentions of “Container::iterator”. The fix is

template <class Container, class T>
void fillContainer (Container& c, T value)
{
   typename Container::iterator b = c.begin();
   typename Container::iterator e = c.end();
   fill (b, e, value);
}

4.12 No matching function …, No match for…

This is a variation on the messages saying a symbol is undeclared. In particular, you will get this message when you call a function, and there are one or more functions with that name, but your set of actual parameters’ data types do not match up with the formal parameter list of any of the declared functions.

Either you are correctly calling a function that you have not declared, or you are trying to call a declared function with the wrong kind of parameters.

This can be one of the longer error messages you will ever get, as g++ tries to list out all the functions with the same name that it knows, with the data types of all their parameters, as a way of showing you all your existing options. Although the list can be a bit daunting, if you are running in a support environment (e.g., emacs) that let’s you step from message to message while displaying the relevant line of code, this list can actually be quite helpful.

4.13 ‘nullptr’ was not identified in this scope

You are compiling a program that uses C++ 2011 features with compiler settings for the 1998 C++ standard.

Change your compiler settings to use the C++11 standard.

4.14 Segmentation error? Segmentation fault? Bus error? Null reference error?

These are all various errors signaled by the underlying operating system when your program tries to retrieve from, store into, or execute instructions from an address that either doesn’t exist or is reserved for another program. In practical terms, these kinds of messages almost always arise because of

To debug these problems, concentrate on your pointers, arrays, and iterators. Add debugging output or use a debugger to find out which one is being used when the crash occurs. Then work backwards to figure out why that pointer/index/iterator has an invalid value. Keep in mind that you might not be using a pointer, array, or iterator directly, but might be using (abusing?) a function or class that does.

4.15 terminate called after throwing an instance of ‘std::out_of_range’

Indicates that one of the std: library container functions has detected an attempt to access or store data that is out of range (e.g., trying to get the N’th item from a vector that only holds N-1 items).

The remainder of the error message will list files and line numbers that may help you trace the point at which the problem was detected.

4.16 Undeclared/undefined names and symbols

First, look very closely at the error messages. Does it say “undeclared” or “undefined”? These are two very different things, and understanding the difference is the key to fixing the problem.

So, if the compiler says that a function is undeclared, it means that you tried to use it before presenting its declaration, or forgot to declare it at all.

The compiler never complains about definitions, because an apparently missing definition might just be in some other file you are going to compile as part of the program.

But when you try to produce the executable program by linking all the compiled .o or .obj files produced by the compiler, the linker may complain that a symbol is undefined (none of the compiled files provided a definition) or is multiply defined (you provided two definitions for one name, or somehow compiled the same definition into more than one .o or .obj file).

For example, if you forget a function body, the linker will eventually complain that the function is undefined (but the name of the function may be mangled in the error message, see below). If you put a variable or function definition in a .h file and include that file from more than one place, the linker will complain that the name is multiply defined.

5 Java Programming

5.1 How do I determine the starting class of a Java program?

A starting class for a program must contain a function of the form

static int main (String[] args) {
   ⋮
}

This is quite similar to the main() function used in C++, though because Java does not allow stand-alone functions, the main() function in Java must be a class member. If a project is supposed to provide more than one program, then there may be many different starting classes within the project. A good way to list them quickly (on a Unix/Linux system) is

find yourProjectDirectory -name '*.java' | xargs grep main

5.2 error: the declared package “…” does not match the expected

package “…”

The source code files of Java programs must be arranged in a way that reflects the package and class style of their contents.

  • If you have a Java class MyClass, it must be stored in a file named MyClass.java.

  • If your Java class is inside a package myPackage, then the Java source code must be stored inside a directory named myPackage.

For example, on one of my projects, I have a class edu.odu.cs.AlgAE.Client.Layout.Anchors. That means that the source code for this class starts with:

package edu.odu.cs.AlgAE.Client.Layout;
   ⋮
public class Anchors {
   ⋮

and I would find the file containing that source code file in edu/odu/cs/AlgAE/Client/Layout/Anchors.java. (If you are on Windows, the same rule applies, but you use \ instead of / in the path.)

So, when you get the “package does not match” error, the possible causes are:

That last possibility is often the one that trips people up, so let’s talk about it.

5.2.1 Compiling from the Command Line

Suppose you have a class named MyPackage.SubPackage.MyClass. That should be in a file MyPackage/SubPackage/MyClass.java.

The command to compile this is

javac compiler-options MyPackage/SubPackage/MyClass.java

So it makes sense that this will only work if you are cd’d into the directory where MyPackage/ resides. If you list the contents of your current directory (e.g., with a Linux ls or Windows dir command) and don’t see MyPackage, then you are probably in the wrong place.

For example, if the absolute path to your source code were /home/yourName/projects/project1/MyPackage/SubPackage/MyClass.java, then you would want to

cd /home/yourName/projects/project1

before trying to compile your code.

5.2.2 Compiling from Eclipse

Part of the project settings for any Java project is a list of one or more “Source” directories. The Source directories are the places where Eclipse believes that you are keeping your packages of source code. These need to follow the same rule about packages and directories.

For example, if the absolute path to your source code were /home/yourName/projects/project1/MyPackage/SubPackage/MyClass.java, then you should have /home/yourName/projects/project1 as one of (possibly the only one of) your Source directories.

To view and change your project’s source directories, go to the Eclipse Project menu and select Properties -> Build Path, or right-click on any file or directory of the project in the Package Explorer and select Build Path -> Configure Build Path... Look at the Source tab to see your Source directories and make changes as necessary.

5.3 How do I install a Java compiler on my PC?

5.3.1 If you are on a Linux PC

Most Linux distributions will support installing Java as part of their normal software installation process. Do what you normally do to install any new software package.

For Ubuntu/Debian distributions, you probably want to install default-jdk. You can do this from the command line like this

sudo apt-get install default-jdk

5.3.2 If you are on a Windows or OS/X PC

There are two main Java packages.

If you want to compile Java code, you need the JDK. Get it here. Download the installer for your PC’s operating system and run it.

5.4 How do I install a Java IDE on my PC?

First, install the Java compiler.

I recommend the Eclipse IDE for Java. To install it, follow the instructions here. You can skip over the parts related specifically to C++ if you only want Eclipse support for Java. Or follow the all steps to install support for both Java and C++.

5.5 How do I set compiler flags and options?

From the command line. of course, you just type the option into the command.

5.5.1 Eclipse: changing the settings for one project

If you are using Eclipse, use the Project menu, select Properties. Go to Java Compiler. You can make changes here or in any of the sub-pages you reach by expanding the Java Compiler tree.

You will probably need to check the box “Enable project specific settings” on any page where you actually want to change the settings.

5.5.2 Eclipse: changing the default settings for all Java projects

From the Window menu, select Preferences, then Java, then Compiler. From here , and on the sub-pages you reach by expanding the Compiler tree, you can change settigns that will become the default for all Java projects in this Eclipse workspace.

5.6 How do I supply command line parameters when executing my programs?

Often you will be writing programs that take “command line parameters” as part of their inputs.

Of course, if you are executing a program from the command line, you just type the parameter values on the command line (hence the name!), e.g.,

Java MyPackage.MyProgram ../testData/myTestData.txt 23

But what if you are launching your program from an IDE?

5.6.1 Eclipse

  1. After you have successfully compiled your code, right-click on the Java class that contains your main function. Then, from the Run menu, select Run configurations...

    You’ll see a list of different project types, one of which should be “Java Application”.

    • Underneath that, you might already have a configuration for this program (Clicking on a configuration will show you what project and what Java class it is associated with.

    • If not, select “Java Application”, then at the top of the columm click on "_New launch configuration`".

  2. On the “Arguments” tab, enter your command line parameters into the “Program Arguments” box.

  3. Click Run to save these arguments and launch your program.

Video of this procedure

5.7 How do I get my program to read from a file instead of from the keyboard?

At the command line, this is called input redirection and is done by appending

< location_of_input_file 

to the end of the command launching the program. You can read more about this in CS252, and it works the exact same way in a Windows command-line session.

What if you are launching your program from an IDE?

5.7.1 Eclipse

After you have successfully compiled your code, right-click on the Java class that contains your main function. Then, from the Run menu, select Run configurations...

You’ll see a list of different project types, one of which should be “Java Application”.

On the “Common” tab, under “Standard input and output”, click to select the “Input” box, then use one of the three buttons on the line below to selectthe file of input data you want supplied as the standard input.

Click Run to save these arguments and launch your program.