Obfuscated C++

Last Month's Obfuscated C++

Last month we asked you to explain the semantics of function f in the following code:


static void
g(unsigned long x)  {
    if (!x) throw 0;
    if (x&1) {
        try {g(x>>1);} catch (int x) {
            throw x+1;
        }
    }
    g(x>>1);
}
        
int
f(unsigned long l) {
    try {
        g(l);
    } catch (int l) {
        return l;
    }
    return 6;
}
f returns the number of 1-bits in its argument. The actual count is implemented by function g, which always throws its result instead of returning it. The first line of g throws a 0 if the input is 0. Otherwise, the low bit is tested. If it is 1, we recursively call g on x>>1, catch the result, increment it, and rethrow it. (Note that the x in "throw x+1" refers to the caught value, not the argument to g.) If the low bit is 0 we simply call g(x>>1) but do not catch the result.

The calls will recurse down until all of the 1-bits have been shifted off. At that point, an integer 0 will be thrown from the innermost function. That integer will be caught at each level of the call stack that corresponds to a 1-bit, incremented, and rethrown. The final value returned from the top-level g will be the number of 1-bits in the original argument.

The "return 6" in f is a red herring. That code is never executed, since g always exits with a throw.

This Month's Obfuscated C++

Identify the error in the following file:


static char* saved = 0;

void saveString(const char* cp) {
    delete saved;
    saved = new char[strlen(cp)]+1;
    strcpy(saved,cp);
}

char* getString() {
    if(!saved) return 0;
    char* rc = new char[strlen(saved)]+1;
    strcpy(rc,saved);
    return rc;
}


Rob Murray is Director of Operations at the Irvine office of Nuforia, an object-oriented software consulting company based in Houston, TX. He has taught C++ at technical conferences since 1987 and is the author of C++ Strategies and Tactics. He was the founding editor of C++ Report and may be contacted at [email protected].