Skip to content

AudioPlayer 启动线程时可能存在其它数据成员还未初始化,导致未定义行为 #27

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Mq-b opened this issue Sep 26, 2024 · 1 comment
Labels
bug Something isn't working issue-resolved 问题已解决

Comments

@Mq-b
Copy link
Owner

Mq-b commented Sep 26, 2024

#include <iostream>
#include <thread>

struct X{
    X(){
        // 假设 X 的初始化没那么快
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::puts("X");
    }
};

struct Test{
    Test(): t{&Test::f, this} // 线程已经开始执行
    {}
    ~Test(){
        if(t.joinable())
            t.join();
    }
    void f()const{ // 如果在函数执行的线程 f 中使用 x 则会存在问题。使用了未初始化的数据成员 ub
        std::cout<<"f\n";
    }

    std::thread t; // 声明顺序决定了初始化顺序,优先初始化 t
    X x;
};

int main(){
    Test t;
}

这本质还是初始化顺序问题,在第四章的 AudioPlayer 实现中就有此问题,需要注意。

std::atomic<bool> stop;              // 控制线程的停止与退出,
std::thread player_thread;           // 后台执行音频任务的专用线程
std::mutex mtx;                      // 保护共享资源
std::condition_variable cond;        // 控制线程等待和唤醒,当有新任务时通知音频线程
std::queue<std::string> audio_queue; // 音频任务队列,存储待播放的音频文件路径
sf::Music music;                     // SFML 音频播放器,用于加载和播放音频文件

这样的声明顺序可能导致线程对象已经初始化,启动线程执行成员函数 playMusic,而互斥量、条件变量、队列、音乐播放器 等成员还未初始化,产生未定义行为

可以自行调整顺序顺序或直接将启动线程这件事情在构造函数体中做(因为这是最后的过程),又或者创建一个 start 函数,等等... 常见做法。

文档

初始化顺序

列表中的成员初始化器的顺序无关紧要:初始化的实际顺序如下:

  1. 如果构造函数是最终派生类的,那么按基类声明的深度优先、从左到右的遍历中的出现顺序(从左到右指的>是基说明符列表中所呈现的顺序),初始化各个虚基类。
  2. 然后,以在此类的基类说明符列表中出现的从左到右顺序,初始化各个直接基类。
  3. 然后,以类定义中的声明顺序,初始化各个非静态成员。
  4. 最后,执行构造函数体。
@Mq-b Mq-b added the bug Something isn't working label Sep 26, 2024
@Mq-b Mq-b closed this as completed in 8f46c3f Sep 26, 2024
@Mq-b Mq-b added the issue-resolved 问题已解决 label Sep 26, 2024
@Mq-b
Copy link
Owner Author

Mq-b commented Sep 26, 2024

不修正原来的代码,这是一个常见的情况,值得学习。

@Mq-b Mq-b changed the title AudioPlayer 启动线程时可能存在其它数据成员还未初始化,导致未定义行为 AudioPlayer 启动线程时可能存在其它数据成员还未初始化,导致未定义行为 Sep 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working issue-resolved 问题已解决
Projects
None yet
Development

No branches or pull requests

1 participant