本日はとても寒くて

今朝は冷え込みました 夜出かける用事があるため、今朝は自転車に乗らず、歩いてきました 従って、起床も 6:00AMとゆっくり目でした
比較的最短コースに近いルートで歩きましたが、とても寒く、「これは自転車で海岸通り通っていたらば、大変だった」と、実感したのです
病院でカンファランスに参加した後、藤沢公証人役場に行ったのです、一か月ぐらい前にも行きました
何でそんな所に行かねばならないか? と言いますと、シンガポール厚生省が、今度のシンガポール・ライブデモンストレーションでPCI術者を行うために、必要だと要求してきたからです
彼らの要求は、まずパスポートを認証しろ、でした これって如何にも矛盾ですよね、おかしいんじゃないの?
それが済んでから、今度は、専門医資格を認証しろ、です 本当に馬鹿じゃないの? という感じです
こんなこといちいち要求されていたらば、もう彼の国でPCIを指導する気にはなりませんね
まあ、そんな国、と思えばそれでもいいのですが、日本人の中には彼の国にカブレた人も多いので、「一体どうなってるの?」という思いです
ということで今朝のルートは
2012_12_19Morning_Walk

本日のPCI

昨日夕方に福岡空港に飛び、唐津の行きつけの日本でもご本の指に入る、という寿司の名店で当地の先生方と食事しました。相変わらず美味しい寿司、大将の才能が輝いています。それに、昨日は何時もよりも、一層気合が入っておられました。昨日のシャリは最高のものでした。絶妙の水加減と炊き加減、そして赤酢と塩、素晴らしいものがありました。松尾雄二さん、川崎先生、森先生、ありがとうこざいました。
そして、本日は 久留米の新古賀病院で何年振りにPCIを行わせて頂きました。ここでは川崎先生、芹川先生はじめ多くの先生方にお世話になりました。かれこれ四年ぶりでしょうか、新古賀病院を訪問させて頂くのは・・・
多分最後に訪れさせて頂いたのは、CVIT総会でのライブデモンストレーションで術者として行わせて頂いた時だったと思います。その時、会場から流れていた他の病院からの慢性完全閉塞のライブデモンストレーションで、とんでもないことになっているのを、カテ室で僕は手技を続けながら見ていた記憶があります。
今回は、3例の方の治療を行わせて頂きましたが、全員合併症無く、成功裏に終了でき、とても嬉しく思います。これから鎌倉に戻ります。鎌倉に戻ったらば、お魚を捌いて、そして塩や酢で〆て、下ごしらえするのです。今日しかできません。
そして、明日も忙しい日々です。

strcat()の考察2

さて、これまでに膨大な数のC言語によるプログラムが作られてきました。実際現代社会のインフラはほとんどC言語によって作られた、と言っても過言ではないでしょう。

それでは、実際にこれまではどのようにしてstrcat()を運用していたのでしょうか?

僕の推定は以下のようです

char buffer[256];
// 予め余分な文字列バッファを確保しておく

char* my_strcat(char* str1, const char* str2) {
  char *buftop = buffer;
  if ((strlen(str1)+strlen(str2)) > 256) exit(1);
  strcpy(buffer, str1); 
  while (*buffer++ != '\0');
  buffer--;
  while ((*buffer++ = *str2++) != '\0');
  return buftop;
}

つまり、冗長性を持った余分なbuffer領域をこのstrcat()関数の外で予め確保し、そこを用いてコピーや連結を行う、というものです。
これならば、安全ですよね。でもなんだかダサいですね。

strcat()についての考察

その後も char* strcat(char* str1, const char* str2)関数について考察続けています。これはC標準で定義されている文字列連結関数です。str1という文字列の後ろに、str2という文字列を連結し、連結された文字列をstr1に格納すると共に、関数の戻り値として文字します。実際にやり取りされているのは、文字列最初の文字へのポインタ(メモリ中のアドレス)だけであり、多量のメモリ・コピーは発生しません。

この関数を自分で実装する方法として、ネットでも多く公開されているのは以下のようなものです

#include <stdlib.h>

char* my_strcat(char* str1, const char* str2) {
  char* str = str1;         // str1先頭アドレスを確保しておく
  while (*str1++ != '\0'); // str1へのポインタを文字列終端\0に達するまで
            // 増加させる ループを抜けた時には、str1の
  str1--;         // 文字列終端の次に来るのでアドレスを戻す必要がある
  while ((*str1++ = *str2++)!='\0');
             .// str1にstr2の先頭から終端に到達するまでコピーする
  return str;
}

しかしながら、このプログラムを見れば分かるように、これではstr1というデータ領域を超えてstr2というデータが書き込まれてしまいます

C/C++ではstr1やstr2のようなローカル変数はスタック上に確保されますので、その結果、関数の戻りアドレスを確保してあったスタックも破壊されかねません。そうなれば、もちろんプログラム全体が異常終了してしまいます。非常に危険な buffer overflowという罠です。

