コンテンツにスキップ

最終更新:2026-10-12

C++ STL Debug モード

問題

Project ステージの schema の中の fields が変化していました。fields は vector ノードで、各メンバーは std::shared_ptr<arrow::Field> です。前後の vector ポインタを比較したところ、_M_impl の _M_start の位置が変化していることがわかったため、gdb watch でその変化を監視し、どこで変更されたのかを確認する必要があります。

Vector の構造

vector のコード:

https://github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/include/bits/stl_vector.h

typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer
        pointer;
struct _Vector_impl_data
{
    pointer _M_start;
    pointer _M_finish;
    pointer _M_end_of_storage;
}

いくつかの重要な情報を知っておく必要があります:

  • _M_start と _M_finish などはすべて pointer 型です
  • pointer 型は生のポインタ型です

この情報があれば、watch でこの _M_start にどのような変化が起きたかを非常に手軽に観察できます。注意:変化するのはこのポインタ _M_start 自体であって、その値が変化するわけではありません。

Watch

まずアドレスを出力します:

(gdb) p &((arrow::Schema::Impl *)this->output_schema_->impl_)->fields_._M_impl._M_start
$10 = (std::_Vector_base<std::shared_ptr<arrow::Field>, std::allocator<std::shared_ptr<arrow::Field> > >::pointer *) 0xb11dd0

pointer* のアドレスが得られたので、次にそれを watch します。

(gdb) watch *((std::_Vector_base<std::shared_ptr<arrow::Field>, std::allocator<std::shared_ptr<arrow::Field> > >::pointer *) 0xb11dd0)
Hardware watchpoint 2: *((std::_Vector_base<std::shared_ptr<arrow::Field>, std::allocator<std::shared_ptr<arrow::Field> > >::pointer *) 0xb11dd0)

その後 continue すると、変更点に到達します:

(gdb) c
Continuing.


Thread 1 "postgres" hit Hardware watchpoint 2: *((std::_Vector_base<std::shared_ptr<arrow::Field>, std::allocator<std::shared_ptr<arrow::Field> > >::pointer *) 0xb11dd0)

Old value = (std::_Vector_base<std::shared_ptr<arrow::Field>, std::allocator<std::shared_ptr<arrow::Field> > >::pointer) 0x979470
New value = (std::_Vector_base<std::shared_ptr<arrow::Field>, std::allocator<std::shared_ptr<arrow::Field> > >::pointer) 0x9fe1e0
VecSeqNext (node=0x9fdc40) at src/backend/vecexecutor/nodeSeqscan.c:210
210     if (table_scan_getnextslot(scandesc, direction, slot))
(gdb) bt
#0  VecSeqNext (node=0x9fdc40) at src/backend/vecexecutor/nodeSeqscan.c:210
#1  0x00007f45994e5c70 in ExecVecScanFetchInternal
    (node=0x9fdc40, accessMtd=0x7f45994e6335 <VecSeqNext>, recheckMtd=0x7f45994e6430 <VecSeqRecheck>) at src/backend/vecexecutor/execScan.c:146
#2  0x00007f45994e58da in ExecVecScanFetch (node=0x9fdc40, accessMtd=0x7f45994e6335 <VecSeqNext>, recheckMtd=0x7f45994e6430 <VecSeqRecheck>)
    at src/backend/vecexecutor/execScan.c:40
#3  0x00007f45994e5d0b in ExecVecScan
    (node=0x9fdc40, vestate=0x9fdd48, accessMtd=0x7f45994e6335 <VecSeqNext>, recheckMtd=0x7f45994e6430 <VecSeqRecheck>)
    at src/backend/vecexecutor/execScan.c:200
#4  0x00007f45994e6487 in ExecVecSeqScan (pstate=0x9fdc40) at src/backend/vecexecutor/nodeSeqscan.c:246
#5  0x00007f45994c40ce in VecExecProcNodeGPDB (node=0x9fdc40) at src/backend/hook/executor.c:102
#6  0x00007f45994c41c2 in VecExecProcNodeFirst (node=0x9fdc40) at src/backend/hook/executor.c:153
#7  0x00007f45994dc610 in ExecProcNode (node=0x9fdc40) at /home/gpadmin/install/cbdb/include/postgresql/server/executor/executor.h:281
#8  0x00007f45994e2065 in get_current_next_batch (node=0x9fdc40) at src/backend/vecexecutor/execMain.c:1851
#9  0x00007f4599375c76 in get_arrow_record_batch(GetNextCallback, void*) (fn=0x7f45994e204d <get_current_next_batch>, arg=0x9fdc40)
    at c_glib/arrow-glib/reader.cpp:216

関連トピック

コメント