【问题标题】:9th call to clone produces seg fault第 9 次调用克隆产生 seg 错误
【发布时间】:2012-02-20 17:55:23
【问题描述】:

我遇到了克隆函数的问题,因为它在第 9 次调用后给我一个分段错误。程序运行良好,直到我使用 9 个以上的线程。

这是我要克隆的电话:

void **child_stack = (void **) malloc(SIGSTKSZ);
clone (func,
       (child_stack + SIGSTKSZ),
       CLONE_VM | CLONE_FILES | CLONE_PARENT_SETTID,
       (void *) argsForFunc,
       &pid);

我使用的是克隆,而不是任何更高级别的线程库,例如 pthreads。

如果有帮助,这是我在使用 GDB 时遇到的错误:

Program received signal SIGSEGV, Segmentation fault.
clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:66
66              movq    %rcx,8(%rsi)
Current language:  auto; currently asm

【问题讨论】:

  • 为什么是 void** child_stack,而不仅仅是 void* child_stack?
  • 为什么要使用clone 而不是pthreads 或其他线程库?

标签: c linux segmentation-fault clone


【解决方案1】:

这是我的克隆电话

不要这样做。在您更正指针算术(由 Jay Conrod 回答)之后,您的代码将因竞争条件而死去,因为您没有按照 glibc 期望的方式设置 TLS(线程本地存储)。

实际上,如果您使用直接的clone 调用,则不能永远在新的“线程",否则您将面临间歇性(并且非常难以调试)故障的风险。只需改用pthread_create()

这是 glibc bug 显示您将遇到的各种问题(请注意,这不是 glibc 问题)。

(1) 因为动态符号解析需要访问 glibc。

【讨论】:

    【解决方案2】:

    TJD 上面的评论让我立即看到了问题:您获取堆栈末尾的指针算法不正确。如果您将堆栈分配为:

    void **child_stack = (void **) malloc(SIGSTKSZ);
    

    然后你计算栈顶为:

    child_stack + SIGSTKSZ
    

    传递给克隆的实际地址将是

    child_stack + sizeof(void*)*SIGSTKSZ
    

    也许您的意思是让child_stack 具有char* 类型? sizeof(char) 的定义是 1,所以这会给你正确的结果。

    【讨论】:

      猜你喜欢
      • 2014-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-05
      • 2019-11-15
      • 2018-06-30
      • 2016-12-31
      • 1970-01-01
      相关资源
      最近更新 更多