在递归调用分段故障对于pthreads [英] Segmentation fault for pthreads in a recursive call

查看:203
本文介绍了在递归调用分段故障对于pthreads的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于$ C $低于C

,我得到一个分段错误,如果我有n> 16运行。

我认为这事做与堆栈,但我不能弄明白。谁能给我个忙吗?在code是不是我的,真的并不重要。我只是想有人给我一个手发生了什么。 这太问题是非常相似,但没有足够的信息(的人谁张贴关于这个问题的答案简短的会谈,但随后继续谈论不同的语言)。此外,请注意,有两个演唱会,没有递归,我可以(如果我做的是正确的)成功创建超过16000线程(虽然OS只会造成约500运行约300)。总之,在这里我在这里,为什么得到赛格故障?谢谢你。

 的#include< pthreads.h中>
#包括LT&;&stdio.h中GT;静态无效* fibonacci_thread(无效* ARG){
INT N =(INT)阿根廷,FIB;的pthread_t TH1,TH2;无效* P值; / *存放值* /开关(N){
情况下0:回报(无效*)0;
情况1:/ * Fallthru蛋白原(1)=蛋白原(2)= 1 * /
案例2:回报(无效*)1;
默认:打破;
}在pthread_create(安培; TH1,NULL fibonacci_thread,(无效*)(N-1));在pthread_create(安培; TH2,NULL fibonacci_thread,(无效*)(N-2));在pthread_join(TH1,&安培; P值);FIB =(INT)P值;在pthread_join(TH2,&安培; P值);FIB + =(int)的P值;回报(无效*)FIB;
}INT主(INT ARGC,CHAR *的argv [])
{
INT N = 15;
的printf(%d个\\ N(INT)fibonacci_thread((无效*)N));
返回0;
}


解决方案

哎呀它,还不如让这个答案。

首先,检查在pthread_create 的返回值和在pthread_join 。 (永远,永远,永远检查错误。只是断言,他们正在返回零,如果你感觉懒惰,但从来没有忽略它们。)

第二,我可以发誓的Linux的glibc通过的 pthread_attr_setstacksize )。当然,这只是虚拟内存,而32位系统仍然限制了你〜2000线程的总数据。

最后,我相信这个线程将产生的数量正确的估计基本上是 FIB(N)本身(多么好听递归)。或约披^ N ,其中(1 +开方(5))/ 2 。所以线程数这里是不是65000,这是我的估计,其中32位系统将运行虚拟机的一致性接近2000。

要确定您的系统上新主题的默认堆栈大小,运行这个程序:

  INT主(INT ARGC,CHAR *的argv [])
{
    为size_t堆栈大小;
    pthread_attr_t ATTR;
    pthread_attr_init(安培; attr指示);
    pthread_attr_getstacksize(安培; attr指示,&安培;堆栈大小);
    phthread_attr_destroy(安培; attr指示);
    的printf(默认堆栈大小=%ZD \\ n,堆栈大小);
    返回0;
}

要重复:这是隔靴搔痒2 ^ 16个线程

令f(n)是计算FIB(n)的时的线程数衍生

当N = 16,一个线程产卵两个新主题:一是计算FIB(15)和另一计算FIB(14)。因此,F(16)= F(15)+ F(14)+ 1。

和一般F(N)= F(N-1)+ F(N-2)+ 1

事实证明,解决这个复发使得f(n)是前n个Fibonacci数的简单相加:

  1 + 1 + 2 + 3 + 5 + 8 // F(6)
+ 1 + 1 + 2 + 3 + 5 // + F(5)
+ 1 // + 1= 1 + 1 + 2 + 3 + 5 + 8 + 13 // = F(7)

这是(非常)粗略披^(N + 1),而不是 2 ^ N 。对于f(16)总在低数千仍计算,而不是成千上万。

嗯,我明白了,你的问题的关键是这(从注释悬挂):


  

感谢尼莫了详细的解答。我做了一个小测试
  pthread_created〜万线只有一段时间(1)内,从而循环
  他们不终止......它做到了!诚然,操作系统很聪明enouth
  只有创造约1000并运行一个更小的数字,但它
  没用完栈。为什么我没有得到段错误,当我产生
  比地段更THREAD_MAX,但是当我做递归怎么办?


下面是我的猜测。

您只有几个核心。在任何时候,内核必须决定的其中线程要运行。如果你有(说)2内核和线程500,那么任何特定线程只会运行时间1/250。所以,你的主循环产生新的线程是不会经常运行。我甚至不能确定内核的调度是否公平相对于单个进程中的线程,所以它至少是可以想象的,与1000线程主线程永远不会在所有运行。

最起码,每个线程执行而(1); 是要出马 1 / HZ 在放弃它的时间片之前,它的核心。这可能为1ms,但它可以根据你的内核是如何配置可高达10毫秒。因此,即使调度是公平的,你的主线程只会让当你有几千个线程一次第二奔波。

由于只有主线程创建新线程,线程创建的速度减慢到爬行,甚至可能停止。

