【问题标题】:For loop not terminating once condition is met using pthread使用 pthread 满足条件后,for 循环不会终止
【发布时间】:2021-09-14 05:15:16
【问题描述】:

当我发现 for 循环没有终止时,我正在编写一段多线程代码。起始代码大概是这样的:

for(int i = V-1-tid; i >= 0; i-=NTHREADS){
  */ stuff */
}

V 和 NTHREADS 是常量,tid 是使用 pthread_create 传递的线程 id。

然后我从循环中删除了所有内容并编写了类似的内容以确保没有任何东西干扰i

for(int i = 0; i<100; i++){
  std::cout<<i<<"<100? "<<(i<100)<<std::endl;
}

这仍然没有停止。

我使用简单的方法生成线程:

for(int i = 0; i < NTHREADS; i++){
  pthread_create(&(threads[i]), NULL, foo, &(parameters[i]));
}

我尝试将i 声明为volatile,但这并没有改变。 如果我用-O0 编译,那么循环会正确停止,但-O0 上面的所有内容都有同样的问题。

我使用的是gcc 9.4.0,更具体地说是g++-9 (Homebrew GCC 9.4.0) 9.4.0,我使用的标志是:

-O3 -mavx -mavx2 -mfma -std=c++11 -march=native -fno-rtti -lquadmath -lpthread -g

我目前正在查看 gcc 的程序集输出以了解发生了什么,但了解优化的 x86 有点痛苦。

我是否遗漏了一些明显的东西?有什么我可以尝试的吗?

编辑:添加示例。

示例代码:

#include <iostream>
#include <pthread.h>
#define NTHREADS 1

void *foo(void *args){
  for(int i = 0; i < 100; i++){
    std::cout<<i<<std::endl;
  }
}

int main(){
  pthread_t threads[NTHREADS];

  for(int i = 0; i < NTHREADS; i++){
    pthread_create(&(threads[i]), NULL, foo, NULL);
  }

  for(int i = 0; i < NTHREADS; i++){
    pthread_join(threads[i], NULL);
  }
}

我得到的输出可以在这里看到:godbolt.org/z/Mfjrj6Khr

【问题讨论】:

  • 您只写了有关症状的文章,但没有足够的信息来了解您为什么会得到您所得到的。请尝试提供minimal reproducible example
  • 感谢您告诉我。我添加了一个具有相同行为的示例。
  • 你从那个例子中得到了什么输出?我在这里得到了预期:godbolt.org/z/4YTqYPdcn。虽然从技术上讲代码具有未定义的行为,因为foo 不返回void*,即输出可以是任何东西
  • 如果我在 Godbolt 上添加 -O3 那么它不会停止:godbolt.org/z/Mfjrj6Khr
  • 添加return NULL。我可以用int main() { foo(0); }复制

标签: c++ gcc pthreads


【解决方案1】:

代码具有未定义的行为 - 函数具有返回类型 void * 但不返回任何内容。编译器会感到困惑并生成一个无限循环。

确保启用并听取编译器警告,它们会告诉您:

1.cpp: In function ‘void* foo(void*)’:
1.cpp:7:1: warning: no return statement in function returning non-void [-Wreturn-type]
    7 | }
      | ^

我能想到的最短的 MCVE 说明了这一点:

#include <cstdio>
void* foo() {
  for(int i = 0; i < 100; i++){
    putchar(i);
  }
}
int main() {
    foo();
}

当使用 g++11.1 在 Godbolt 上使用 -O3 编译时:

foo():
        push    rbx
        xor     ebx, ebx
.L2:
        mov     rsi, QWORD PTR stdout[rip]
        mov     edi, ebx
        add     ebx, 1
        call    putc
        jmp     .L2            # Just an endless loop.
main:
        sub     rsp, 8
        call    foo()

【讨论】:

    猜你喜欢
    • 2013-04-08
    • 1970-01-01
    • 2012-02-21
    • 2019-01-29
    • 2013-11-22
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多