Some C++ tutorials

I do lot of my development in C++. It’s not the most user-friendly of languages but it’s very powerful. Learning it can be a bear, however.

If you’re really a glutton for punishment, you could start with The C++ Programming Language, by the creator of the language – Bjarne Stroustrup. This is a very dense book and while it contains a lot of really important information it leaves a lot to be desired when it comes to learning to program with the language. I’d recommend this as the third book you pick up after you’ve learned some of the basics.

A great place to start would be Bruce Eckel’s Thinking in C++. If you like learning from a book, you can pick it up at places like Amazon or B&N. Bruce has been kind enough, however, to make the book available for download for free at the book’s website. (He also has an excellent book on Java, appropriately named Thinking in Java.)

Another good online tutorial can be found at cplusplus.com. It’s not quite as user friendly as Eckel’s book, nor does it go into the same level of detail. It does provide a nice high level overview though.

Once you get started you might have some questions. The C++ FAQ (lite) is a good place to start. This is the online version of the much larger print version. I haven’t read the print version but it doesn’t get very good reviews. The latest print edition was last published in 1998 so I have no doubt it’s missing a lot of useful information. Some more useful books along these line are Scott Meyer’s Effective C++ , More Effective C++ , and Effective STL books.

A good online reference guide can be found at cppreference.com, which provide help on syntax and some example code. It’s especially nice in that each example shows which include(s) is needed for the method in question.

That’s it for now. If I come across any more useful C++ links / books, I’ll be sure to forward them along. Until then, happy programming!

Tagged with:
Posted in Uncategorized

Templates on HP

If you run into a compiler error like this compiling a template on HP 11.00:

Error 419: “myfile.cpp”, line 5 # ‘iterator’ is used as a type, but has not been defined as a type.

std::vector::iterator j;

you need to specify the ‘typename’ before vector. e.g.

typename std::vector::iterator j;

Tagged with: ,
Posted in Uncategorized

Calculating Perl performance

I’ve been doing some scripting in perl lately. I’ve been writing a script that generates a slew of data files and it was running really slow. I wanted to find out the bottleneck. Fortunately for me, Perl includes a nice high-level profiler. Here’s how to use it.

First run your script using the -d:dProf option:

bash-4.1$ perl -d:dProf myScript.pl

This generates a tmon.out file that contains the profile information.

Next run the dprofpp command:

bash-4.1$ perl dprofpp -u

This generates a usage report like this:

Exporter::export has -2 unstacked calls in outer
Exporter::Heavy::heavy_export has 2 unstacked calls in outer
Total Elapsed Time = 0.168504 Seconds
User Time = 0.122504 Seconds Exclusive 

Times %Time ExclSec CumulS #Calls sec/call Csec/c  Name  
13.0   0.016  0.016      3   0.0053 0.0053  vars::BEGIN  
13.0   0.016  0.016      5   0.0032 0.0031  IO::Seekable::BEGIN
13.0   0.016  0.032      7   0.0023 0.0045  IO::File::BEGIN
13.0   0.016  0.016      1   0.0159 0.0158 main::parseConfigFile
12.2   0.015  0.015      2   0.0075 0.0075  Exporter::as_heavy
12.2   0.015  0.015      3   0.0050 0.0050  File::Bsename::BEGIN
0.00   0.000  0.000      2   0.0000 0.0000 Exporter::Heavy::heavy_export
0.00       - -0.000      1        -      -  Fcntl::BEGIN
... etc

From there it’s pretty easy to figure out what’s happening. There are a lot of cool options to the dprofpp command. Check them out with the -h option.

Happy scripting!

Tagged with: ,
Posted in Uncategorized

Dumping the NIS database programmatically

I recently had to get user information from a NIS domain programmatically. It’s fairly simple to dump the NIS database from the command line using ypcat. e.g.

bash-4.1$ ypcat passwd.byname
user1:crypticpwd:100:100:User One:/homes/user1:/bin/sh
user2:crypticpwd:101:100:User Two:/homes/user2:/bin/csh
....

It’s just as easy to match users or UIDs using ypwhich. e.g.

