Log in

No account? Create an account
Now I remember why I try to avoid coding in c.... - Nick [entries|archive|friends|userinfo]

[ website | gagravarr.org ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Now I remember why I try to avoid coding in c.... [Sep. 5th, 2009|07:12 pm]
At work, in common with most IT firms, we have a need to securely store a lot of passwords. Quite a while ago we settled on PWMan as the tool to do this with. It has a nice ncurses front end, and uses gpg encrypted xml files under the hood, so there's no worries about getting your data out if you ever want to go to anything else. After posting a few patches, several of us were given commit access, and all was good.

Roll forward to last week, and I'm now the only active maintainer of the project. We haven't had any problems with pwman for a while, but there are one or two features that people have asked for, and I figured it might be good to try to implement a few of them. The biggest thing was search (filtering results on the screen has been in there for an age, but not finding all entries anywhere in the tree). As pwman is written in c (using ncurses and libxml2 directly), there isn't anyone else at work who was comfortable making the changes, so it was either I do them or no-one would. I had a couple of hours spare, and I figured that might be enough. My hunch was 20-30 minutes were it in python, double it as I hadn't worked on the codebase lately, apply my usual "it's java not python, double it" multiplier, and hope that c and java coding times are similar. That gave me 2 hours, which seemed fine.

How wrong was I...

We're now at about 6 hours of coding, and search is almost but not quite fully implemented. Firstly I wrote the search algorithm and structures as I would in python, perl or java, only to remember at the last moment that auto-extending arrays and vanilla c don't mix, and I didn't want to have to pull in something like APR as a dependency at this stage. So, back to the drawing board, and I had to re-write the whole thing (algorithm, data structures etc) using linked lists.

Then, when I compiled and ran the program normally, and did a search it segfaulted. Compiled it without the optimisations, and with the -g flag, and ran it under gdb. No segfault, seemed to be fine. I was very bemused. Then I ran it a bit longer under gdb, and eventually managed to trigger the segfault.

At this point, I was once again reminded of why I don't like c. The bug was a simple, schoolboy error - I'd added a couple of new fields to a structure, but I'd forgotten to null one of them. Not something you need to worry about with java, python or perl, but as any C hacker will tell you, very very important there. I'd remembered for almost all of my new fields, forgotten one, and thus as soon as the memory was re-used for another similar structure (more common at the higher optimisation levels), it all went to pot :(

So, I did a full review of all the structure creating code, spotted a few other places that might need it too and added it explicitly, then all seemed fine. I do now know a lot more about using gdb than I used to, but it's all taken longer than I'd hoped for, and so I still haven't managed to find the time to write the rest of the UI. Hopefully I'll get a chance soon, and then pwman will have nice and shiny search. In the mean time, I'm reminded why lots of people end up deciding that porting non-performance critical code from c to python is worth doing when they want to add moderately complicated features....