8

我只是在我的项目中使用 Intel Parallel 检查器,它显示一个警告:

应用程序中的一个或多个线程访问了另一个线程的堆栈。这可能表明您的应用程序中存在一个或多个错误。

我确实有一些在线程之间共享的堆栈上分配的对象。我不明白为什么这是一个问题。有什么提示吗?

4

2 回答 2

10

没有错,只是可能错了。像 Intel Parallel Inspector 这样为您的程序提供额外诊断的工具必须在误报和误报之间进行权衡,在这种情况下,开发人员似乎认为访问另一个线程的堆栈更有可能是一个错误(低假阳性率(如果报告)比不(高假阴性率,如果不报告)。

Valgrind 是另一个可以在正确的代码中发出错误信号的工具示例。

这里真正的问题是,“另一个线程在做什么?” 如果你认为,“也许它会从那个函数返回并且堆栈帧将是无效的”,那么你做的并行编程是错误的。没有关于多线程行为的答案应该用“也许”来限定。您最好确保该线程不会返回,例如,通过使其等待信号量或条件变量,或使其与其他线程连接。

讨论

Pubby: “AFAIK 效率非常低。”

它效率低下的唯一原因是您可能有多个内核修改相同的缓存行,这与其他类型的共享内存具有相同的问题。

Collin:你怎么知道堆栈帧在另一个线程中仍然是好的?

如果你在多个线程中使用某些东西,你会使用某种同步机制来确保它不会以无效的方式被修改。这种情况也不例外。

H2CO3:嗯,你有什么理由不应该走进别人的房子吗?

如果我们要进行类比,我会说进程就是房子,每个线程都是房子里的人。如果戴夫在他的房间里有一份家务清单,我每次需要查看清单时都会去他的房间。如果他停止这样做,他最好告诉我,否则我会开始在他桌子上的随机纸片上写字。

结论

这个程序的行为是否可以接受是一个风格问题。

于 2013-01-28T20:51:13.597 回答
5

想象一下——一个线程正在执行,一个方法被调用,该方法具有一个本地(堆栈)变量(一个对象)。它将这个对象添加到工作队列中,该队列由单独的线程处理。

该线程获取第一个线程添加的项目并访问第一个线程的堆栈上的对象。

在此期间第一个线程做了什么?它可能已退出该方法并释放了该堆栈空间。释放的空间可能会或可能不会被重新使用。访问第一个线程的堆栈的第二个线程可能会或可能不会正常工作,具体取决于时间和调用图。

如果您知道堆栈变量在第二个线程处理它时将存在,那么这样做是安全的;例如,如果线程 1 将堆栈变量排队,然后阻塞,直到线程 2 通知它已完成处理,这是一个安全操作。

发出警告而不是错误是因为这可能是也可能不是合法操作,并且分析仪无法确定。

于 2013-01-28T20:54:20.783 回答