memorandums

日々の生活で問題解決したこと、知ってよかったことなどを自分が思い出すために記録しています。

デバッグの理論と実践の1章のsample.cのruby版をつくってみた

以下は、デバッグの方法について、独自?の理論を展開している本です。

デバッグの理論と実践 ―なぜプログラムはうまく動かないのか

デバッグの理論と実践 ―なぜプログラムはうまく動かないのか

独自といってもUdacityにも採用されているくらいですから1つの王道とも言えるかもしれません。

www.udacity.com

私見ですが、実際にプロがこれを読んでみなが賛同するか。。。は微妙と感じます。それでもデバッグの方法について経験や勘だけに頼らず論理的な手順を示したという点では、もしかすると世界初なのではないかと思います。

この1章に、この著者が提案するデバッグの手順(TRAFFIC)を概観する例題があります。

以下の著者のページにソースファイルがありますので、そちらから転載しています。

www.whyprogramsfail.com

/* sample.c -- Sample C program to be debugged */

#include <stdio.h>
#include <stdlib.h>

static void shell_sort(int a[], int size)
{
    int i, j;
    int h = 1;

    do {
        h = h * 3 + 1;
    } while (h <= size);
    do {
        h /= 3;
        for (i = h; i < size; i++)
        {
            int v = a[i];
            for (j = i; j >= h && a[j - h] > v; j -= h)
                a[j] = a[j - h];
            if (i != j)
                a[j] = v;
        }
    } while (h != 1);
}

int main(int argc, char *argv[])
{
    int *a;
    int i;

    a = (int *)malloc((argc - 1) * sizeof(int));
    for (i = 0; i < argc - 1; i++)
        a[i] = atoi(argv[i + 1]);

    shell_sort(a, argc);

    printf("Output: ");
    for (i = 0; i < argc - 1; i++)
        printf("%d ", a[i]);
    printf("\n");

    free(a);

    return 0;
}

このソースにはバグがあります。詳しくは上記の本を読んでいただきたいのですが、argcの理解が浅いことが起因するエラーになります。

このC言語のプログラムを講義用にRubyに置き換えたものが以下です。

def shell_sort(a, size)
  h = 1
  loop do
    h = h * 3 + 1
    break if h > size
  end

  loop do
    h /= 3
    for i in h..(size-1) do
      v = a[i]
      j = i
      while j >= h && a[j - h] > v do
        a[j] = a[j - h]
        j -= h
      end
      if i != j then
        a[j] = v
      end
    end
    break if h == 1
  end
end

#main

a = [0, 0, 0]
for i in 0..(ARGV.size-1) do
  a[i] = ARGV[i].to_i
end

shell_sort(a, a.size)

puts "Output: "
for i in 0..(a.size-1) do
  print a[i], " "
end

なるべく元のプログラムに似せて作っていますのでrubyらしさはないと思います。また、C言語では許される文法もrubyでは実行時エラーが出るのでちょっと変えているところもあります。すぐにばれちゃいそうですが。。。

上記のソースをa.rbとし、本書の通り、以下のような「14 11」という引数を与えて実行をすると。

ruby a.rb 14 11

実行結果は「0 11 14」となります。本プログラムは昇順でソートするので「11 14」となるのが正解なのですが0がはいる。。。なぜだろう?という例題です。

あまり役立つ人はいないかもしれませんが。。。とりあえずログとして。