[英]Thread stack overflow
在像我们创建任务的vxworks这样的RTO中,指定了stacksize。 我们可以在C中编写一个例程来检查堆栈是否溢出或者没有执行任务吗?
看看你的编译器,他们经常让你添加prelude函数来做这个,或者他们甚至可以自己检查它,除非你操作堆栈指针寄存器。
并检查操作系统是否允许您安装“guard-pages”。 将线程堆栈中的最后一页标记为非读取/非写入并捕获SIGSEGV信号并使用特定于OS / CPU的方式来确定它是否是失败的保护页面。 为此,您必须确保函数的堆栈帧(堆栈传递参数,局部变量和alloca分配的空间)始终小于页面大小,否则您可以跳过“guard-page”这是最好的方法处理它,因为它在正常处理期间没有运行时开销。
你会看到这种高度的OS / CPU /编译器依赖。 但我很确定谷歌会为所有系统找到可用的代码和帮助程序,因为它是低级程序员(例如运行时或解释器实现者)的一种非常常见的技术。
如果你知道堆栈有多大,如果你小心,那么是(但不是便携)。 如果没有其他方法可以获得堆栈的基址,则需要在线程的main函数中记录堆栈变量的地址; 这使您可以近似堆栈的顶部。 然后,在您的检查功能中,您获取局部变量的地址; 这给了你堆栈的底部。 如果顶部和底部之间的差异与您的堆栈大小有关,那么现在是时候担心; 如果差异大于堆栈大小,则担心已经太晚了 - 损坏已经完成(但现在你需要考虑如何清理)。
仅供参考,您可以使用checkStack()从VxWorks中的shell执行类似的操作。
您可以使用一些技术 - 通常您有一个低优先级的任务,每隔一秒左右嗅探所有其他任务的堆栈状态。
a:在任务开始之前,确保堆栈空间已填充已知模式。 然后,您可以通过检查模式找出剩余多少“未损坏的”堆栈。
b:你可以简单地嗅探所有其他线程的堆栈指针。
我建议两者结合使用。 因为你正在使用像VxWorks TaskInfoGet()函数这样的低级东西,所以很难使它甚至可以远程移植。
我不知道VxWorks,但我的回忆是Green Hill的Velosity / uVelosity内核提供了执行此操作的代码。 即使他们没有,因为它们提供了用户可以修改的源,并且基础设施就在那里,所以很容易添加。
编辑:为了披露,我和他们一起做了一个夏季实习,将uVelosity移植到一个新的架构。 这就是我对线程堆栈处理的亲密关系。
如果您的特定应用程序静态分配其线程,则可以将其堆栈放置在静态定义的区域中,并使用链接器映射将符号放置在这些区域的末尾。 然后,您只需要获取当前的堆栈指针(如其他答案中所述),并将“堆栈段结束”指针与该地址进行比较。 如果每个线程都有一些位置来存储作为其堆栈末尾提供给它的地址,那么这也适用于动态分配。
堆栈大小默认为1MB,具体取决于编译器。 根据这些信息,您可以尝试使用以下内容捕获剩余的堆栈:
unsigned long remaining_stack_size() {
char dummy;
return 0x000fffff & (unsigned long)&dummy;
// 0x000fffff is 1MB -1 (1048576 -1)
}
编辑:请注意,它实际上返回当前堆栈位置,这是相同的事情。
编辑(2):对于那些说我错了的人,这里有一个概念证明:
#include <stdio.h>
#include <windows.h>
unsigned long remaining_stack_size() {
char dummy;
return 0x001fffff & (unsigned long)&dummy + 1; // okay, some minor adjusts
}
void recurse_to_death(unsigned long used, char *p) {
char buf[32*1024];
used += 32*1024;
printf("Used: 0x%08x Remaining: 0x%08x\n", used, remaining_stack_size());
recurse_to_death(used, buf);
}
DWORD WINAPI my_thread(void *p) {
printf("Total stack size of this Thread: 0x%08x bytes\n", remaining_stack_size() + 72);
recurse_to_death(0, NULL);
return 0;
}
int main(int argc, char *argv) {
DWORD tid;
// CreateThread's stack size actually defaults to 1MB+64KB and does not honor lower values
CreateThread(NULL, NULL, my_thread, NULL, NULL, NULL);
Sleep(30000);
return 0;
}
remaining_stack_size()
预测堆栈溢出完美。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.