プログラミング

[C言語]スペースを大量に入れるとバグが直るコードを書いてみた

投稿日:

↓こういうツイートがバズっていたので、実際に組んでみた。

バグのあるコード

たとえば、”hogehoge”という文字列の、”o”を”piyopiyo”に置換する、というプログラムをこう書く。
(2/22 11時追記:destのナル終端忘れていたので修正しました。ナル終端は今回のバグとは関係ないです)

#include <stdio.h>

void replace(char *dest, char *src) {
  while (*src != '\0') {
    if (*src != 'o') {
      *dest++ = *src++;
    } else {
      *dest++ = 'p';
      *dest++ = 'i';
      *dest++ = 'y';
      *dest++ = 'o';
      *dest++ = 'p';
      *dest++ = 'i';
      *dest++ = 'y';
      *dest++ = 'o';
      *src++;
    }
  }
  *dest = '\0';
}

void hoge() {
  char str1[] = "fuga";
  char str2[] = "";
  char str3[] = "hogehoge";
  replace(str2,str3);

  printf("%s\n", str2);
}

void main() {
  hoge();
}

実行してみる

hpiyopiyogehpiyopiyoge
Segmentation fault

この通り、なんとか動きはするがセグメンテーション違反を起こす。
ちなみにコンパイラはgcc。他の環境だと別の挙動になるかもしれない。

直ったコード

一見無関係に見える、”fuga”の部分にスペースを大量に注入する。

#include <stdio.h>

void replace(char *dest, char *src) {
  while (*src != '\0') {
    if (*src != 'o') {
      *dest++ = *src++;
    } else {
      *dest++ = 'p';
      *dest++ = 'i';
      *dest++ = 'y';
      *dest++ = 'o';
      *dest++ = 'p';
      *dest++ = 'i';
      *dest++ = 'y';
      *dest++ = 'o';
      *src++;
    }
  }
  *dest = '\0';
}

void hoge() {
  char str1[] = "fuga               "; // スペース注入
  char str2[] = "";
  char str3[] = "hogehoge";
  replace(str2,str3);

  printf("%s\n", str2);
}

void main() {
  hoge();
}

実行してみる

hpiyopiyogehpiyopiyoge

セグメンテーション違反しなくなる。

問題

さてここで問題です。

  1. そもそもなぜセグメンテーション違反していたのでしょうか。
  2. スペースを入れることでセグメンテーション違反が解決したのはなぜでしょうか。
  3. この直し方はもちろん正攻法ではありません。どう直すべきでしょうか。

C言語を学ぶ人は考えてみてください。正解はまわりのC言語ユーザーに聞いてみてね。
そしてC言語を学ばない人は「こんなクソみたいな言語一生使わんわ滅びろ」って思ってください。

-プログラミング

執筆者:

関連記事

GeoJSONで市町村境界をマージして都道府県境界にしたい(実践編)

前々回と前回で問題を整理して、ようやく実践編です。 まず実物のリンク貼りましょう。GitHubに上げました。 今回はGo言語で書いてますが、ポイントがいくつかあります。 ちなみに言語としてGoを選択し …

no image

BlueskyのAPI制限が厳しくなったぞ

以前、Blueskyのbotを作る記事を書いたんですが、そのbotがいつの間にかひどくエラーを吐くようになっていました。 で、調べたところ、API制限が厳しくなっていると。 詳しく言うと、Rate L …

SHOWROOMのガチイベをGoogleスプレッドシートでグラフにしよう

もくじ1 まえがき2 みほん3 だいじな注意事項3.1 Google Apps Scriptの制限3.2 SHOWROOMの仕様4 てじゅん4.0.1 1.4.0.2 2.4.0.3 3.4.0.4 …

no image

例え話をしないC言語のポインタの説明

もくじ1 まえおき2 Hello, Worldより簡単に2.1 サンプルコード2.2 変数の置き場所2.3 変数が入っているところを見てみる3 C言語とメモリ3.1 変数cの「まわり」を見てみる3.2 …

GeoJSONで市町村境界をマージして都道府県境界にしたい(その1)

前回の続きで、国土地理院の「国土数値情報」っていうオープンデータで遊んでいます。独立した記事なので前回のは読まなくても良いです。 もくじ1 やりたいこと2 問題の整理3 「穴」の考慮4 つづく やりた …