bash-4.1$ ypwhich 100 passwd.byuid
user1:crypticpwd:100:100:User One:/homes/user1:/bin/sh

Unfortunately, examples of doing this programmatically are few and far between. After some experimentation I figured out how to get the entire NIS database using yp_all.

The yp_all function is defined as follows:

int yp_all(char* indomain,
char* inmap,
struct ypall_callback* incallback
);

where ypall_callback is defined as:

struct ypall_callback {
int(*foreach)();
char *data;
};

And foreach is defined as a function:

int foreach (
int instatus,
char* inkey,
int inkeylen,
char* inval,
int invallen,
char* indata
);

Seems straight forward enough, no? yp_all takes a structure containing some arbitrary data and a callback function. yp_all queries the NIS database and makes a call to the given callback function for each row in the result set. Define your special handling in the foreach implementation for every record and there you have it. Don’t forget to handle error conditions along the way.

You can use the same method to query other NIS databases by specifying a different inmap value. These are fully qualified map names, not aliases. A not so exhaustive list includes:

  • passwd.byname
  • passwd.byuid
  • group.byname
  • group.bygid
  • mail.aliases

You’ll need to know the format of each entry to parse it properly.

There’s an equivalent yp_match API call that can retrieve specific records from a NIS database.

Example:

// define the foreach method called by yp_all
extern "C" int my_foreach(int instatus, char *inkey,
int inkeylen, char *inval,
int invallen, char *indata) {
// This function is call for every record in the database
// note - be sure to use the provide keylens to determine the
// length of the provided data, otherwise you'll pick up garbarge.
// indata at this point is what you provided to the structure. If it's not
// a char * you'll need to cast it properly.

...

// do something with the current record here
}

struct ypall_callback yp_cb;
yp_cb.foreach = myforeach;
yp_cb.data = dataPassedToForEach;

yp_all(myNISDomain, "passwd.byname", &yp_cb);
Tagged with: ,
Posted in Uncategorized

memory leak detection using dbx

The Solaris compiler suite ships with dbx, a source level debugger. Later versions include additional functionality to detect memory leaks and dangling blocks at program exit. The Sun guys once again designed a pretty powerful tool with a god awful interface. Here are some hints to using the detector.

Suppose you have a simple program like this, which is both leaking memory and has open blocks at program exit:

int main(int argc, char *argv[]) {
char *openBlock = new char[255];

for(int i=0; i &lt 100; ++i) {
char *leak = new char[i * 1024];
sleep(5);
}
}

It’s pretty obvious just looking at this code that we’re leaking a lot of memory; leaving a lot of dangling pointers, etc. Unfortunately most code in the real world is not this obvious. Sometimes it takes a little extra help to track down the leaks. This is especially true when you’re trying to track down a leak in legacy code. There’s often a ton of cruft in the way, making detecting the leak visually that much more difficult.

Fortunately, dbx comes to our rescue. There are a number of dbx commands to control run time checking. Here’s a quick run down of the common ones:

check memusage – enables memory leak detection and memory usage summary reports at program exit.

showleaks – show memory leaks when you’ve stopped at a breakpoint.

showmemuse – show the memory usage report when you’ve stopped at a breakpoint.

dbxenv rtc_mel_at_exit – controls the verbosity of the memory usage report at the end of execution. I use “verbose” most of the time.

dbxenv rtc_error_log_file_name – lets you specify where you want the summary report written.

We run the above program in dbx as follows:

bash-4.1$ dbx a.out
(dbx) check -memuse
(dbx) dbxenv rtc_mel_at_exit verbose
(dbx) dbxenv rtc_error_log_file_name a.out.errors
(dbx) run
Running: a.out
(process id 10331)
Reading librtc.so
RTC: Enabling Error Checking...
RTC: Running program...
Checking for memory leaks...

Actual leaks report (actual leaks: 97 total size: 4842752 bytes)

Memory Leak (mel):
Found 96 leaked blocks with total size 4842497 bytes
At time of each allocation, the call stack was:
[1] operator new() at 0xfd5061ac
[2] main() at line 7 in "main.cpp"

