Wednesday, March 7, 2012

Tips for job fairs

I'm not sure if I'd consider this lucky, but I've been able to represent my company at a couple of college job fairs while we were looking for interns. It's not surprising how little they know about how to handle a job fair, and I'll admit, when I was looking for a job at that age, I didn't do much better. The thing that a prospective intern needs to know, is that the job fair can get you an interview. When we were at the last college fair, we picked up between 100 and 200 resumes. I marked one as "high priority" and the rest I will probably pass on. There was only one student who came up to talk to me who was interested in anything. Lots of students would stop by and say things like, "I'm looking for a job, what do you have?" While it is a valid question, it puts you in with all of the other students that are doing the same thing. The most interesting (to us) were the people who had an interest in what we were doing and asked a few questions about our products.

It turns out, at the school we were at, there was a lot of CS and EE students. 90% of the EEs wanted to do hardware or drivers. That's fine, but I don't think they realized the competition for the single driver/platform job that we had. The one person who was interested in networking is got phone screened and I believe that the person who was interested in technical writing is going to be interviewed. If you really want a job, it makes sense to tailor your pitch and resume to the company, or at least the type of position that you're applying to, but it's far more important to apply to the position that nobody else applies to. I saw one guy that had two resumes, one for a hardware position and one for a software position. He probably didn't mean to show me that, but it was a fantastic idea. I wouldn't have been too put off if somebody had asked which of the positions were getting all of the applicants, and then asking if they can apply to one of the other ones.

