Showing posts with label coding. Show all posts
Showing posts with label coding. Show all posts

Friday, February 26, 2010

Objective C

I've been reading a document written to help C++ programmers learn Objective C. If you are in my situation where you know C++, but Objective C seems completely unreadable, then I suggest you read it too. It's very good and hits on all the main points you need to know.
Objective C isn't actually a very large language, being a strict superset of C, but has some very nice features. The main difference is that instead of calling methods on objects, you send messages to them instead. So in effect, if an object doesn't implement the method you want to call, then you get an exception, rather than a crash in C++ (after convincing the C++ compiler to let you do it...).
Classes are also treated as objects, so you can query classes for properties and so on. All in all, this makes for a more object oriented language, although presumably wouldn't have the efficiency of code written in C++ or C. The Objective C memory model seems pleasant to get along with, and then you could just rely on a garbage collector as well if you don't even want to think about it.
Now, to actually try some exanples using it.

Wednesday, January 13, 2010

It's good to be a software engineer

It's officially good to be a software engineer. Low physical activity and stress levels. Mostly, I personally think it's interesting because everything keeps changing. Boredom is the worst.

Monday, December 14, 2009

Virtual Inheritance.

I found a bug recently that was causing a crash only on a Solaris 10 build, but the same code was fine on Win32. I eventually tracked it down to the Sun compiler not generating the correct code for a virtual inheritance situation. It was a multiple inheritance situation, and one of the parents was a pure abstract interface class, so it's not like the design was really ugly, or the situation was particularly complex. There was only one implementation of the virtual method for the class, and the abstract interface was derived virtually. Calling the method on the class worked fine, but calling the method on a const abstract base class reference (where the method was declared) returned fine, but the returned object caused a crash as soon as it was used. The method was there, but the compiler didn't hook it up in the virtual method table. It hooked something up though. Bizarre. I removed the virtual keyword, and everything worked fine.
The Sun compiler is Flakey.

Monday, November 30, 2009

Sun C++ compiler precompiled headers implementation sucks.

I'm using the Sun C++ compiler (Sun C 5.9 SunOS_sparc Patch 124867-01 2007/07/12) on Solaris (5.10 Generic_141444-09 sun4v sparc SUNW,SPARC-Enterprise-T5220) for work.

I noticed that the compiler supports precompiled header files recently, and thought, great, this is going to speed up compiling enormously. For a given C++ package, compiling on Windows under VC9, the time taken decreases from 55 seconds to 22 seconds when precompiled headers is enabled. That is a significant difference, and well worth the effort of setting it up to work for you.
On Solaris, without precompiled headers, this same package takes 2:30s to compile. OK, it's an older machine, but when precompiled headers is turned on (-xpch=autofirst), the time taken, incredibly, increases slightly to 2:40s. I mean, seriously, WTF!?
With some more digging, I work out that the Sun compiler's implementation of pchs is infantile. They just collect up the postprocessed code from the headers and lob into one large file. There is nothing precompiled about Sun's precompiled headers, If anything, it's preprocessed headers. And it has to be implemented badly to take longer! Sheesh! Even the link above shows a minimal improvement for a really simple case.
Get it together Sun! Oh, right, Oracle is buying, and they probably care less.

Wednesday, August 26, 2009

Windows CAN support more than 4Gb RAM

This is something I hadn't appreciated earlier. 32 bit Windows can support more than 4Gb of RAM. The link is a very well written article and worth some time if you have interest.
The main point to think about when trying to get your head around this is that a modern OS doesn't allow applications to access memory directly, but via virtual memory pages. These pages are mapped to physical memory in a way the OS decides given the ability of the hardware. 16 bit Windows was able to access more than 64K memory, and in the same way, 32 bit windows can access more than 4Gb memory. 32 bit Windows drivers need to deal with 64 bit numbers to do this, but this has been part of Windows since at least Windows 2000 and probably Windows NT. Note, of course, that any individual 32 bit app can only access less than 4Gb RAM, we're talking about the OS here.
The reason Vista 32 and others only report less than 4Gb RAM is a licencing one! See the article.
Obviously it is in Microsoft's interest to have us all using 64 bit Windows asap. That's fine with me.

Monday, June 29, 2009

wmain parameters corrupted?

Well, that was frustrating. I was trying to get command line parameters passed into the unicode wmain function defined as

int wmain( int argc, wchar_t *argv[]);

But I was getting corrupt looking bizarre values placed into argc and argv.
My problem was that in Visual Studio, I set the linker option for the entry point as wmain, but it has to be

wmainCRTStartup

Don't make the same mistake.

Saturday, November 15, 2008

More Cores.

You have probably heard about Moore's law driving the relentless improvement in computational power we've seen the last 40 years. Unfortunately, this "law" isn't about power or speed, but purely about the number of transistors able to be packed onto a chip. Speed has historically been a direct result of this as the clock speed was able to be driven up with the smaller device sizes.
While Moore's law is still happily churning along, and probably will for at least another decade or two, recently processor speeds haven't really been increasing very much. Instead we are now seeing multiple cores (copies of a whole processor) embedded in chips. Currently, that's mostly 2 and 4 core chips, but since this is now the easiest way to use all the extra transistors that can be packed into a chip, over the next 10 years we'll see many many cores on your desktop. Numbers like 32-128 I suggest.
Cool right? But there's a problem. Most of today's software only knows how to do one thing at a time, so if you had a 128 core machine today, it wouldn't feel any faster. We need to write more software that uses multiple cores. Its called parallel programming, and it's much harder than normal programming as it is prone to sudden and massive program failure as threads wamp each other's data. It's been suggested that 1% of programmers actually know anything about this.
At least I may be hold onto a job for the next ten years.

