プログラミング

[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言語を学ばない人は「こんなクソみたいな言語一生使わんわ滅びろ」って思ってください。

-プログラミング

執筆者:


comment

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

関連記事

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

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

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

まえがき SHOWROOMのガチイベ、と言えば配信者が獲得ポイント数でランキングされ、最終的にファンの札束で殴り合って勝者を競う札束タワーバトルなわけです。 数日~数週間にわたって配信者同士でランキン …

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

前回の続きで、国土地理院の「国土数値情報」っていうオープンデータで遊んでいます。独立した記事なので前回のは読まなくても良いです。 やりたいこと 国土数値情報で提供されている「行政区域データ」は、市町村 …

no image

C言語のポインタに関する補足説明

前回、C言語のポインタに関する解説記事を書きまして、そこそこの反響を貰うとともにいくつかの指摘を受けました。 前回の記事では幾つか「ウソではないけど真実と違う」記述がありまして、その点を補足としていく …

no image

UnityのCompute Shaderに線分と三角形の衝突判定をさせる

はじめてCompute Shader使ってみた。でもあまり性能は出ないのでただの失敗の記録です。 まず元のアルゴリズムはコレ。 線分と三角形の当たり判定 – 富士見研究所 で、これをまず三角形の表裏問 …