If I were a student again, the best strategy would be to actually research the companies that are there. I bet you can find out their positions (our jobs were listed on both our own website and the schools'). I would pick 10-25 companies that I want to apply to, find our their positions, and make up resumes specifically for those jobs. I would go visit those first, before it gets too crowded. Knowing a couple things about the company so I could carry on a 2 minute conversation about the company without asking boring questions is a good idea. At our table, these things would put you in the top 1% of the people that were coming to talk to us. It's no guarantee of a job because you still need the skills, but this is an easy way to get an initial contact. Don't worry too much about your skill set, that should be on your resume, and any company worth working for will evaluate that at a later point. It's much more important to show a little enthusiasm in the various positions that are offered.

It might be different for other places, but fancy resume paper and suits didn't change one thing at our place. I can't even remember what the intern that I ended up interviewing was wearing. All I know is that he was excited that we had a network team that used Wireshark and we have a simulator for our hardware.

Maybe it doesn't take too much to impress me.

Saturday, October 22, 2011

Template metaprogramming

Template metaprogramming is a fairly useless feature of C++, but we can have some fun with it. I've been trying to improve my functional programming skill set, so a friend proposed a problem:

Write a routine that can count bits in an integer at compile time using templates.

Here's the basic recursive solution:

int count_bits(unsigned int x)
{
if(x == 0)
{
return 0;
}
else
{
return (x & 0x1) + count_bits(x >> 1);
}
}



This isn't what I had in mind though. I want to do this using templates. That gets us there:

#include <stdio.h>

template<unsigned long long input>struct numBits
{
static const unsigned long long value = numBits<(input >> 1)>::value+(input&1);
};

template <> struct numBits<0>
{
static const unsigned long long value=0;
};

#define output(num) printf("0x%llX: %u\n", (unsigned long long)num, numBits<(unsigned long long)num>::value)

int main(int argc, const char **argv)
{
output(0x0);
output(0x1);
output(0x2);
output(0x3);
output(0x4);
output(0x11);
output(0x111);
output(0x1000);
output(0x1010);
output(0x1001001);
output(0xFFFFFFFFFFFFFFFEULL);
output(0xFFFFFFFFFFFFFFFFULL);

return 0;
}




Ha! The biggest problem with this is it only works on constants (it IS compile time). It's an academic exercise, as there's not much good reason to use this over the other options. The output looks like:

0x0: 0
0x1: 1
0x2: 1
0x3: 2
0x4: 1
0x11: 2
0x111: 3
0x1000: 1
0x1010: 2
0x1001001: 3
0xFFFFFFFFFFFFFFFE: 63
0xFFFFFFFFFFFFFFFF: 64

Sunday, October 9, 2011

Near space attempt #1




I have been reading about a bunch of the high altitude weather balloon experiments, and I wanted to give it a try. I started with a bunch of websites sort of explaining what they did, and initially decided to copy them. I got myself a Canon A470 and a Motorola i290 prepaid cell phone from Amazon, a sturdy styrofoam box and some kite string from my parents, a 600g weather balloon off Ebay, a rocket parachute from a sketchy online hobby shop and two 60 cubic foot helium tanks from Taylor Rental. The goal was 100K feet (3 times higher than those really small jets up there).




This was collected over a 2.5 month period. The project was "officially" started when I found a different camera and the Motorola cell phone on sale on Amazon on July 24th. The first camera I got couldn't support larger than a 2GB memory card, so I returned it and bough a used Canon A470 instead. I'll put up more info about each of the parts used in separate posts.

We've had a lot of rainy weekends lately, and the weekend of October 8th was the first nice one in the past 3 or 4 weeks. It turns out the the high winds we favorably blowing from north to south, allowing us to launch the balloon from Nashua and recovering it somewhere in the Massachusetts Metro-West area. I wanted it to land in a civilized area, so it we had a chance of getting to it without a huge overland hike and somewhere where there should be cell phone coverage.

Using habhub.org the predicted flight path put it somewhere south of Framingham. This was the weekend.





Fill 'er up

I played phone tag all week with various FAA offices until I at least got someone to at a least acknowledge that I was going to send a balloon up somewhere near Boire Field. I arrived at 8 and scoped out a place to launch it and decided that behind the tennis court would work. A co-worker helped inflate the balloon. The 600g balloon was supposed to be 6ft in diameter fully inflated (113 cubic ft). I used a piece of tubing duct taped inside the balloon nozzle and stuck over the balloon filler. Emptying a single 60 cubic foot helium tank took about 8 or 9 minutes. This is a picture of the balloon after the first tank:



Switching to the second tank was pretty easy. Packing the payload was pretty straightforward:



The green piece is a mylar balloon crumpled up so it (possibly) would show up on radar. I don't know if that worked, but it didn't add much weight. The black box plugged into the phone is a battery extender that I had. I don't think that did anything either, but it did add weight. The phone would typically run for around 10 hours with the GPS tracking software enabled, so the extra battery pack was overkill. The camera is pointing through a hole in the side of the box. I filled the box up the rest of the was with packing peanuts and taped a note onto the top:



Hopefully that will keep the Massachusetts police organizations from over-react-ing.


The Launch

Liftoff was at 9:13 EDT. We toddled down to Framingham to wait for a signal of the parachuting payload coming back to Earth. While eating lunch, we got our tracking signal:





Awesome! It landed in North Easton!?! We were still 40 miles away in Framingham. Touchdown was at 12:13 EDT. We drove over and found the payload intact:



The balloon was shredded and really twisted up in the parachute. I think it would be better to put the ballon farther from the parachute next time, but I'll detail that later.

The raw result:


Flying a balloon to 100K feet

The pictures weren't outstanding, but I'll call it a success. I got a picture of the blackness of space, so I know it got a long way up there, and we were able to successfully do it once.
Some of the highlights:











Tuesday, September 13, 2011

Compile time asserts

C and C++ don't have a built-in version of a compile time assert. Being in both the network protocol business, the embedded system business and distributed system business, I spend a lot of time counting bytes to make sure our data structures are the correct size. I then have to chase down the problems that arise when somebody adds an additional field to a data structure, which causes the compiler to add more padding and things get larger than expected.

GCC 4.3 (but not by default) and VS 10 support static_assert as part of the C++x0 changes, but it's still not supported in C.

I poked around and came up with a gimmicky solution but it works pretty well.


#define ASSERT_LINE_HELP_CONCAT(a, b) a##b
#define ASSERT_LINE_HELP(a, b) ASSERT_LINE_HELP_CONCAT(a, b)
#define CT_ASSERT(expression) \
enum { \
ASSERT_LINE_HELP(COMPILE_TIME_ASSERT_ON_LINE_, __LINE__) \
= 1/((expression)) \
}


It creates an enum called COMPILE_TIME_ASSERT_ON_LINE_### and sets it to 1 on a valid constant expression and 1/0 on an invalid expression. Setting an enum constant to 1/0 will cause it to fail compilation (that's what we want!). The extra indirection is to allow the __LINE__ macro to be expanded to show the line number.

As an example:


#include <stdio.h>

#define ASSERT_LINE_(a, b) a##b
#define ASSERT_LINE(a, b) ASSERT_LINE_(a, b)
#define CT_ASSERT(expression) \
enum { \
ASSERT_LINE(COMPILE_TIME_ASSERT_ON_LINE_, __LINE__) \
= 1/((expression)) \
}


// as defined in the Liunx kernel
struct tcphdr {
unsigned short source;
unsigned short dest;
unsigned int seq;
unsigned int ack_seq;
unsigned short res1:4;
unsigned short doff:4;
unsigned short OOPS:1; // this is the problem
unsigned short fin:1;
unsigned short syn:1;
unsigned short rst:1;
unsigned short psh:1;
unsigned short ack:1;
unsigned short urg:1;
unsigned short res2:2;
unsigned short window;
unsigned short check;
unsigned short urg_ptr;
};

CT_ASSERT(sizeof(struct tcphdr) == 20);

int main()
{
return 0;
}





bandken@six6six:~$ gcc temp.c
temp.c:33: warning: division by zero
temp.c:33: error: enumerator value for ‘COMPILE_TIME_ASSERT_ON_LINE_33’ is not an integer constant
bandken@six6six:~$


This lets us know that our TCP header size isn't 20.

There's a few caveats. It will be confusing to have multiple instances of the CT_ASSERT(...) on the same line. That's pretty simple to remedy, but the bigger problem exists when CT_ASSERT(...) is used in a header file. It won't work if there aren't #include guards. If multiple CT_ASSERTs are included in a header file, they will all resolve to the same line. If that is the case, it might be preferable to use a separate .c file that includes the various asserts that could be put into the header files.

This is a bit kludgy, but it does provide checking that wouldn't normally be available. In cases where data structure size is vital, it provides a compile time check for these cases. Unit tests that checked the sizes could be used as an alternative to the compile time assert, but that requires the unit tests to be a) written and b) run every time. Depending on the environment, that's not guaranteed, where as CT_ASSERT(...) will force the issue to be dealt with before it's committed to the source code repo.

Sunday, September 11, 2011

pure virtual method called


bandken@six6six:~$ ./a.out
pure virtual method called
terminate called without an active exception
Aborted
bandken@six6six:~$


Someone had asked me to explain what this meant. Simply, it means that you called a pure virtual function without having the method defined. With most compilers (at least all the ones that I've used), a dummy function is inserted into the virtual function table entry, and it remains there until a concrete class is constructed and the pure virtual function replaced with the correct function. GCC won't even let you call a pure virtual function in the abstract class's constructor, as this example shows:


class Base
{
public:
Base()
{
Oopsie(); // ERROR: warning: abstract
// virtual ‘virtual void
// Base::Oopsie()’
// called from constructor
}

virtual void Oopsie() = 0;
};

class Derived : public Base
{
public:
virtual void Oopsie() {};
};

int main()
{
Derived derived;
return 0;
}



We're lucky that we actually get an error. There's no reason why the compiler needs to tell us about this. It doesn't take much tweaking to get past this.


class Base
{
public:
Base()
{
init();
}

void init()
{
Oopsie();
}

virtual void Oopsie() = 0;
};

class Derived : public Base
{
public:
virtual void Oopsie() {};
};

int main()
{
Derived derived;
return 0;
}



The constructor order is Base, then Derived. In the constructor for Base, we call init(), which calls Oopsie(). Since Derived hasn't been instantiated yet, we call the pure virtual method and our program crashes.

We're not limited to having this problem only in the constructor. Here you can see the problem happening in the destructor. The destructor order is Derived first, then Base (opposite order of the constructors). By the time the done() method is called, the Derived destructor has already been called, and the derived Oopsie() call no longer exists.


class Base
{
public:
~Base()
{
done();
}

void done()
{
Oopsie();
}

virtual void Oopsie() = 0;
};

class Derived : public Base
{
public:
virtual void Oopsie() {};
};

int main()
{
Derived derived;
return 0;
}



Typically, a good rule of thumb is to be very careful when putting any virtual functions into constructors and destructors. You might even know what you are doing. Maybe. Sure, calling that virtual function from the abstract base class constructor is fine, because....uh, I can't think of ANY examples why this is a good idea. If you really wanted some functionality the was to be provided in a function that happened to be virtual, please do something like this:


class Base
{
public:
Base()
{
init();
}

void init()
{
// ..
// ..
// ..
functionalityThatICannotLiveWithout();
}

void functionalityThatICannotLiveWithout()
{
// ..
}

virtual void pureVirtualMethod()
{
functionalityThatICannotLiveWithout();
}
};

class Derived : public Base
{
public:
virtual void pureVirtualMethod() {};
};

int main()
{
Derived derived;
return 0;
}

Monday, August 29, 2011

Fixing an electric piano...


...or really, my first attempt at time-lapse photography. My friend gave me a Roland MP 300 that had a few broken keys. It is a synthesizer that has actual hammers instead of springs. Two hammers were broken and their remains blocked others from functioning properly, and I broke two more taking it apart. There's 5 different hammers for each 12 tone octave, and I went to all the trouble of looking up the correct part numbers and sizes, but if you order them directly from Roland, you actually need to just give them the note (A#, D, etc.). They couldn't look them up by the part numbers.

To take the images, I used a Canon A470 with CHDK installed. It was a nightmare trying to put the images together. I tried to use iMovie on my iPhone but it kept crashing. Windows Live Movie Maker for 2 different Windows 7 computers could build the entire movie, but would crash when trying to save it. The only one I could get to work was Movie Maker for Windows XP. Even still, it was a pain in the neck. The only Windows XP computer that I have is one that's running on my headless VirtualBox server. Movie Maker doesn't run over Remote Desktop or without any audio hardware, so I had to enable VRDE in VirtualBox and install a "virtual" sound card into the machine. Don't worry if that doesn't make any sense.

The interval is 5 seconds per picture, and there are 1200 images. That's roughly 1.5 hours over two days.



The hardest part was figuring out how to get the keyboard out because there were many brackets and hidden screw and tabs, plus the frame that held the hammers and keys is a big chunk of steel. The keyboard alone probably weighed close to 40 pounds. I only have one leftover screw!



The sound quality on my dad's Yamaha keyboard is better, but it's much more pleasant to play the Roland with the inertial hammers and keys. I can pipe the audio output of the Roland into the Yamaha to get the best of the two, but it does require having two keyboard set up in the basement. When I get good enough to play something recognizable, I'll record and post.

Friday, August 12, 2011

My interview questions

I've always been surprised by how few people ask any technical questions at an interview. There's plenty of posts that are much better than mine on this subject. My favorite is this one: http://steve-yegge.blogspot.com/2006/03/truth-about-interviewing.html

I'm often tasked with evaluating the basic technical competence of an individual. This is commonly known as the "bad cop" around here. I think that's undeserved, as the technical part of the interview is my favorite part. I'd much rather design another object-oriented elevator than discuss what my greatest weakness is, or how I dealt with a problematic co-worker.

Anyway, I wanted to share my interview questions. If you are going to get interviewed by me, it's likely that you'll end up some variants of these. The good candidates get through then in short order so we can get onto more important things. These were modeled after Steve's recommendations from above. These allow for more in depth probing after the initial answer is obtained.

1. Write a C function that counts the number of bits set in an unsigned int. What about signed?
2. Tell me about polymorphism, and why it is useful. How could this be done under the hood?
3. You have a singly linked list of addresses, sorted by the person's name. There's millions of entries. We need to provide the linked list to some other entity at some point so it at least needs to keep the sorted linked list format. What are some ways to speed up the lookup of an entry?
4. We have a directory (say on an SMB share so anybody can access it) that has an arbitrary number of sub-directories. These directories may or may not have sub-directories, but they do have an arbitrary number of text files. These text files contain IP addresses in the dot-decimal format like so:

10.127.13.3
10.127.14.5
10.127.13.16
10.127.13.241

I generated these files incorrectly, and any IP address that has a zero in one of it's fields is printed incorrectly:
10.127..1
10..1.3
10.127.14.
.1.2.3
127...1
...1

should be really printed as
10.127.0.1
10.0.1.3
10.127.14.0
0.1.2.3
127.0.0.1
0.0.0.1

How can I find these bad IP addresses and can I fix the easily?