::Hikaru's blog

調べたこと, 考えたことをメモ.
<< December 2017 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 >>

スポンサーサイト

一定期間更新がないため広告を表示しています

- | permalink | - | -

構造体にナゾの隙間

以下のような構造体Bを定義すると、ナゾの隙間ができる。 struct A { virtual void funcA() {} }; struct B : virtual A { B() {} virtual void funcA() {} }; 構造体Bのレイアウト 0+-----+ |vbptr| 4+-----+ | 0 | ← ????? 8+-----+ |vfptr| 12+-----+

Bのコンストラクタを書かなかったり、B::funcA()を書かなかったりすると隙間はなくなる。
Bにメンバ変数を追加すると、その分のサイズが伸びるので、単純にパディングというわけでは無さそう。
謎である。(VC++7, VC++9で確認)
C, C++ | permalink | comments(3) | trackbacks(0)

_mm_malloc

_aligned_malloc

<malloc.h>
#define _mm_malloc(a, b) _aligned_malloc(a, b)
C, C++ | permalink | comments(0) | trackbacks(0)

複雑な宣言の読み方

1. 識別子を探す。 2. 直近の()があれば"function returning"とする。 3. 直近の[]があれば"array of"とする。 4. 直近の*があれば"pointer to"とする。 5. 直近の&があれば"reference to"とする。 6. 2〜5を最後まで繰り返し、日本語へ翻訳する。(右から訳していく) # constは無視 # 関数の引数は無視 int* X[10]; array of pointer to int intへのポインタの配列 int (&X())[10]; function returning reference to array of int intの配列への参照を返す関数 int (*X[10])(); array of pointer to function returning int intを返す関数へのポインタの配列 (参照: K&E 第2版 5.12 複雑な宣言)
C, C++ | permalink | comments(0) | trackbacks(0)

多次元配列の全要素を積算する

#include <numeric> template<class Ty> struct sum_t { typedef Ty type; }; template<class Ty, size_t N> struct sum_t<Ty[N]> // 部分特殊化 { typedef typename sum_t<Ty>::type type; }; template<class Ty, size_t N> typename sum_t<Ty>::type sum(Ty (&arr)[N]) { typedef typename sum_t<Ty>::type Result; Result* p = reinterpret_cast<Result*>(arr); return std::accumulate(p, p + sizeof(arr) / sizeof(Result), Result()); } int main() { double arr[][3][3] = { {{11,12,13},{14,15,16},{17,18,19}}, {{21,22,23},{24,25,26},{27,28,29}}, {{31,32,33},{34,35,36},{37,38,39}}, }; double ret = sum(arr); }
C, C++ | permalink | comments(0) | trackbacks(0)

不完全型のdelete

不完全型(未定義の型)をdeleteした時の動作は未定義です。

ISO/IEC 14882 5.3.5
If the object being deleted has incomplete class type at the point of deletion and the complete class has a non-trivial destructor or a deallocation function, the behavior is undefined.
(削除されるオブジェクトが削除時点で不完全な型であって、その完全クラスが自明でないデストラクタ又は開放関数をもつ場合、その動作は、未定義とする。)

struct Hoge;
void func1(Hoge* pHoge)
{
  delete pHoge; // Hogeのデストラクタが呼び出されない
}


特にauto_ptrでハマりやすいです。

struct FugaImpl;
struct Fuga
{
  auto_ptr<FugaImpl> m_pImpl;
};

void func2()
{
  Fuga fuga;
} // FugaImplのデストラクタが呼び出されない

boost::shared_ptrではboost::checked_deleterを使い、リンク時に解決させることでこの問題を回避しています。
C, C++ | permalink | comments(0) | trackbacks(0)

auto_ptr_ref

auto_ptr_refは、右辺値のauto_ptrをコピーできるようにするための中間型です。

例えば、
auto_ptr<foo> create_foo()
{
return auto_ptr<foo>(new foo);
}
void func1()
{
auto_ptr<foo> pfoo = create_foo();
}

func1では、create_fooによって作られる一時オブジェクト(右辺値)をpfooへコピーしますが、auto_ptrには右辺値を受け取れる(const参照を引数に持つ)コピーコンストラクタは定義されていません。
(const auto_ptrにもかかわらず、コピーによって所有権が移動してしまうため)

しかしauto_ptrには、auto_ptr_refを引数に持つコンストラクタと、auto_ptr_refへの変換演算子が定義されているので、暗黙の型変換によりコピーが可能なわけです。
C, C++ | permalink | comments(1) | trackbacks(0)

名前空間のエイリアス

namespace foobar = foo::bar;
C, C++ | permalink | comments(0) | trackbacks(0)

Template template parameter

template <typename> class List;

template <typename T, template <typename> class Cont>
class Stack {
Cont<T> m_Cont;
};

int main()
{
Stack<int, List> stack;
return 0;
}
C, C++ | permalink | comments(0) | trackbacks(0)

CRTのメモリリークのチェック機能

crtdbg.hをインクルードするとmallocとfreeが_malloc_dbgと_free_dbgに置き換わり、CRTのヒープの状況を監視する。
_CrtDumpMemoryLeaksを呼び出せば、ヒープ内の開放されていないオブジェクトすべてをダンプできる。
また、CrtSetDbgFlagで_CRTDBG_LEAK_CHECK_DFを指定するとプログラム終了時に自動的にCrtDumpMemoryLeaksを呼び出してくれる。

#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>

int flag = ::_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
::_CrtSetDbgFlag(flag | _CRTDBG_LEAK_CHECK_DF);

出力例:
> Detected memory leaks!
> Dumping objects ->
> {56} normal block at 0x003A58A0, 1 bytes long.
> Data: < > CD
> Object dump complete.

_CrtSetBreakAlloc(56);
としておけば、newしている箇所でブレイクさせることができる。

メモリ リークの検出と特定
C, C++ | permalink | comments(2) | trackbacks(0)

mallocとfreeはモジュールを越えてはいけないのか

問. DLL内でmallocされたポインタをEXE側でfreeしてはいけないのか。また、new、deleteについてはどうか。

答. DLL、アプリケーションの両方でCRT(Cランタイムライブラリ)をダイナミックリンクしている場合はOK。

# 確認を行った環境はMicrosoft Visual C++ 7.1です。

以下、詳細な説明…
続きを読む >>
C, C++ | permalink | comments(0) | trackbacks(0)