これを避けるためには、stringクラスを用いるか、予めstr1用に巨大なバッファを用意しておくか、それとも HEAP領域から動的にメモリ・バッファを確保するかしかありません。もちろん、stringクラスでは内部的にバッファを確保してくれているのでしょう。

HEAPより確保するものとしては、例えば以下のようになります

#include <cstdlib>

char* my_strcat(char* str1, const char* str2) {
  char* str = new char[strlen(str1)+strlen(str2)+1];
  // 動的にHEAP領域から2つの文字列を入れる分メモリ確保
  strcpy(str, str1); // 新たなバッファにstr1をコビー
  strcat(str, str2);  // その後ろにstr2を安全に連結
  retrun str;
}

しかし、これでは重大な問題が発生します それはメモリー・リークというものです。この関数内ではHEAP領域から毎回 str1+str2+1の長さのメモリーを確保しているのですが、関数終了時に、それを開放していません。従って、この関数呼出を何回も繰り返していると、やがてHEAP領域が枯渇するため、突然プログラムが異常終了してしまいます。いわゆる実行時エラーが発生します。

この重大な問題を解決するためには、やはり C++のクラスという概念を使う必要があるでしょう。

 

やっぱり

僕の考察は正しかったようです strcat()という C言語の string.hで定義されている文字列連結関数は、バッファ・オーバーフローを非常におこし易い関数のようです。危険で使えませんね、これでは。

やはり、C++の時代には極力C文字列関数は使用せず、安全なstringクラスを使用せねばならない、ということでしょう。あるいは、僕のプログラム中でしているように、わざわざ必要な長さの文字列バッファを、heap領域に取得するのが良いのでしょうか

何時になればバラ色の未来が?

一週間ぶり、いや、最後に朝の海岸を走ったのが12/06でしたので、何と10日間以上のブランクがありました。この間に 市民公開講座、鎌倉ライブデモンストレーション、札幌と函館の出張と続きました。昨日はきちんと選挙にも行き、国民の権利を行使しました。

今朝 5:30AMに起床してから、テレビで選挙結果を見て、それでダラダラしながら心の中で「今日は天気も悪いし走らないでもいいのでは」と、怠惰な心が囁きかけるのです。

しかし、6:00AMになって、決意しました。「走ろう」です。それで出発したのですが、足の筋肉は痛いは、息は苦しいは、で全然ペースが上がりません。おまけに由比ヶ浜に差し掛かる頃には、小雨がぱらついてきたのです。そして巨福呂坂にさしかかる頃には、「今日はここまで走ってきて頑張ったから、自転車を歩いて押して巨福呂坂を登ればいいや」と、考え始めました。

ところが、坂の上り口で応援して下さっていたのです。まるでにんじんをぶら下げられた馬のように、それで俄然登り始めました。やはり苦しい、何時までたっても苦しい。本当に楽になるのでしょうか?

そして本日の記録が以下の通り、まあ走り切ったから良し、とします。

20121217Morning_Run

C++のお勉強

ここ数日既にuploadしている 自転車乗りプログラムを見直しています。そして、クラス定義に重大な問題点を発見したのです。それは、コピー・コンストラクタと代入演算子の二つを定義していなかったために発生するバグです。これに気づきましたので、 Cyclistクラスの定義を次のように改良しました。

class Cyclist 
{
    // 自転車乗りオブジェクト
private:
    Cyclist() {}
protected:
    int _power; // 自転車漕ぐ力
    const char* _name; // 名前
    char* _temp;
public:
    Cyclist(int power, const char* name)
            :_power(power), _name(name) {
                _temp = new char[strlen(_name)+strlen("は")];
    }
    const char* operator() (int slope) {
        if (_power < slope) return "登れない\n";
        else return "登れる\n";
    }
    const char* name() {
        strcpy(_temp, _name);
        return strcat(_temp, "は");
    }
    ~Cyclist() {
        if (_temp != NULL) delete _temp;
    }
    Cyclist(const Cyclist& orig) {
        this->_temp = new char[strlen(orig._name)+strlen("は")];
        this->_power = orig._power;
        this->_name = orig._name;
    }
    Cyclist& operator= (const Cyclist& orig) {
        if (this->_temp != NULL) delete _temp;
        this->_temp = new char[strlen(orig._name)+strlen("は")];
        this->_power = orig._power;
        this->_name = orig._name;        
    }
}; // Cyclist

そこでさらに新たな疑問が湧いたのです それは、Cの文字列関数である strcatなのです strcatとは String Concanateの略であり、第一引数と第二引数に C文字列に対するポインターを渡すと、連結された C文字列のポインターが戻り値として戻る標準的関数です

そこで思った疑問は、戻される文字列は新たにメモリー領域を確保されているのか否か? というものです。もしも第一引数の終わりに単純に付け足せば、第一引数確保メモリー領域近傍のデータあるいはプログラムを破壊するのでは? という疑問です

ネットで strcat()自作プログラムを調べても、全て単純に第一引数に続いて第二引数をコピーしているだけなのです。この疑問から逃れられませんでしたので、上のプログラムではわざわざ戻り値領域を newで確保しています。どなたか教えて下さい。