【问题标题】:Detect Incorrect stack variable usage检测不正确的堆栈变量使用
【发布时间】:2011-05-09 17:12:12
【问题描述】:

我的应用程序将某些工作交给工作机构,以在线程池线程中执行,如下所示

void Execute ProcessWork
{
    int nRes = 0;
    CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork();
    // Incorrect use of stack variable
    pProcessMessageWork->m_pStatus = &nRes;
    // Worker Agency
    m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork);
}

CFireProcessMessageWork 的定义如下。下面给出的类的 DoWork 方法将在工作线程中执行。由于变量 nRes 的使用方式不当,我的应用程序偶尔会崩溃。我花了将近一周的时间来确定问题的原因。我尝试使用完整选项和堆栈帧 (/RTC) 的页面堆来检测问题。但应用程序在与问题无关的位置崩溃。

微软是否提供任何工具来检测此类问题?

class CFireProcessMessageWork
{
public:
    int *m_pStatus;
public:
    CFireProcessMessageWork()
    {
        m_pStatus = NULL;
    }
    int DoWork()
    {
     // Using Address of nRes
        *mpStatus = 0;
        // Do Some Work and Pass mpStatus to fill the error code
        HRESULT hRes = pGEMMessageEvents->ProcessMessage(varData, m_nMsgCount, m_newTkt,m_idxFunc,&m_nRetVal);
        return *mpStatus
    }
}

【问题讨论】:

  • 我不知道有什么工具,但你绝对应该有一个流程——它叫做code-review!跨度>
  • 为什么首先要存储地址?

标签: c++ memory-management windbg


【解决方案1】:

问题是这些行中的每一行都对编译器有意义。它们没有任何错误,只是组合并不是很好。即使这样,也需要大量的额外工作和分析才能确定它是错误的用途。

考虑例如,您可以在同一个函数中加入工作线程,然后一切都会正确,如果该函数没有在不同的线程中处理,而只是在 SubmitWork 调用中操作代码,那么这将是正确的...而且编译器不一定知道线程,所以事实是编译器几乎不可能检测到这一点。

另一方面,这对于审阅者来说应该很明显,因此可以通过审阅代码来更好地解决它。其他可能的选择是使用某种形式的共享所有权来处理资源——这可能意味着更多的成本:

void Execute ProcessWork {
    std::shared_ptr<int> nRes = std::make_shared<int>( 0 );
    CFireProcessMessageWork *pProcessMessageWork = new CFireProcessMessageWork();
    pProcessMessageWork->m_pStatus = nRes;                   // copies the shared_ptr
        m_pMessageWorkerAgency->SubmitWork(pProcessMessageWork);
}

在这种情况下,以额外分配为代价的对象的共享所有权保证了线程在更新状态时不会导致未定义的行为。但是,虽然从语言的角度来看,这将使程序正确,但它仍然可能是不受欢迎的:状态将不会在工作线程之外 可读,因为唯一的其他引用是 outside 工人控制。

【讨论】:

  • Rodriguez - dribeas:你有我的 +1 非常详尽的解释 :)
【解决方案2】:

您正在通过传递&amp;nRes 在此处编写语法上有效的代码,但是由于它是堆栈中的本地变量并且正在其他线程中被访问,因此该地址将无效,从而导致崩溃。我认为仔细的同行代码审查应该有助于解决这些问题。

【讨论】:

    猜你喜欢
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 2021-11-02
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    相关资源
    最近更新 更多