Posts for 2015 April

Globing in bash

Post by Nico Brailovsky @ 2015-04-30 | Permalink | Leave a comment

There is a pretty common and unnecessary pattern used by bash scripts: whenever you need to loop through a list of file names in a path, you might tempted to write something like this.

for fname in $(ls | grep foo); do echo $fname; done

You can save some typing by using bash-globbing:

for fname in foo; do echo $fname; done

Not only the script should be cleaner and faster, bash will take care of properly expanding the file names and you won't have to worry about things like filenames with spaces. This should also be portable to other shells too.

Want to know more about bash globbibg? Check out http://www.linuxjournal.com/content/bash-extended-globbing


gdb: Print very long strings

Post by Nico Brailovsky @ 2015-04-28 | Permalink | Leave a comment

gdb defaults are usually quite sensible and just "let you work". Some times, though, your project is not very sensible and you have to do weird things in gdb. An example: printing huge strings or vectors to try and reproduce a heisenbug. A lot of people get surprised at first because gdb will refuse to print very long strings, printing only the first few chars. Same for vectors. And if you have many repeating elements (eg "f000000000000000000000000000000bar") you might see something like "fooo0bar". Just type these magic commands to see the whole string:

> set print repeats 0
> set print elements 0

gcc: Optimization levels and templates

Post by Nico Brailovsky @ 2015-04-21 | Permalink | 6 comments | Leave a comment

Analyzing the assembly output for template devices can be a bit discouragging at times, specially when we spend hours trying to tune a mean looking template class only to find out the compiler is not able to reduce it's value like we expected. But hold on, before throwing all your templates away you might want to figure out why they are not optimized.

Let's start with a simple example: a template device to return the next power of 2:

template 
struct Impl_Next_POW2 {
    static const bool is_smaller = n < curr_pow;
    static const long next_pow = _Next_POW2::pow;
    static const long pow = is_smaller? curr_pow : next_pow;
};
template 
struct Impl_Next_POW2 {
    // This specializtion is important to stop the expansion
    static const long pow = curr_pow;
};
template 
struct Next_POW2 {
    // Just a wrapper for _Next_POW2, to hide away some
    // implementation details
    static const long pow = _Next_POW2::pow;
};

Gcc can easily optimize that away, if you compile with "g++ foo.cpp -c -S -o /dev/stdout" you'll just see the whole thing is replaced by a compile time constant. Let's make gcc's life a bit more complicated now:

template 
struct Impl_Next_POW2 {
    static long get_pow() {
        static const bool is_smaller = n < curr_pow;
        return is_smaller?
                    curr_pow :
                    _Next_POW2::get_pow();
    }
};
template 
struct Impl_Next_POW2 {
    static long get_pow() {
        return curr_pow;
    }
};
template 
struct Next_POW2 {
    static long get_pow() {
        return _Next_POW2::get_pow();
    }
};

Same code but instead of using plain static values we wrap everything in a method. Compile with "g++ foo.cpp -c -S -fverbose-asm -o /dev/stdout | c++filt" and you'll see something like this now:

main:
    call    Next_POW2<17>::get_pow()
Next_POW2<17>::get_pow():
    call    _Next_POW2<17, 1l, false>::get_pow()
_Next_POW2<17, 1l, false>::get_pow():
    call    _Next_POW2<17, 2l, false>::get_pow()
_Next_POW2<17, 2l, false>::get_pow():
    call    _Next_POW2<17, 4l, false>::get_pow()
_Next_POW2<17, 4l, false>::get_pow():
    call    _Next_POW2<17, 8l, false>::get_pow()
_Next_POW2<17, 8l, false>::get_pow():
    call    _Next_POW2<17, 16l, false>::get_pow()
_Next_POW2<17, 16l, false>::get_pow():
    call    _Next_POW2<17, 32l, false>::get_pow()
_Next_POW2<17, 32l, false>::get_pow():
    movl    $32, %eax    #, D.2171

What went wrong? It's very clear for us the whole thing is just a chain of calls which could be replaced by the last one, however that information is now only available if you "inspect" the body of each function, and this is something the template instanciator (at least in gcc) can't do. Luckily you just need to enable optimizations, -O1 is enough, to have gcc output the reduced version again.

Keep it in mind for the next time you're optimizing your code with template metaprogramming: some times the template expander needs some help from the optimizer too.


Bash traps: almost like RAII for bash

Post by Nico Brailovsky @ 2015-04-16 | Permalink | Leave a comment

