おもちゃバコ

主に趣味について

問題のあるC++コードについて

こんにちハロ

今回はCEDEC2015で話題になったCoverityクイズについての記事です.

今更な内容ですが,見たときに直ぐに解けなかったので備忘録として残しておきます.


参考文献

この記事の元ネタです.
別の調べ物をしていた時に発見しました.
ota42y.com

同じ内容のプログラムです.
tanku.hatenablog.jp


問題

問題のバグが潜んでいるソースコードに検証を追加したもの.

実行結果

0: 0, 0, 0
1: 0, 0, 0
2: 0, 0, 0
3: 0, 0, 0
4: 0, 0, 0
5: 0, 0, 0
6: 0, 0, 0
7: 0, 0, 0
8: 0, 0, 0
9: 0, 0, 0

0: 0, 0, 1
1: 1, 2, 2
2: 3, 3, 4
3: 4, 5, 5
4: 6, 6, 7
5: 7, 8, 8
6: 9, 9, 0
7: 0, 0, 0
8: 0, 0, 0
9: 0, 0, 0

問題点

添え字と同じ数値をメンバ変数x,y,zに代入したいのに,暗黙の型変換(アップ・キャスト)によってアドレス位置がずれてしまった.

本来はこうなってほしい↓.

0: 0, 0, 0
1: 1, 1, 0
2: 2, 2, 0
...

図解

f:id:lambda410:20210815135204p:plain

解決策

横着せずに1つずつ処理する(参考文献とほぼ同じ).
根本的に解決したい場合は,参考文献を参照してください.


メモリ構造

Coverityクイズだけでは薄いので,クラスのメモリ構造について簡単な検証をして見ました.
特に解説はないですが,クラス配置ついてなんとなく理解が深まった気がします.

sizeof
int        : 4
base       : 8
derived    : 12
base_h_f   : 8
derived_h_f: 12

base_class address
    base  : 0x7ffcc71ede30
    base.x: 0x7ffcc71ede30
    base.y: 0x7ffcc71ede34

derived_class address
    derived  : 0x7ffcc71ede20
    derived.x: 0x7ffcc71ede20
    derived.y: 0x7ffcc71ede24
    derived.z: 0x7ffcc71ede28

base_have_func address
    base_h_f        : 0x7ffcc71ede10
    base_h_f.x      : 0x7ffcc71ede10
    base_h_f.y      : 0x7ffcc71ede14
    base_h_f::func  : 0x4008a2

derived_have_func address
    derived_h_f        : 0x7ffcc71ede00
    derived_h_f.x      : 0x7ffcc71ede00
    derived_h_f.y      : 0x7ffcc71ede04
    derived_h_f.z      : 0x7ffcc71ede08
    derived_h_f::func  : 0x4008a2
    derived_h_f::funcX : 0x4008d2

まとめ

C++は奥が深い.