吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1602|回复: 15
收起左侧

[讨论] Qt编译器报错error: use of undeclared identifier 'pthread_getat...

[复制链接]
Pojie1999.0909 发表于 2023-6-3 17:06
本帖最后由 Pojie1999.0909 于 2023-6-4 12:03 编辑

操作系统:windows 10
Qt版本:Qt5.14.2
编译器:MinGW 7.3.0 32bit for C++
已经在头文件添加了
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <pthread.h> // 使用pthread_getattr_np()函数需要定义宏_GNU_SOURCE,而且要在pthread.h前定义

但是使用pthread_getattr_np时,编译器依然提示错误,error: use of undeclared identifier 'pthread_getattr_np'
什么情况?有没有大佬遇到过?怎么解决?

2023-06-04_120045.png

2023-06-04_115737.png




[C++] 纯文本查看 复制代码
#include <QCoreApplication>
#include <QDebug>
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <pthread.h> // 使用pthread_getattr_np()函数需要定义宏_GNU_SOURCE,而且要在pthread.h前定义
#include <stdio.h>
#include <stdlib.h>
#include "unistd.h" // for sleep
#include <errno.h>


using namespace std;

// Qt Creator非常智能,已经不需要在代码中手动添加pthread头文件和库了,就像一个内置线程库。

/// 线程函数
void* thfunc(void *arg)
{
    qDebug() << "in thfunc";
    return (void*)0;
}
/// 线程函数1
void* thfunc1(void *arg)
{
    int *pn = (int*)arg; // 获取参数地址
    int n = *pn;         // 解引
    qDebug() << QString("in thfunc:n=%1").arg(n);
    return (void*)0;
}
/// 线程函数2
void* thfunc2(void *arg)
{
    char *str;
    str = (char*)arg; // 得到传进来的字符串
    qDebug() << QString("in thfunc:str=%1").arg(str);
    return (void*)0;
}

typedef struct // 定义结构体的类型
{
    int n;
    char *str;
}MYSTRUCT;
/// 线程函数3
void* thfunc3(void *arg)
{
    MYSTRUCT *p = (MYSTRUCT*)arg; // 得到传进来的字符串
    qDebug() << QString("in thfunc:n=%1,str=%2").arg(p->n).arg(p->str); // 打印结构体的内容
    return (void*)0;
}

int gn = 10; // 定义一个全局变量,将会在主线程和子线程中用到
/// 线程函数4
void* thfunc4(void *arg)
{
    gn++; // 递增1
    qDebug() << QString("in thfunc:gn=%1").arg(gn); // 打印全局变量gn的值
    return (void*)0;
}

/// 线程函数5
void* thfunc5(void *arg)
{
    qDebug() << "sub thread is running";
    return NULL;
}