试试这个。相反,而(1); 在实验中的子线程,尝试而(1)暂停(); 。 ( 暂停 从unistd.h中)。这将保持封锁子线程,并应该让主线程保持磨掉创建新线程,导致您的崩溃。

再次,请检查什么在pthread_create 的回报。

Given the code below, I get a segmentation fault if I run it with n>16.

I think it has something to do with the stack, but I can't figure it out. Could anyone give me a hand? The code is not mine, and really not important. I would just like someone to give me a hand with what is happening. This SO question is very similar, but there's not enough information (the person who posts the answer briefly talks about the problem, but then goes on to talk about a different language). Besides, notice that with two gigs and no recursion, I can (if I'm doing it right) successfully create more than 16000 threads (though the OS only creates about 500 and runs about 300). Anyway, where am I getting the seg fault here and why? Thanks.

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

static void* fibonacci_thread( void* arg ) {
int n = (int)arg, fib;

pthread_t th1, th2;

void* pvalue; /*Holds the value*/

switch (n) {
case 0:  return (void*)0;
case 1:  /* Fallthru, Fib(1)=Fib(2)=1 */
case 2:  return (void*)1;
default: break;
}

pthread_create(&th1, NULL, fibonacci_thread, (void*)(n-1));

pthread_create( &th2, NULL, fibonacci_thread, (void*)(n-2));

pthread_join(th1, &pvalue);

fib = (int)pvalue;

pthread_join(th2, &pvalue);

fib += (int)pvalue;

return (void*)fib;
}

int main(int argc, char *argv[])
{
int n=15;
printf ("%d\n",(int)fibonacci_thread((void*)n));
return 0;
}

解决方案

Heck with it, might as well make this an answer.

First, check the return values of pthread_create and pthread_join. (Always, always, always check for errors. Just assert they are returning zero if you are feeling lazy, but never ignore them.)

Second, I could have sworn Linux glibc allocates something like 2 megabytes of stack per thread by default (configurable via pthread_attr_setstacksize). Sure, that is only virtual memory, but on a 32-bit system that still limits you to ~2000 threads total.

Finally, I believe the correct estimate for the number of threads this will spawn is basically fib(n) itself (how nicely recursive). Or roughly phi^n, where phi is (1+sqrt(5))/2. So the number of threads here is closer to 2000 than to 65000, which is consistent with my estimate for where a 32-bit system will run out of VM.

[edit]

To determine the default stack size for new threads on your system, run this program:

int main(int argc, char *argv[])
{
    size_t stacksize;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr, &stacksize);
    phthread_attr_destroy(&attr);
    printf("Default stack size = %zd\n", stacksize);
    return 0;
}

[edit 2]

To repeat: This is nowhere near 2^16 threads.

Let f(n) be the number of threads spawned when computing fib(n).

When n=16, one thread spawns two new threads: One to compute fib(15) and another to compute fib(14). So f(16) = f(15) + f(14) + 1.

And in general f(n) = f(n-1) + f(n-2) + 1.

As it turns out, the solution to this recurrence is that f(n) is just the sum of the first n Fibonacci numbers:

      1 + 1 + 2 + 3 + 5 + 8   // f(6)
+         1 + 1 + 2 + 3 + 5   // + f(5)
+ 1                           // + 1

= 1 + 1 + 2 + 3 + 5 + 8 + 13  // = f(7)

This is (very) roughly phi^(n+1), not 2^n. Total for f(16) is still measured in the low thousands, not tens of thousands.

[edit 3]

Ah, I see, the crux of your question is this (hoisted from the comments):

Thanks Nemo for a detailed answer. I did a little test and pthread_created ~10,000 threads with just a while(1) loop inside so they don't terminate... and it did! True that the OS was smart enouth to only create about 1000 and run an even smaller number, but it didn't run out of stack. Why do I not get a segfault when I generate lots more than THREAD_MAX, but I do when I do it recursively?

Here is my guess.

You only have a few cores. At any time, the kernel has to decide which threads are going to run. If you have (say) 2 cores and 500 threads, then any particular thread is only going to run 1/250 of the time. So your main loop spawning new threads is not going to run very often. I am not even sure whether the kernel's scheduler is "fair" with respect to threads within a single process, so it is at least conceivable that with 1000 threads the main thread never gets to run at all.

At the very least, each thread doing while (1); is going to run for 1/HZ on its core before giving up its time slice. This is probably 1ms, but it could be as high as 10ms depending on how your kernel was configured. So even if the scheduler is fair, your main thread will only get to run around once a second when you have thousands of threads.

Since only the main thread is creating new threads, the rate of thread creation slows to a crawl and possibly even stops.

Try this. Instead of while (1); for the child threads in your experiment, try while (1) pause();. (pause is from unistd.h.) This will keep the child threads blocked and should allow the main thread to keep grinding away creating new threads, leading to your crash.

And again, please check what pthread_create returns.

这篇关于在递归调用分段故障对于pthreads的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