その後も 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++のクラスという概念を使う必要があるでしょう。