/// 输出自定义的错误信息
#define handle_error_en(en,msg) do {errno=en;perror(msg);exit(EXIT_FAILURE);} while (0)
static void* thread_start7(void *arg)
{
    int i,s;
    pthread_attr_t gattr; // 定义线程属性结构体
    s = pthread_getattr_np(pthread_self(),&gattr); // 获取当前线程属性结构值
    if(s!=0)
        handle_error_en(s,"pthread_getattr_np"); // 打印错误信息
    qDebug() << "Thread's detachstate attribute";
    s = pthread_attr_getdetachstate(&gattr,&i); // 从属性结构值中获取分离状态的属性
    if(s)
        handle_error_en(s,"pthread_attr_getdetachstate");
    qDebug() << QString("Detach state =%1").arg(
                    (i == PTHREAD_CREATE_DETACHED)?"PTHREAD_CREATE_DETACHED" :
                    (i == PTHREAD_CREATE_JOINABLE)?"PTHREAD_CREATE_JOINABLE" :
                    "???");
    pthread_attr_destroy(&gattr);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 创建一个简单的线程,不传参数
    pthread_t tidp;
    int ret;
    ret = pthread_create(&tidp,NULL,thfunc,NULL); // 创建线程
    if(ret)
    {
        qDebug() << QString("pthread_create failed:%1").arg(ret);
        return -1;
    }
    sleep(1); // main线程挂起1秒,为了让子线程有机会去执行
    qDebug() << "in main:thread is created";

    // 创建一个线程,并传入整数类型的参数
    pthread_t tidp1;
    int ret1,n1=110;
    ret1 = pthread_create(&tidp1,NULL,thfunc1,&n1); // 创建线程并传递n1的地址
    if(ret1)
    {
        qDebug() << QString("pthread_create failed:%1").arg(ret1);
        return -1;
    }
    pthread_join(tidp1,NULL); // 等待子线程结束
    qDebug() << "in main:thread is created";

    // 创建一个线程,并传递字符串作为参数
    pthread_t tidp2;
    int ret2;
    const char *str2="hello world";
    ret2 = pthread_create(&tidp2,NULL,thfunc2,(void*)str2); // 创建线程并传递str2的地址
    if(ret2)
    {
        qDebug() << QString("pthread_create failed:%1").arg(ret2);
        return -1;
    }
    pthread_join(tidp2,NULL); // 等待子线程结束
    qDebug() << "in main:thread is created\n";

    // 创建一个线程,并传递结构体作为参数
    pthread_t tidp3;
    int ret3;
    MYSTRUCT mystruct3; // 定义结构体
    // 初始化结构体
    mystruct3.n = 1100;
    mystruct3.str = "hello world!";
    ret3 = pthread_create(&tidp3,NULL,thfunc3,(void*)&mystruct3); // 创建线程并传递mystruct3结构体的地址
    if(ret3)
    {
        qDebug() << QString("pthread_create failed:%1").arg(ret3);
        return -1;
    }
    pthread_join(tidp3,NULL); // 等待子线程结束
    qDebug() << "in main:thread is created\n";

    // 创建一个线程,共享进程数据
    pthread_t tidp4;
    int ret4;
    ret4 = pthread_create(&tidp4,NULL,thfunc4,NULL); // 创建线程
    if(ret4)
    {
        qDebug() << QString("pthread_create failed:%1").arg(ret4);
        return -1;
    }
    pthread_join(tidp4,NULL); // 等待子线程结束
    gn++; // 子线程结束后,gn再递增1
    qDebug() << QString("in main:gn=%1").arg(gn); // 再次打印全局变量gn的值

    // 创建一个可分离线程
    /* 分离状态(Detached State)是线程很重要的一个属性。POSIX线程的分离状态决定一个线程以什么样的方式来终止自己。
     * 这里所说的分离状态是POSIX标准下的属性所特有的,用于表明该线程以何种方式终止自己。默认的分离状态是可连接的,即创建线程时如果使用默认属性,
     *   则分离状态属性就是可连接的,因此默认属性下创建的线程是可连接的线程。
     * POSIX下的线程要么是分离的,要么是非分离的(也称可连接的,joinable)。前者用宏PTHREAD_CREATE_DETACHED表示,
     *   后者用宏PTHREAD_CREATE_JOINABLEB表示。默认情况下创建的线程是可连接的,一个可连接的线程可以被其他线程收回资源和杀死(或称撤销),
     *   并且不会主动释放资源(比如堆栈空间),必须等待其他线程来回收它占用的资源,因此我们要在主线程中调用pthread_join()函数(阻塞函数,
     *   当它返回时所等待的线程的资源就被释放了)。
     * 如果是可连接的线程,那么线程函数自己返回结束时或调用pthread_exit()结束时都不会释放线程所占用的堆栈和线程描述符(总计8KB多),
     *   必须调用pthread_join()且返回后才会释放这些资源。这对于父进程长时间运行的进程来说会是灾难性的。
     *   因为父进程不退出并且没有调用pthread_join(),则这些可连接线程的资源就一直不会释放,相当于变成僵尸线程,僵尸线程越来越多,
     *   再想创建新线程时将没有资源可用!
     * 重要的事情再说一遍,一个可连接的线程所占用的内存仅当有线程对其执行pthread_join()后才会释放,因此为了避免内存泄漏,
     *   可连接的线程在终止时,要么已被设为DETACHED(可分离),要么调用pthread_join()函数来回收资源。
     *   另外,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join()的线程将得到错误代码ESRCH。
     * 可分离的线程。这种线程运行结束时,它的资源将会立刻被系统回收。可以这样理解,这种线程是能独立(分离)出去的,可以自生自灭,父线程不用管它。
     * 一个线程设置为可分离状态有两种方法:一种方法是调用函数pthread_detach(),它可以将线程转换为可分离线程;
     *   另一种方法是在创建线程时就将它设置为可分离状态,基本过程是首先初始化一个线程属性的结构体变量(通过函数pthread_attr_init()),
     *   然后将它设置为可分离状态(通过函数pthread_attr_setdetachstate()),最后将该结构体变量的地址作为参数传入线程创建函数 pthread_create(),
     *   这样所创建出来的线程就直接处于可分离状态了。
    */
    pthread_t thread_id5;
    pthread_attr_t thread_attr5;
    struct sched_param thread_param5;
    size_t stack_size5;
    int res5;
    res5 = pthread_attr_init(&thread_attr5);
    if(res5)
        qDebug() << "pthread_attr_init failed:" << res5;
    res5 = pthread_attr_setdetachstate(&thread_attr5,PTHREAD_CREATE_DETACHED);
    if(res5)
        qDebug() << "pthread_attr_setdetachstate failed:" << res5;
    res5 = pthread_create(&thread_id5,&thread_attr5,thfunc5,NULL);
    if(res5)
        qDebug() << "pthread_create failed:" << res5;
    qDebug() << "main thread will exit";
    sleep(1);

    // 创建一个可分离的线程,且main线程先退出
    /* 对于可连接的线程,主线程可以调用pthread_join()函数等待子线程结束。
     * 对于可分离线程,并没有这样的函数,但是可以先让主线程退出而进程不退出,一直等到子线程退出了才退出进程。
     * 也就是说,在主线程中调用函数pthread_exit(),如果在main线程中调用了pthread_exit(),那么此时终止的只是main线程,
     *   而进程的资源会为由main线程创建的其他线程保持打开的状态,直到其他线程都终止。
     *   值得注意的是,如果在非main线程(其他子线程)中调用pthread_exit(),则不会有这样的效果,只会退出当前子线程。
    */
    pthread_t thread_id6;
    pthread_attr_t thread_attr6;
    struct sched_param thread_param6;
    size_t stack_size6;
    int res6;
    res6 = pthread_attr_init(&thread_attr6); // 初始化线程结构体
    if(res6)
        qDebug() << "pthread_attr_init failed:" << res6;
    res6 = pthread_attr_setdetachstate(&thread_attr6,PTHREAD_CREATE_DETACHED); // 设置分离状态
    if(res6)
        qDebug() << "pthread_attr_setdetachstate failed:" << res6;
    res6 = pthread_create(&thread_id6,&thread_attr6,thfunc5,NULL); // 创建一个可分离的线程
    if(res6)
        qDebug() << "pthread_create failed:" << res6;
    qDebug() << "main thread will exit";
    pthread_exit(NULL); // 主线程退出,但进程不会此刻退出,下面的语句不会再执行
    qDebug() << "main thread has exited, this line will not run"; // 此句不会执行
    /* 正如我们预料的那样,在main线程中调用了函数pthread_exit()后将退出main线程,但进程并不会在此刻退出,而是等到子线程结束后才退出。
     *   因为是分离的线程,所以它结束的时候所占用的资源会立刻被系统回收。如果是一个可连接的(joinable)线程,
     *   则必须在创建它的线程中调用 pthread_join()函数来等待可连接线程的结束并释放该线程占用的资源。
     * 在任何一个时间点上,线程是可连接的(Joinable),或者是分离的(Detached)。一个可连接的线程在自己退出或pthread_exit()时
     *   都不会释放线程所占用堆栈和线程描述符(总计8KB多),需要通过其他线程调用pthread_join()之后才释放这些资源;
     *   一个分离的线程是不能被其他线程回收或杀死的,所占的资源在它终止时由系统自动释放。
    */

    // 获取线程的分离状态属性
    pthread_t phr7;
    int s7;
    s7 = pthread_create(&phr7,NULL,&thread_start7,NULL); // 创建线程
    if(s7!=0)
    {
        handle_error_en(s7,"pthread_create");
        return 0;
    }
    pthread_join(phr7,NULL); // 等待子线程结束

    return a.exec();
}

