下記のようなコードはスタック破壊します。
void
my_substr(char **dst, char *str, size_t oft, size_t len)
{
*dst = (char *)malloc(len + 1);
memcpy(*dst, (str + oft), len);
*(dst + len) = '\0';
return;
}
main()から直接呼んだ程度ならその場でセグメント違反となってくれるのでいいのですが、呼ばれる位置が深いと、(処理系によるかもしれませんが)上位関数のスタック領域を上手に壊してくれて別の箇所で異常動作しているように見えるため、原因特定が困難になる場合があります。
このようなバグを簡単に見つけられるような方法や、最近のLinuxで手軽に使えるツールなどを教えてください。
#サンプルコードそのものに対する突っ込みはご容赦ください、説明のため簡略化しているだけですので
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
いわゆる「単体テスト」とかでいけそうな気がするんだけど....
ありがとうございます。
おっしゃることは全く同感で、プログラマには同じことを言いました。
状況としては、
・これまで普通に動いていたように見えたデーモンプログラムが突然落ちたという報告
・実行バイナリ
・落ちたときのスタックトレース
・1万行弱のソースコード
だけの情報が渡され、ここから原因を探れと。
スタックトレースを見ると不自然な落ち方をしていることからスタック破壊だろうとはすぐに想像はつきました。最終的にはコードレビューで原因を特定したのですが、もっと楽に原因箇所の絞り込みができないものかと思った次第です。
No.2
- 回答日時:
私自身にも「このようなバグを簡単に見つけられるような方法や、ツールなど...」は思い当たりません。
ポインタを一旦使えば、何処かで想定外の領域を指定してしまう可能性は常にあるわけで、自分で気をつける以外にないのではないでしょうか。
あるいはC言語を止めて、C++に移行する(それでも保証できるわけではありませんが)ことでしょうか。
ありがとうございます。
やはり難しそうですか。他の情報も待ってみます。
>ポインタを一旦使えば、何処かで想定外の領域を指定してしまう可能性は常にあるわけで、自分で気をつける以外にないのではないでしょうか。
そこを補助してくれるのが、ヒープ領域に関してはElectricFenceやvalgrindが結構強力なツールだと思っています。gdbだけだと上手く動いていない現場周辺から探るしかないため、重宝しています。
No.1
- 回答日時:
ご質問者様が仰る「スタック破壊」とは具体的にどのコードを指しているのでしょうか。
但し、如何にも「ヒープメモリをfree()せずに乱費していそうな」コードに見えます。私自身はヒープメモリに関するトラブルを除くため、オープンソースの"valgrind"を利用しています。
ありがとうございます。
>ご質問者様が仰る「スタック破壊」とは具体的にどのコードを指しているのでしょうか。
ここです。
*(dst + len) = '\0';
正しくは、
*(*dst + len) = '\0';
です。
>"valgrind"を利用しています。
valgrindでは、残念ながらこのバグを検出することはできませんでした。もしかしたらオプションによっては検出できるのかもしれませんが、上手く使いこなせていません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# sprintf()の使い方について 1 2022/08/17 16:16
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# スタックフレームの消滅 6 2023/05/20 12:33
- C言語・C++・C# 略語の読み方について 2 2023/05/25 12:35
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教えるわが家の防犯対策術!
ホームセキュリティのプロが、家庭の防犯対策を真剣に考える 2組のご夫婦へ実際の防犯対策術をご紹介!どうすれば家と家族を守れるのかを教えます!
-
数字以外が入力されたらエラー文を出したい。
C言語・C++・C#
-
画面を強制的に再描画させる方法
C言語・C++・C#
-
メモリのセグメント違反の解決方法を教えてください。
C言語・C++・C#
-
-
4
charからLPTSTRへの変換方法
C言語・C++・C#
-
5
LPSTR型の初期化について
C言語・C++・C#
-
6
CString型からdouble型への変換
C言語・C++・C#
-
7
Run-Timeエラーの原因に関して教えてください。
C言語・C++・C#
-
8
構文エラー;"が型の前にありませんとは、どうしたら解決できるのですか。"
C言語・C++・C#
-
9
UpdateData( FALSE); による文字列データの表示更新(VC++6.0)
C言語・C++・C#
-
10
C言語にて構造体のメンバがNULLであるかを判定するサンプルを作成して
C言語・C++・C#
-
11
多重定義が起きている?--lnk2005エラー:VC++
C言語・C++・C#
-
12
VC++スレッドの正しい終了のさせかた
C言語・C++・C#
-
13
スレッドの監視方法について
C言語・C++・C#
-
14
エラー Run-Time Check Failure #2 - Stack around the variable 'ps' was corrupted.
C言語・C++・C#
-
15
fgetsで拾われる改行文字を削除したい
C言語・C++・C#
-
16
変数の値が勝手に変化する原因
C言語・C++・C#
-
17
#define _CRT_SECURE_NO_WARNINGS について
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
mallocについて
-
reallocについて
-
malloc呼び出し時のセグメンテ...
-
64ビットと32ビットの違い
-
mallocで確保するメモリの領域...
-
gcnew arrayによるメモリ確保に...
-
malloc、new のメモリ確保について
-
ビットをローテートするプログ...
-
stringの最大サイズ
-
大容量の静的な確保の限界値
-
座標値を読み込んである領域に...
-
MSDNがgethostbynameではなくge...
-
char*型が0x0を含む場合
-
DLLのマルチスレッドの動作につ...
-
メモリ不足になってしまう。
-
配列の添え字の最大数とは?
-
スタック破壊の上手な見つけ方...
-
OpenCV cvLoadImageについて
-
allocってなんですか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
newしないオブジェクトについて
-
allocってなんですか?
-
スタック破壊の上手な見つけ方...
-
ヒープメモリの解放について
-
配列の添え字の最大数とは?
-
void*型のデータサイズ
-
c言語のポインタへの文字列入力...
-
DLLのマルチスレッドの動作につ...
-
C++で、メンバもヒープに確保さ...
-
指定したメモリアドレスの値の...
-
win32APIのHeapAlloc()の使い方...
-
ポインタのポインタの初期化法
-
プログラムが途中で強制終了し...
-
大容量の静的な確保の限界値
-
malloc呼び出し時のセグメンテ...
-
ヒープ領域の限界値設定
-
free関数で動作が止まる
-
stringの最大サイズ
-
64ビットと32ビットの違い
-
LPWSTRのコピー
おすすめ情報