【问题标题】:Part of pthread stack seems to be already used部分 pthread 堆栈似乎已被使用
【发布时间】:2023-03-06 16:27:01
【问题描述】:

我已将 Linux 中 pthread 的堆栈大小设置为 16 KB。如果我随后将一个大于 8 KB 的数组压入堆栈,应用程序会因分段错误而停止。在我看来,我正在尝试访问堆栈底部以下的内存,这可能是未映射的内存,因此是段错误。

这里是示例代码:

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <string.h>

void *start_routine(void *arg)
{
  size_t size = 9*1024;
  unsigned char arr[size];

  memset(arr, 0, size);
}

int main()
{
  int err;
  pthread_attr_t threadAttr;
  size_t stacksize;
  void *stackAddr;
  pthread_t thread;

  pthread_attr_init(&threadAttr);
  pthread_attr_setstacksize(&threadAttr, 16*1024);
  pthread_attr_getstacksize(&threadAttr, &stacksize);
  printf("stacksize: %d\n", stacksize);

  pthread_create(&thread, &threadAttr, start_routine, NULL );
  pthread_join(thread, NULL);

  return 0;
}  

我丢失了大约 8 KB 的堆栈似乎很奇怪。我也尝试了稍大的堆栈大小。不知何故,我可以使用多少堆栈似乎有所不同。

我知道对于现在的系统(除了一些嵌入式系统)来说,这几个字节并不重要,但我只是好奇为什么我不能使用大部分定义的堆栈。我不希望我可以使用整个堆栈,但减少大约 8 KB 似乎相当多。

在调用入口例程之前,线程的堆栈中放置了哪些信息?

谢谢 菲利普

【问题讨论】:

  • 我在 MacOS 上使用 gcc 编译和运行程序没有问题。
  • 我唯一能想到的是你可以检查 pthread_attr_setstacksize(...) == 0 的返回值。如果你尝试,手册页说它返回 -1 并将 errno 设置为 EINVAL将堆栈大小设置为高于某些系统强加的限制。不过,这似乎不太可能。
  • 看看ulimit -s 的输出 - 你可能没有得到每个线程的全部 16K。
  • @Kevin 很高兴知道您可以在 MacOS 上运行该程序。也许你可以尝试增加数组的大小,看看你能走多远?
  • @Kevin pthread_attr_setstacksize 函数返回 0。此外,我还有 pthread_attr_getstacksize 的堆栈大小请求。这似乎很好。

标签: stack pthreads


【解决方案1】:

在对 glibc nptl 源代码进行一些调查后,我得出的结论是,在堆栈的底部放置了拥有堆栈的线程的 pthread-struct,并且可能还有一些其他变量,具体取决于 glibc 配置。他们一起使用大约3K。堆栈的顶部充满了保护页,通常为 4K 大。因此,已经使用了大约 7-8K。我有点惊讶,至少保护页面的内存没有单独分配。在我的脑海中,我想记住会是这样,但事实并非如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-18
    • 1970-01-01
    • 2019-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 2019-04-15
    相关资源
    最近更新 更多