You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中取消线程后cout进入错误状态的原因探究

线程取消导致cout进入错误状态的原因分析

问题代码

#include <iostream>
#include <pthread.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
using namespace std;

void *func_1 (void *arg)
{
    for (;;) {
        cout << "1" << endl;
        sleep (1);
    }
    return NULL;
}

void *func_2 (void *arg)
{
    for (;;) {
        cout << "222" << endl ;
        sleep (1);
    }
    return NULL;
}
int main (void)
{
    pthread_t thread_1, thread_2;
    assert (pthread_create (&thread_1, NULL, func_1, NULL) == 0);
    assert (pthread_create (&thread_2, NULL, func_2, NULL) == 0);
    pthread_cancel (thread_1);
    pthread_join (thread_1, NULL);
    pthread_join (thread_2, NULL);
}

程序输出

1
222

问题描述

程序输出上述内容后进入阻塞状态,此时cout.bad()和cout.fail()均返回true;改用printf()则运行正常,调用cout.clear()后程序可恢复正常。需要解释为何cout会进入错误状态。


原因分析

  1. 线程取消打断IO操作
    当主线程调用pthread_cancel(thread_1)时,thread_1可能正处于cout << "1" << endl;的执行过程中——endl会触发标准输出流的缓冲区刷新操作,这个操作涉及内核级系统调用(将缓冲区数据写入终端)。而IO操作属于POSIX定义的线程取消点,线程会在这个点响应取消请求,直接终止执行。

  2. C++流的状态被异常置位
    C标准输出流cout内部维护了状态标志位(如badbit、failbit),用于标识流操作的健康状态。当线程在IO系统调用过程中被强制终止时,未完成的IO操作会被判定为失败,C标准库会自动将cout的badbit和failbit置为true,标记流处于错误状态,后续所有流操作都会直接失败,导致thread_2的cout输出被抑制,程序表现为阻塞。

  3. printf不受影响的原因
    C标准库的printf函数实现逻辑与C++流不同:对于被中断的系统调用,C标准库通常会尝试自动重启系统调用(若对应信号为可重启类型),或者不会将中断关联到流的错误状态上,因此printf可以继续正常输出。

  4. cout.clear()恢复的原理
    cout.clear()函数的作用是重置流的所有错误状态标志位,将badbit、failbit等恢复为false,让cout重新回到可操作状态,后续的流操作即可正常执行。


内容的提问来源于stack exchange,提问作者sixsixqaq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 01:10:27