Memory Leak (mel):
Found leaked block of size 255 bytes at address 0x20be8
At time of allocation, the call stack was:
[1] operator new() at 0xfd5061ac
[2] main() at line 4 in "main.cpp"

Pretty nice. Not as nice as a purify run, and certainly not as intuitive, but it gets the job done without having to fork over the $$$ for a purify license.

Tagged with: , ,
Posted in Uncategorized

Returning CORBA object references

The CORBA object semantics are really frustrating at times. They behave close enough to how C++ does things to make them familiar, but they differ enough to lull you into a false sense of familiarity.

Your first attempt to return a reference from a method might look like this:

MyObject_var getReference() {
MyObject_var rval = new MyObject();
... // do some stuff
return rval;
};

MyObject_var tmp = getReference();

This looks promising. Let’s walk through the reference count here:

  • rcount = 1 — reference after construction
  • rcount = 2 — reference count is incremented when assigned to the temporary used for return values.
  • rcount = 1 — reference count is decremented when the stack variable falls out of scope.* rcount = 2 — after assignment to tmp
  • rcount = 1 — when tmp falls out of scope. Whops! We have a dangling pointer. The reference count never returns to zero; the underlying object is never destructed.

The recommended approach is to never use _var types as parameters or return values. This avoids the dangling pointer problem and is safer. The above would be rewritten as:

MyObject_ptr getReference() {
MyObject_var rval = new MyObject();
... // do some stuff
return rval.retn();
};

MyObject_var tmp = getReference();

The reference counts in this case?

  • rcount = 1 — reference after construction
  • rcount = 0 — the pointer is assigned to the return value; retn releases ownership of the pointer.
  • rcount = 0 — The var no longer owns the pointer, so the referenc count stays the same.
  • rcount = 1 — after assignment to tmp
  • rcount = 0 — when tmp falls out of scope.

Nice and clean, no?

Tagged with: , ,
Posted in Uncategorized

When a C++ destructor is not called

Suppose you’re following the “resource acquisition is initialization” technique where you allocate resources as part of construction. You might write classes like:

class X {
Resource* _resource;
public:
X();
~X();
};

X::X() _resource(0) {
_resource = new Resource();
...
}

X::~X() {
delete _resource;
}

The resource is allocated in the constructor when the object is instantiated and released in the destructor when the object is deleted. This is a very common way of allocating resources in C++; it's clean, elegant, and easy to understand. All is right with the world, right?

Suppose after the resource is allocated there's an exception in the X constructor. Your first instinct is to assume the destructor is called and your resource is freed up. Your first instinct is wrong.

If there's an unhandled exception during construction, the object does not exist, therefore the destructor will never be called. In the above case that assumption would lead to a resource leak each time the constructor failed.

Something like this would work better:

X::X() : _resource(0) {
try {
_resource = new Resource();
...
}
catch(...) {
delete _resource;
throw;
}
}

X::~X() {
delete _resource;
}
Tagged with: , ,
Posted in Uncategorized

Reallocation failure in ySpace()

The Solaris compiler really has some useless error messages. I get “Reallocation failure in ySpace()” occasionally when compiling under SunOS with the forte compiler. The compilation fails and I’m left scratching my head.

This error message is really awful. The message doesn’t tell you what went wrong, why the “Reallocation” failed, or any hints to correct the situation. Who was this message targetting? It certainly wasn’t the user of the compiler who, after all, is only interested in why his compilation has failed. Had the message been written with the user in mind it would have said something useful about the situation.

Enough harping about useless error messages…

After digging around for twenty minutes I figured out the underlying problem. The compiler ran out of swap space. You can monitor your swap utilization by running:

sh$ vmstat -S 5

This will print out the available swap every 5 seconds so you can see how the available swap is fluctuating. I observed the swap space going from 80 megs down to zero when my compile failed.

To increase the available swap, find a location with plenty of space and do the following:

sh$ mkfile [swap size. eg. "64m"] [location]
sh$ swap -a [location]

To remove this swap later execute:

    swap -d [location]
Tagged with: ,
Posted in Uncategorized
Design a site like this with WordPress.com
Get started