Everywhere, but specially in bash, cleaning up is annoying and error prone. Resource leaks can be common if your bash script is interrupted half-way. Do you need to execute something always, even if your script fails or gets killed? Try using traps:

#!/bin/bash
foobar() {
    echo "See ya!"
}
trap "foobar" EXIT

It doesn't mater how you end this script, "foobar" will always be executed. Want to read more about bash traps? Check here.


C++: Invalidating references to elements in a vector

Post by Nico Brailovsky @ 2015-04-14 | Permalink | Leave a comment

Is this valid C++?

void do_something(const int&);
#include 
void foo() {
    std::vector v = {1,2,3,4,5};
    const int &num = v.at(1);
    v.push_back(42);
    do_something(num);
}

Doesn't seem quite right, does it? push_back will most likely trigger a resize for the vector, and that will invalidate references to elements in the vector. num will end up pointing anywhere and so using it to call do_something is not valid C++. Or is it? What happens if we reserve some space for v?

void do_something(const int&);
#include 
void foo() {
    std::vector v = {1,2,3,4,5};
    v.reserve(40);
    const int &num = v.at(1);
    v.push_back(6);
    do_something(num);
}

It again might seem wrong, but this in fact is valid C++ code. Common sense might tell us that a call to push_back automatically invalidates references to elements in the vector, and it only works because most implementations will do the reasonable thing (ie not to invalidate references unless they must). Turns out the standard makes a special prevision for this case in section 23.3.6.5: a resize for a vector is guaranteed to be triggerd if, and only if, the capacity of the vector is not enough, and references to elements in the vector are guaranteed to be valid unless resize is triggered.

A bit of language laweyering shows that what seems like an error is in fact allowed by the standard, but even if this is valid C++ code you should always keep in mind that assuming that the capacity of a vector will be enough is a VERY big assumption, it's very easy to break and you won't get any warning when it happens (maybe a core dump, if you're lucky).


Code natural selection

Post by Nico Brailovsky @ 2015-04-09 | Permalink | 1 comments | Leave a comment

A funny thought just came to me: if you write nice clean code, it's easy to replace it. Just plug out an object somewhere, replace it with another one implementing the same interface, run the tests. Tada! On the other hand, if you write crappy code it might be nigh impossible to replace it. It will probably be worked around whenever a change is needed, simply adding layers of crust. Maybe that's why legacy code sucks: it's simply code natural selection - and the fittest to survive is simply the crappiest one. I think I'm depressed now.


Ruby-style digit separator for C-98?

Post by Nico Brailovsky @ 2015-04-07 | Permalink | Leave a comment

A silly, and not very useful tip: I love how ruby allows you to write numbers like 1000000 as 1_000_000. Very useful to write benchmarking tests.

Until we get to C++14 we don't have a nice alternative, but we have an ugly hack we can use: instead of writing 1000000 write "1 ## 000 ## 000".

It works, '##' is the preprocessor's token pasting operator, and it will paste two tokens together. Looks ugly, breaks the GUI highlighting, but at least you can count how many zeros you've got.

Nitpicker's corner: multiplying by 10 is easier, but there is no job-safety involved in that.

Nitpicker's corner II: The evaluation order of a chain of '##' is not defined, but I don't expect this to cause any problems; any order of evaluation should result in the same result for this case.


Vim Tip: I want more menus!

Post by Nico Brailovsky @ 2015-04-02 | Permalink | 1 comments | Leave a comment

As a uber vim geek, you shouldn't be using a lot of gui menus. Scratch that, you shouldn't be using any menus at all, period. Still, I'll admit it's a bit hard to remember every single shortcut for actions you rarely use.

Say, for example, you like to encrypt your text. Not always, but every once in a while. Enough to make a shortcut for it but not enough to remember what the shortcut is. You can try to grep your ~/.vimrc. You might find something like:

" Encrypt my stuff
map e ggg?G

(Yes, that command will actually encrypt your text in Vim. Try it!)

Wouldn't it be nice if you had a simpler way, though?

Turns out you can add your "encrypt" command to your gui. Then "menu" commands work just like the "map" family, but they create a GUI menu instead. Change your vimrc to something like this:

" Encrypt my stuff
map e ggg?G
menu Project.Encrypt ggg?G

Now if you reload your vimrc you'll find a new GUI menu created, from which you can easily encrypt your text. Decrypting is left as an exercise to the reader.

Extra tip: Want to try to learn the actual shortcut, like a real vim'er? Then try this:

menu Project.Encryptggg?G ggg?G

Everything after the TAB will be right-aligned: you can use that space to annotate the key-combo you should use next time.

As usual, for more info check :help menu