How often have I told myself, "I'll kludge this now and rewrite it later"? And how many times did I actually go back and rewrite that kludgy bit? "Too often" and "not enough". Many job postings include the phrase "update legacy applications," as a euphemism for "rewrite poorly-designed spaghetti." The Y2K problem was a huge exercise in code out-living the developer's plan, with a healthy dose of cargo-culting thrown in. Lately, I've been learning to plan for a likely possibility: My code will survive to haunt my bug lists and my resume for a long time.
... or "Ask Not To Whom The Pointer Points, It Points To Thee."
TL;DR: A pointer is not a reference. A pointer knows nothing about the data being pointed to. Returning multiple values requires actual work.
Everything went wrong when I wanted a string with a
NUL character inside it.
C strings are not Perl scalars, they don't know how long they are. So to mark
the end of a string, C uses the
strcpy function will
copy to your destination until the first
\0 from your source. When you want to
have a string with a
\0 inside of it that does not mark the end of the string,
you need to know exactly how long the string is. This is not difficult to do,
but you also have to return that length from the function that creates your
C functions do not have more than one return value.
(char* buffer, int bufferSize) = get_string_with_nuls(); // You thought it could be that easy?
So in order for your function to result in more than one value, you have to pass in references to be used to fill in with actual values.
char* buffer; int bufferSize = get_string_with_nuls( buffer ); // C programmers will already know what I did wrong here
Thinking like a Perl programmer, I thought I could just pass in the pointer to the function and the function could fill it with data. Two problems:
- I passed in the pointer itself, not a reference to the pointer:
- I did not initialize the pointer to anything.
A more correct way would be:
char* buffer = malloc( 128 * sizeof( char ) ); int bufferSize = get_string_with_nuls( &buffer );
But this suffers from another problem: I have to know beforehand how big my string is going to be and allocate that much memory beforehand.
The way I ended up succeeding was:
int bufferSize; char* buffer = get_string_with_nuls( &bufferSize );
get_string_with_nuls can handle the
malloc with exactly the correct
size and give it to me. I don't have to guess at a size beforehand.
Of course, a struct could do this better, or since I'm actually in C++, an object. I'll be planning a new API as soon as I confirm this one actually works and has proper tests (written in Perl, of course).
... or Why A Good Perl Developer Is Not Automatically A Good C Developer, the Story of C Programming via Google.
My tests failed, but only sometimes. I was building an XS module to interface
with a C wrapper around a C++ library (wrapper unnecessary? probably).
test was failing with exit code 11. Some quick searching revealed that I had
an intermittent segfault. Calling a function
as_xml would fail with a SEGV in
strlen(). This only happened in perl after
as_xml when perl was making a SV
out of the return value. This also only mainly happened during
prove myself would succeed 19 times out of 20, where make test would
fail 19 times out of 20. Worse, my C test program would never fail at all.
A major milestone in WebGUI 8 development was reached this week: A dry-run of the WebGUI 8 upgrade was successfully run against the plainblack.com database. This means the only thing remaining from releasing an alpha 8.0.0 is updating all the custom code on http://plainblack.com and http://webgui.org. As always, plainblack.com and webgui.org will be the first sites running the latest bleeding-edge version of WebGUI (unless one of you wants to beat me to the punch).
This month, I also gave a presentation to Madison.PM about building applications in WebGUI 8, a quick introduction to Assets and an overview of the most important changes to how they work. The slides are available at http://preaction.github.com/ and the code samples are linked at the end.
On an unrelated topic, I really enjoyed using S5 to build my slides, SHJS to highlight the code inside, and Github Pages to host the whole thing. I plan on doing the same for all my presentations: They look good, readable without a special program, editable without a special program, anyone can fork and update my presentations, and they're served by a nice, fast, free host.