Tuesday, October 28, 2008

variable argument lists

I found an interesting problem with using var args today. When you implement a function that takes a variable number of arguments, you have to use a nasty little function called va_start() which gets a pointer to the first of the variable arguments that was passed on the stack to the function. See code below. In order to do this, you pass to va_start() the argument that was just before the variable arguments passed, in this case a const MyObj&.
I found that this just caused the user of the va_list to crash.
It turns out that you can't use an object reference like this, because the sizeof mechanism that determines how far to advance the pointer past the parameter thinks the parameter is as big as the object, where it is really just a reference to that object.
Solution: Pass a const MyObj* or a MyObj by value. In some functions, you could arrange the order of params so that a pointer or value is next to the var args.
Nasty.

void doStuff(const MyObj& details, ... )
{
va_list args;
va_start(args, details);
//use args
va_end(args);
}

Thursday, September 25, 2008

Test Driven Development

Just finished reading this. Interesting, but not entirely convinced.
Essentially, Beck lays down the following development procedure:
  • write an (automated) test
  • run the test to show it fails
  • do the quickest thing possible to get that test working, even if it's really dirty or evil
  • fun the test to show it passes
  • refactor
  • check all tests still pass
  • rinse, repeat.
The main thing to notice is that the tests you write drive the functionality, rather than the functionality dictating what tests you write. The outcome of this is that the software is designed as you go, and essentially has the minimum possible clean design for the software at each point in the software's life.
It sounds good, but when I ran through his examples, I couldn't help feeling there is magic involved. I think my main concern about the methodology is that the design must necessarily wander around a great deal, and I can't help but think that this would waste a lot of development time in refactoring from design to design. Beck suggests that to some degree, this happens anyway, and IDE refactoring tools are getting really good these days to help with that.
I completely agree that having unit tests that give you a really high code coverage makes it much safer to refactor code, and continuous refactoring of code is really important as new features and modelling enter the fray, and the design necessarily morphs over time. If anything, having read this book will make me write even more unit tests.

Monday, September 22, 2008

I Love Functors. Part II

See Part I.
There's a better way using std::for_each()! With this, just use for_each() directly.

class Base
{
public:
virtual ~Base(){};
typedef std::list List;
struct Functor
{
virtual ~Functor(){}
virtual void operator()(Base& o) const=0;
};
static void Functorator(List& l, const Functor& f)
{
std::for_each(l.begin(), l.end(), f);
}
};

BTW -code formatted by http://formatmysourcecode.blogspot.com/
Thank you Greg Houston!

Monday, September 8, 2008

I love Functors


//Don't keep writing list loops, use functors!
class Base
{
public:
virtual ~Base(){};
typedef std::list List;
struct Functor
{
virtual ~Functor(){}
virtual void operator()(Base& o) const=0;
};
static void Functorator(List& l, const Functor& f)
{
for (List::iterator it=l.begin();
it!=l.end(); ++it)
{
f(*(*it));
}
}
};

Monday, August 25, 2008

DLLMain() Don'ts

{if not programmer, escape}

I never knew this, but it makes Oh, So Much Sense Now.
You can define a special function in a Windows DLL called DLLMain(). It's a piece of code that gets executed when your DLL is first loaded into the address space of your process. (It also gets called at other times, like thread attachment and shutdown). But that's not the bit I didn't know. I was recently debugging a problem where loading a DLL was causing a system crash. It looked as though the static variables in a dependent dll (loaded as a result) were not initialised, and thus any attempt to use them was causing massive, sudden and irrevocable system carnage. Now, the DLLMain of one of the dependant DLLs was calling a fairly innocuous trace function, however, the tracing platform was doing some funky dynamic loading of implementation DLLs to get around some tracing dependency issues. The problem with this is that when the CRT calls your dll's DLLMain() function, it takes out a lock (called the loader lock) on DLL loading (actually initialising loaded DLLs). This means that dynamically loading DLLs during a DLLMain is a Really Bad Thing. IMHO, this really should have completely deadlocked rather than trying to do what it did. Perhaps it would have deadlocked if any of the dependent DLLs defined their own DLLMain() functions. What it actually did was to load the DLL as asked, but not initialise any of the static data for it. Nasty.
More info.

Monday, August 18, 2008

Core Interest: Software

Another core interest is software. When I say software, I really mean programming software. No one likes software for the sake of software because all software has problems. Whether it is slow, buggy, or just plain not useful enough, any piece of software has its problems.
Writing good software is a really interesting and challenging task, and when you can get some good results, it's also very fulfilling. Most of the software I write is in C++, but I've also written a fair amount of Java, and dabbled in stuff like PHP, Javascript, and other lesser abominations of languages.
The key to writing good software is in the modelling of the functionality or the abstraction of the functionality into well defined, er, clumps. You want to create little clumps of software that have well defined responsibilities, interfaces and relationships with other clumps.
Of course, writing commercial software requires a whole host of other activities, and the actual modelling and writing of software makes up about 5-10% of a software engineer's job. Unit and system testing, documentation writing, bug investigation and fixing, maintaining build systems, meetings and discussions groups, email flaming, etc etc.
In my spare time a while back I wrote a software package for the management of stock portfolios. Check out StockWhip!
I've worked for such companies as Baltimore Technologies, CyberTrust (now Verizon Business), RSA, and now, Websense. I work on the Email Filter product, fighting the good fight against email spam and other annoyances and threats.