免费评分

参与人数 1吾爱币 +1 收起 理由
xouou + 1 你用的是vc编译器?

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Pojie1999.0909 发表于 2023-6-3 17:22
真是搞不懂,有没有大佬给看看?
一闪一闪233 发表于 2023-6-3 18:26
pthread_getattr_np函数是GNU C库(glibc)的一个扩展函数,因此它可能不是所有平台和编译器的标准函数。请确保您的编译器和操作系统支持该函数。

如果您的编译器不支持该函数,您可以尝试使用其他可用的方法来获取线程属性,或者查阅您所使用的编译器的文档,了解如何在特定环境下获取线程属性。

如果您需要进一步的帮助,请提供您正在使用的编译器和操作系统的详细信息,以便我能够提供更具体的建议。
Eaglecad 发表于 2023-6-3 21:30
这是在window下?window下需要安装支持gnu的编译器,比如mingw。Linux需要在pro里增加链接库 lpthread
ShenBohemian 发表于 2023-6-4 00:13
在linux系统中可以成功编译并运行
Snipaste_2023-06-04_00-12-31.png
Arthurian 发表于 2023-6-4 10:10
这是Windows吗?pthread是Linux的多线程库。如果是Windows环境,单纯加GNU宏定义是不行的
Dlan 发表于 2023-6-4 10:57
既然是QT ,为何不用 QThread
 楼主| Pojie1999.0909 发表于 2023-6-4 11:50
Dlan 发表于 2023-6-4 10:57
既然是QT ,为何不用 QThread

想学习学习这个posix。
 楼主| Pojie1999.0909 发表于 2023-6-4 11:52
Arthurian 发表于 2023-6-4 10:10
这是Windows吗?pthread是Linux的多线程库。如果是Windows环境,单纯加GNU宏定义是不行的

是的,我是在windows下的qt写的,windows下没办法使用pthread_getattr_np获取线程属性吗?我是用mingw编译的。
 楼主| Pojie1999.0909 发表于 2023-6-4 11:53
ShenBohemian 发表于 2023-6-4 00:13
在linux系统中可以成功编译并运行

谢谢!一会儿我搞个虚拟机也试试。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 22:44

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表