Linux から Solaris にプログラムを移植し、solarisstudio 12.3 でビルドします。
次の定義があります。
typedef std::list<ISocketMultiplexerJob *> CSocketJobs;
typedef CSocketJobs::iterator CJobCursor;
CSocketJobs m_socketJobs;
そしてこのコード:
CSocketMultiplexer::CJobCursor
CSocketMultiplexer::nextCursor(CJobCursor cursor)
{
CLock lock(m_mutex);
CJobCursor j = m_socketJobs.end();
CJobCursor i = cursor;
while (++i != m_socketJobs.end()) {
if (*i != m_cursorMark) { // CRASHES HERE!!
j = i;
// move our cursor just past the job
m_socketJobs.splice(++i, m_socketJobs, cursor);
break;
}
}
return j;
}
次の理由により、上記の行でクラッシュします。
(dbx) print i
i = {
_C_node = (nil)
}
「++i」反復がリストから外れたように見えますが、m_socketJobs.end() に対するテストはそれを確認できず、通過させました。デバッグのヘルプが必要です。たとえば、dbx の *i をより C++ に適した方法で解析するにはどうすればよいですか?
nextCursor() の呼び出し元は、このスニペット <> にあります。
// collect poll entries
if (m_update) {
m_update = false;
pfds.clear();
pfds.reserve(m_socketJobMap.size());
CJobCursor cursor = newCursor();
CJobCursor jobCursor = nextCursor(cursor);
while (jobCursor != m_socketJobs.end()) {
ISocketMultiplexerJob* job = *jobCursor;
if (job != NULL) {
pfd.m_socket = job->getSocket();
pfd.m_events = 0;
if (job->isReadable()) {
pfd.m_events |= IArchNetwork::kPOLLIN;
}
if (job->isWritable()) {
pfd.m_events |= IArchNetwork::kPOLLOUT;
}
pfds.push_back(pfd);
}
jobCursor = nextCursor(cursor); //FATAL CALL
}
関数 newCursor() は次のとおりです。
CSocketMultiplexer::CJobCursor
CSocketMultiplexer::newCursor() {
CLock lock(m_mutex);
return m_socketJobs.insert(m_socketJobs.begin(), m_cursorMark);
}
私はいくつかの変更を行い、 newCursor()/nextCursor() が機能し、機能しないことを発見しました....おそらく別のスレッドがコンテキストを傷つけています。以下の例 (私のプログラムに埋め込まれています) では、「CJobCursor c = newCursor();」の最初の init 「c= nextCursor(c);」という行を挿入できます。私のプログラムのどこにいてもクラッシュしません。しかし、「BAD」というコメントが付いた次のものには欠陥があり、2 回目の nexCursor() 呼び出しでクラッシュします。これは興味深いと思いますが、まだ説明がありません。コンテキストが物事を殺しているので、プログラム全体の中でテストを続ける必要があると思います。どう思いますか?
void
CSocketMultiplexer::serviceThread(void*)
{
std::vector<IArchNetwork::CPollEntry> pfds;
IArchNetwork::CPollEntry pfd;
CJobCursor c = newCursor();
CJobCursor j = nextCursor(c);
c = nextCursor(c);
c = nextCursor(c);
// service the connections
for (;;) {
CThread::testCancel();
// wait until there are jobs to handle
{
CLock lock(m_mutex);
while (!(bool)*m_jobsReady) {
m_jobsReady->wait();
}
}
// lock the job list
lockJobListLock();
lockJobList();
// collect poll entries
if (m_update) {
m_update = false;
pfds.clear();
pfds.reserve(m_socketJobMap.size());
CJobCursor cursor = newCursor(); //BAD, Ill-fated object
CJobCursor jobCursor = nextCursor(cursor);
c = nextCursor(c);
cursor = nextCursor(cursor); // SEGV's here
while (jobCursor != m_socketJobs.end()) {
ISocketMultiplexerJob* job = *jobCursor;
if (job != NULL) {
pfd.m_socket = job->getSocket();
pfd.m_events = 0;
if (job->isReadable()) {
pfd.m_events |= IArchNetwork::kPOLLIN;
}
if (job->isWritable()) {
pfd.m_events |= IArchNetwork::kPOLLOUT;
}
pfds.push_back(pfd);
}
c = nextCursor(c);
jobCursor = nextCursor(cursor);
}
c = nextCursor(c);
deleteCursor(cursor);
}