私は synergy-project.org の古いリビジョン (1.3.4) の奥深くにいて、Solaris Studio 12.4 でビルドしています-m64 でのコンパイルとリンク。これがなぜ厄介なのかを理解するために、ビルドフラグなどで何を見ることができますか? 以下のログでは、プログラムは関数内でブレークポイントが設定されており、間違ったポインターが表示されています。その親 (スタックの「上」) には正しいデータがあります。
(dbx) print &event
&event = 0x948d30
(dbx) up
Current function is TMethodEventJob<CXWindowsScreen>::run
66 (m_object->*m_method)(event, m_arg);
(dbx) print &event
&event = 0xffff80f8be958a60
(dbx) down
(dbx) print event
event = {
m_type = 7354752U
m_target = 0x7091a0
m_data = 0x7036a0
m_flags = 6257120U
}
(dbx) up
Current function is TMethodEventJob<CXWindowsScreen>::run
66 (m_object->*m_method)(event, m_arg);
(dbx) print event
event = {
m_type = 2U
m_target = 0x94ee80
m_data = 0xc838b0d68
m_flags = 0
}
コード:
void
CClientProxy1_0::handleData(const CEvent&, void*)
{
// handle messages until there are no more. first read message code.
UInt8 code[4];
UInt32 n = getStream()->read(code, 4);
while (n != 0) {
// verify we got an entire code
if (n != 4) {
LOG((CLOG_ERR "incomplete message from \"%s\": %d bytes", getName().c_str(), n));
disconnect();
return;
}
// parse message
LOG((CLOG_DEBUG2 "msg from \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3]));
if (!(this->*m_parser)(code)) {
... m_parser は次のように解決されます。
bool
CClientProxy1_0::parseHandshakeMessage(const UInt8* code)
{
if (memcmp(code, kMsgCNoop, 4) == 0) {
// discard no-ops
LOG((CLOG_DEBUG2 "no-op from", getName().c_str()));
return true;
}
else if (memcmp(code, kMsgDInfo, 4) == 0) {
// future messages get parsed by parseMessage
m_parser = &CClientProxy1_0::parseMessage;
if (recvInfo()) {
EVENTQUEUE->addEvent(CEvent(getReadyEvent(), getEventTarget()));
addHeartbeatTimer();
return true;
}
}
return false;
}
}
... 通信プロトコルが進むにつれて m_parser がどのようにリロードされるかに注目してください。
関数へのステップインに関する質問への回答: 関数へのエントリ時に壊れ、関数がすぐにクラッシュします。「parseHandshakeMessage() を handleData() にハードコーディングすると、正しく動作します。ただし、このシステムには、正しく動作するために関数ポインターに依存する他の例があります。コンパイル フラグを投稿する場合がありますが、それらは冗長で広範囲です。