鱼C论坛

 找回密码
 立即注册
查看: 1721|回复: 3

C++ std::bad_function_call 与 Segmentation Fault 同时出现

[复制链接]
发表于 2023-8-3 16:27:08 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 hellomyprogram 于 2023-8-4 07:15 编辑

在我的代码中,如果保留 threads.cpp 第 46 行的 if (function) ,那么我的程序会突然无响应。
而如果删除的话,我的代码会报 Segmentation Fault 和 std::bad_function_call ,但是它们出现似乎是随机的,有的时候有,有的时候没有。
Minecraft for C.zip (5.58 KB, 下载次数: 3)
Segmentation Fault 错误出现在 main.cpp 的第 17 行。 std::bad_function_call 出现在 threads.cpp 的第 45 行。
请问这是为什么?又怎么解决?

--- 已解决 ---
问题出自内存泄漏,在 DistributeThread::run 下调用了 sleep 函数,但是 sleep 函数只接受整数,因此我输入的小数都被整型化为 0 ,因此 DistributeThread “疯了”,乱发任务,导致内存泄漏,在崩溃时刻,线程里的任务队列已经积攒到百万数量级。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-8-3 16:27:29 | 显示全部楼层
这种情况通常发生在多线程代码中,涉及了竞态条件(race condition)或者内存访问错误。Segmenation Fault 表示你的程序试图访问了无效的内存地址,而 std::bad_function_call 则表示你尝试调用一个空的 std::function 对象。

解决这个问题的步骤如下:

1. 调试 Segmentation Fault:
   · 确保你没有越界访问数组或者指针。
   · 确保没有在使用已释放的内存。
   · 确保没有使用空指针。
   · 使用工具如  valgrind  来检查内存错误。

2. 调试 std::bad_function_call:
   · 确保在调用 std::function 之前,该对象已经被正确地初始化。
   · 确保你没有在多个线程中同时修改或调用同一个 std::function 对象,可能需要使用互斥锁来保护。
   · 如果是从其他线程调用的 std::function,确保在调用之前该函数对象不会被销毁。

3. 处理竞态条件:
   · 使用互斥锁(mutex)来保护共享数据,确保每个线程在访问共享数据之前先锁定互斥锁,在访问完毕后解锁。
   · 考虑使用原子操作来进行简单的线程安全操作。

4. 使用调试工具:
   · 使用调试器(如 GDB)来逐步调试程序,查找问题所在。
   · 使用线程检测工具(如 Helgrind)来检测多线程代码中的问题。

5. 编写更健壮的代码:
   · 仔细设计多线程架构,避免竞态条件和死锁。
   · 使用智能指针等 RAII 技术来管理资源,避免内存泄漏。

在定位问题时,可以根据错误出现的条件和频率来排查。如果问题确实难以找到,可能需要更详细的代码和错误信息来进行深入分析。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-8-3 16:30:36 | 显示全部楼层
问题分析

根据提供的代码文件和问题描述,出现 Segmentation Faultstd::bad_function_call 错误的位置分别在 main.cpp 的第 17 行和 threads.cpp 的第 45 行。这些错误似乎是随机出现的。

由于没有提供完整的代码,我无法直接定位问题的具体原因。但是可以给出一些可能导致这些错误的常见原因和解决方法。

解决方案

1. Segmentation Fault 错误:
   - 检查第 17 行代码附近的指针操作,确保指针有效,并且没有被释放、空指针解引用等问题。
   - 检查是否存在数组越界的情况,确保数组访问不超过合法范围。
   - 使用合适的内存管理技术,如智能指针(std::shared_ptrstd::unique_ptr)来避免内存泄漏和悬挂指针等问题。
   - 如果有多线程代码,请确保在访问共享资源时正确地进行同步,以避免竞态条件等问题。

2. std::bad_function_call 错误:
   - 检查第 45 行代码附近的函数对象使用,确保在调用函数对象之前,已经将有效的函数对象绑定到它上面。
   - 在使用函数对象之前,可以使用条件语句或者std::function::target来检查函数对象是否为空,避免调用无效的函数对象。
   - 确保函数签名匹配,避免调用时参数类型不匹配或者返回值类型不一致。

3. 除了以上的常见问题,还可能存在其他与特定代码相关的问题。这种情况下,需要仔细检查相关代码,进行逐行调试并使用调试器来跟踪程序执行过程,以找出错误发生的具体原因。

请注意,由于我无法直接查看并修改你上传的代码,以上解决方案只是根据常见问题给出的一般性建议。如果你能提供更多关于问题的上下文信息或相关的代码片段,我可以尝试提供更具体的帮助。

如果回答对你有帮助,请给我一个最佳答案!
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-8-3 16:38:20 | 显示全部楼层
完整代码如下:
  1. // main.cpp
  2. #include <SFML/Graphics.hpp>
  3. #include "threads.h"

  4. DistributeThread threads;

  5. class Main
  6. {
  7.         public:
  8.                 double view_direction[2] = {0, 0};
  9.                 double player_position[3] = {0, 0, 0};
  10.                 sf::RenderWindow *window = nullptr;
  11.                 sf::RenderWindow *window_log = nullptr;
  12.                 sf::Event event;

  13.                 void control()
  14.                 {
  15.                         while (this->window->pollEvent(event))
  16.                         {
  17.                                 switch (event.type)
  18.                                 {
  19.                                         case sf::Event::KeyPressed:
  20.                                                 if (event.key.control)
  21.                                                 {
  22.                                                         switch (event.key.code)
  23.                                                         {
  24.                                                                 case sf::Keyboard::L:
  25.                                                                         if (this->window_log == nullptr)
  26.                                                                         {
  27.                                                                                 this->window_log->setVisible(true);
  28.                                                                         }
  29.                                                                         break;
  30.                                                         };
  31.                                                 };
  32.                                                 break;
  33.                                         case sf::Event::Closed:
  34.                                                 this->window->close();
  35.                                                 threads.stop();
  36.                                                 break;
  37.                                 };
  38.                         };
  39.                 };

  40.                 void init()
  41.                 {
  42.                         this->window = new sf::RenderWindow(sf::VideoMode(1000, 1000), "Minecraft for C");
  43.                         this->window_log = new sf::RenderWindow(sf::VideoMode(1000, 1000), "Minecraft for C");
  44.                         this->window_log->setVisible(false);
  45.                 };
  46. };

  47. int main()
  48. {
  49.         Main system;
  50.         threads.work("Control", std::bind(Main::init, &system));
  51.         threads.repeat_work("Control", 50, std::bind(Main::control, &system));
  52.         if (threads.start())
  53.         {
  54.                 threads.join();
  55.         };
  56.         return 0;
  57. };
复制代码
  1. // math.cpp
  2. #include <cmath>
  3. #include "math.h"
  4. #include "constants.hpp"

  5. double radian(const double theta){
  6.         return theta * (constants::pi / 180);
  7. };

  8. Matrix::Matrix(const Matrix &item) : Matrix(item.dimensions, item.values)
  9. {};

  10. Matrix::Matrix(Matrix &&item)
  11. {
  12.         this->dimensions[0] = item.dimensions[0];
  13.         this->dimensions[1] = item.dimensions[1];
  14.         this->values = item.values;       
  15.         item.values = nullptr;
  16. };

  17. Matrix::Matrix(const unsigned short dimensions[2])
  18. {
  19.         this->dimensions[0] = dimensions[0];
  20.         this->dimensions[1] = dimensions[1];
  21.         this->values = new double[dimensions[0] * dimensions[1]]();
  22. };

  23. Matrix::Matrix(const unsigned short dimensions[2], const double *values) : Matrix(dimensions)
  24. {
  25.         for (unsigned int ptr_offset = 0; ptr_offset < dimensions[0] * dimensions[1]; ptr_offset++)
  26.         {
  27.                 *(this->values + ptr_offset) = *(values + ptr_offset);
  28.         };
  29. };

  30. Matrix::~Matrix()
  31. {
  32.         if (this->values != nullptr)
  33.         {
  34.                 delete[] this->values;
  35.         };
  36. };

  37. Matrix Matrix::operator+(const Matrix &other) const
  38. {
  39.         if (this->dimensions[0] != other.dimensions[0] || this->dimensions[1] != other.dimensions[1])
  40.         {
  41.                 throw errors::MatrixDimensionError();
  42.         };
  43.         Matrix result(*this);
  44.         for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
  45.         {
  46.                 *(result.values + ptr_offset) += *(other.values + ptr_offset);
  47.         };
  48.         return result;
  49. };

  50. Matrix Matrix::operator+(const double other) const
  51. {
  52.         Matrix result(*this);
  53.         for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
  54.         {
  55.                 *(result.values + ptr_offset) += other;
  56.         };
  57.         return result;
  58. };

  59. Matrix Matrix::operator-() const
  60. {
  61.         Matrix result(*this);
  62.         for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
  63.         {
  64.                 *(result.values + ptr_offset) += -*(result.values + ptr_offset);
  65.         };
  66.         return result;
  67. };

  68. Matrix Matrix::operator-(const Matrix &other) const
  69. {
  70.         Matrix reversed = -other;
  71.         return *this + reversed;
  72. };

  73. Matrix Matrix::operator-(const double other) const
  74. {
  75.         return *this + -other;
  76. };

  77. Matrix Matrix::operator*(const Matrix &other) const
  78. {
  79.         if (this->dimensions[1] != other.dimensions[0])
  80.         {
  81.                 throw errors::MatrixDimensionError();
  82.         };
  83.         unsigned short result_dimensions[2] = {this->dimensions[0], other.dimensions[1]};
  84.         Matrix result(result_dimensions);
  85.         int result_ptr_offset, this_ptr_offset, other_ptr_offset;
  86.         for (short result_row = 0; result_row < result_dimensions[0]; result_row++)
  87.         {
  88.                 for (short result_column = 0; result_column < result_dimensions[1]; result_column++)
  89.                 {
  90.                         result_ptr_offset = result_row * result_dimensions[1] + result_column;
  91.                         for (short index = 0; index < this->dimensions[1]; index++)
  92.                         {
  93.                                 this_ptr_offset = result_row * this->dimensions[1] + index;
  94.                                 other_ptr_offset = index * other.dimensions[1] + result_column;
  95.                                 *(result.values + result_ptr_offset) += *(this->values + this_ptr_offset) * *(other.values + other_ptr_offset);
  96.                         };
  97.                 };
  98.         };
  99.         return result;
  100. };

  101. Vector Matrix::operator*(const Vector &other) const
  102. {
  103.         unsigned short vector_matrix_dimensions[2] = {other.dimensions, 1};
  104.         Matrix vector_matrix(vector_matrix_dimensions, other.values);
  105.         Matrix result_matrix = *this * vector_matrix;
  106.         Vector result = Vector(result_matrix.dimensions[0], result_matrix.values);
  107.         return result;
  108. };

  109. Matrix Matrix::operator*(const double other) const
  110. {
  111.         Matrix result(*this);
  112.         for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
  113.         {
  114.                 *(result.values + ptr_offset) *= other;
  115.         };
  116.         return result;
  117. };

  118. Matrix Matrix::operator/(const double other) const
  119. {
  120.         return *this * (1.0 / other);
  121. };

  122. Matrix Matrix::transpose() const
  123. {
  124.         Matrix result(this->dimensions);
  125.         unsigned short row, column;
  126.         for (unsigned int ptr_offset = 0; ptr_offset < this->dimensions[0] * this->dimensions[1]; ptr_offset++)
  127.         {
  128.                 row = ptr_offset / this->dimensions[1];
  129.                 column = ptr_offset % this->dimensions[1];
  130.                 *(result.values + column + row * this->dimensions[1]) = *(this->values + ptr_offset);
  131.         };
  132.         return result;
  133. };

  134. Vector::Vector(const Vector &item) : Vector(item.dimensions, item.values)
  135. {};

  136. Vector::Vector(const unsigned short dimensions, const double values[])
  137. {
  138.         this->dimensions = dimensions;
  139.         this->values = new double[dimensions]();
  140.         for (unsigned short index = 0; index < dimensions; index++)
  141.         {
  142.                 this->values[index] = values[index];
  143.         };
  144. };

  145. Vector::Vector(Vector &&item)
  146. {
  147.         this->dimensions = item.dimensions;
  148.         this->values = item.values;
  149.         item.values = nullptr;
  150. };

  151. Vector::~Vector()
  152. {
  153.         if (this->values != nullptr)
  154.         {
  155.                 delete[] this->values;
  156.         };
  157. };

  158. Vector Vector::operator+(const Vector &other) const
  159. {
  160.         if (this->dimensions != other.dimensions)
  161.         {
  162.                 throw errors::VectorDimensionError();
  163.         };
  164.         Vector result(*this);
  165.         for (unsigned short index = 0; index < this->dimensions; index++)
  166.         {
  167.                 result.values[index] += other.values[index];
  168.         };
  169.         return result;
  170. };

  171. Vector Vector::operator+(const double other) const
  172. {
  173.         Vector result(*this);
  174.         for (unsigned short index = 0; index < this->dimensions; index++)
  175.         {
  176.                 result.values[index] += other;
  177.         };
  178.         return result;
  179. };

  180. Vector Vector::operator-() const
  181. {
  182.         Vector result = *this;
  183.         for (unsigned short index = 0; index < this->dimensions; index++)
  184.         {
  185.                 result.values[index] = -result.values[index];
  186.         };
  187.         return result;
  188. };

  189. Vector Vector::operator-(const Vector &other) const
  190. {
  191.         Vector reversed = -other;
  192.         return *this + reversed;
  193. };

  194. Vector Vector::operator-(const double other) const
  195. {
  196.         return *this + -other;
  197. };

  198. Vector Vector::operator*(const Vector &other) const
  199. {
  200.         if (this->dimensions != 3 || other.dimensions != 3)
  201.         {
  202.                 throw errors::VectorDimensionError();
  203.         };
  204.         Vector result(*this);
  205.         for (unsigned short index = 0; index < this->dimensions; index++)
  206.         {
  207.                 result.values[index] = this->values[(index + 1) % 3] * other.values[(index + 2) % 3] - this->values[(index + 2) % 3] * other.values[(index + 1) % 3];
  208.         };
  209.         return result;
  210. };

  211. Vector Vector::operator*(const double other) const
  212. {
  213.         Vector result(*this);
  214.         for (unsigned short index = 0; index < this->dimensions; index++)
  215.         {
  216.                 result.values[index] *= other;
  217.         };
  218.         return result;
  219. };

  220. Vector Vector::operator/(const double other) const
  221. {
  222.         return *this * (1.0 / other);
  223. };

  224. double Vector::dot(const Vector &other) const
  225. {
  226.         if (this->dimensions != other.dimensions)
  227.         {
  228.                 throw errors::VectorDimensionError();
  229.         };
  230.         double result = 0;
  231.         for (unsigned short index = 0; index < this->dimensions; index++)
  232.         {
  233.                 result += this->values[index] * other.values[index];
  234.         };
  235.         return result;
  236. };

  237. double Vector::length() const
  238. {
  239.         double result_squared = 0;
  240.         for (unsigned short index = 0; index < this->dimensions; index++)
  241.         {
  242.                 result_squared += this->values[index] * this->values[index];
  243.         };
  244.         return sqrt(result_squared);
  245. };

  246. Vector Vector::length(const int scale) const
  247. {
  248.         return *this / (this->length() * scale);
  249. };

  250. double Vector::angle(const Vector &other) const
  251. {
  252.         return acos(this->dot(other) / (this->length() * other.length()));
  253. };
复制代码
  1. // threads.cpp
  2. #include <unistd.h>
  3. #include <iostream>
  4. #include "threads.h"

  5. BasicThread::BasicThread(const char* name)
  6. {
  7.         this->name.assign(name);
  8.         this->state = choices::state_free;
  9.         this->thread = new std::thread(&BasicThread::run, this);
  10. };

  11. choices::state BasicThread::get_state()
  12. {
  13.         return this->state;
  14. };

  15. [[nodiscard]]
  16. std::unique_lock<std::mutex> * BasicThread::pause()
  17. {
  18.         this->state = choices::state_paused;
  19.         std::unique_lock<std::mutex> *lock = new std::unique_lock<std::mutex>(this->mutex);
  20.         return lock;
  21. };

  22. void BasicThread::resume(std::unique_lock<std::mutex> &lock)
  23. {
  24.         lock.unlock();
  25.         this->alarm.notify_all();
  26. };

  27. void BasicThread::run()
  28. {
  29.         this->lock = new std::unique_lock<std::mutex>(this->mutex);
  30.         this->lock->unlock();
  31.         std::function<void ()> function;
  32.         while (this->running)
  33.         {
  34.                 this->state = choices::state_running;
  35.                 if (this->queue.empty())
  36.                 {
  37.                         this->sleep();
  38.                 }
  39.                 else
  40.                 {
  41.                         function = queue.front();
  42.                         if (function)
  43.                         function();
  44.                         this->queue.pop();
  45.                 };
  46.         };
  47.         delete this->lock;
  48. };

  49. void BasicThread::sleep()
  50. {
  51.         this->state = choices::state_free;
  52.         this->alarm.wait(*this->lock);
  53. };

  54. void BasicThread::stop()
  55. {
  56.         this->running = false;
  57.         this->alarm.notify_all();
  58.         this->thread->join();
  59.         this->state = choices::state_stopped;
  60. };

  61. void BasicThread::work(std::function<void ()> function)
  62. {
  63.         this->queue.push(function);
  64.         this->alarm.notify_all();
  65. };

  66. BasicThread * DistributeThread::create(const char* name)
  67. {
  68.         std::string name_string = name;
  69.         if (this->threads.find(name_string) != this->threads.end())
  70.         {
  71.                 throw errors::ThreadExistError();
  72.         };
  73.         BasicThread *new_thread = new BasicThread(name);
  74.         this->threads[name_string] = new_thread;
  75.         this->locks[name_string] = std::unique_lock<std::mutex>(new_thread->mutex);
  76.         this->locks[name_string].unlock();
  77.         return new_thread;
  78. };

  79. bool DistributeThread::start()
  80. {
  81.         if (this->plans.empty())
  82.         {
  83.                 return false;
  84.         };
  85.         this->thread = new std::thread(DistributeThread::run, this);
  86.         return true;
  87. };

  88. BasicThread * DistributeThread::get(const char *thread_name)
  89. {
  90.         std::string thread_string = thread_name;
  91.         if (this->threads.find(thread_string) == this->threads.end())
  92.         {
  93.                 return this->create(thread_name);
  94.         }
  95.         else
  96.         {
  97.                 return this->threads[thread_string];
  98.         };
  99. };

  100. void DistributeThread::join()
  101. {
  102.         this->thread->join();
  103. };

  104. void DistributeThread::repeat_work(const char* thread_name, unsigned int delay, std::function<void ()> function)
  105. {
  106.         plan new_plan;
  107.         new_plan.delay = delay;
  108.         new_plan.function = function;
  109.         new_plan.thread = this->get(thread_name);
  110.         this->plans[last_id] = new_plan;
  111.         this->queue.push(queue_item(delay, last_id));
  112.         last_id++;
  113. };

  114. void DistributeThread::run()
  115. {
  116.         queue_item function;
  117.         plan function_plan;
  118.         while (this->running)
  119.         {
  120.                 function = this->queue.top();
  121.                 if (function.first > this->game_time)
  122.                 {
  123.                         sleep((function.first - this->game_time) / 1000);  // Change milliseconds into seconds
  124.                         this->game_time = function.first;
  125.                         continue;
  126.                 };
  127.                 this->queue.pop();
  128.                 function_plan = this->plans[function.second];
  129.                 function_plan.thread->work(function_plan.function);
  130.                 this->queue.push(queue_item(function.first + function_plan.delay, function.second));
  131.         };
  132. };

  133. void DistributeThread::stop()
  134. {
  135.         this->running = false;
  136.         for (auto iterator : this->threads)
  137.         {
  138.                 iterator.second->stop();
  139.         };
  140.         this->thread->join();
  141. };

  142. void DistributeThread::work(const char* thread_name, std::function<void ()> function)
  143. {
  144.         this->get(thread_name)->work(function);
  145. };
复制代码
  1. // math.h
  2. #pragma once

  3. double radian(const double);

  4. class Vector
  5. {
  6.         public:
  7.                 unsigned short dimensions = 0;
  8.                 double *values = nullptr;

  9.                 Vector(const Vector &);
  10.                 Vector(Vector &&);
  11.                 Vector(const unsigned short, const double []);
  12.                 ~Vector();
  13.                 Vector operator+(const Vector &) const;
  14.                 Vector operator+(const double) const;
  15.                 Vector operator-() const;
  16.                 Vector operator-(const Vector &) const;
  17.                 Vector operator-(const double) const;
  18.                 Vector operator*(const Vector &) const;
  19.                 Vector operator*(const double) const;
  20.                 Vector operator/(const double) const;
  21.                 double dot(const Vector &) const;
  22.                 double length() const;
  23.                 Vector length(const int) const;
  24.                 double angle(const Vector &) const;
  25. };

  26. class Matrix
  27. {
  28.         public:
  29.                 unsigned short dimensions[2] = {0, 0};
  30.                 double *values = nullptr; // "*" creates a ptr pointing at an array with two dimensions.

  31.                 Matrix(const Matrix &);
  32.                 Matrix(Matrix &&);
  33.                 Matrix(const unsigned short [2]);
  34.                 Matrix(const unsigned short [2], const double *); // "*" is actually a ptr pointing at the first element of an array with two dimensions.
  35.                 ~Matrix();
  36.                 Matrix operator+(const Matrix &) const;
  37.                 Matrix operator+(const double) const;
  38.                 Matrix operator-() const;
  39.                 Matrix operator-(const Matrix &) const;
  40.                 Matrix operator-(const double) const;
  41.                 Matrix operator*(const Matrix &) const;
  42.                 Vector operator*(const Vector &) const;
  43.                 Matrix operator*(const double) const;
  44.                 Matrix operator/(const double) const;
  45.                 Matrix transpose() const;
  46. };
复制代码
  1. // threads.h
  2. #include <condition_variable>
  3. #include <functional>
  4. #include <thread>
  5. #include <map>
  6. #include <mutex>
  7. #include <queue>
  8. #include <unordered_map>
  9. #include "constants.hpp"

  10. class BasicThread
  11. {
  12.         friend class DistributeThread;
  13.         public:
  14.                 std::string name = "Basic";
  15.                 BasicThread(const char*);
  16.                 choices::state get_state();
  17.                 std::unique_lock<std::mutex> * pause();
  18.                 void resume(std::unique_lock<std::mutex> &);
  19.                 void stop();
  20.         protected:
  21.                 std::condition_variable alarm;
  22.                 std::unique_lock<std::mutex> *lock;
  23.                 std::mutex mutex;
  24.                 std::queue<std::function<void ()>> queue;
  25.                 bool running = true;
  26.                 choices::state state = choices::state_free;
  27.                 std::thread *thread = nullptr;
  28.                 void run();
  29.                 void sleep();
  30.         public:
  31.                 void work(std::function<void ()> function);
  32. };

  33. class DistributeThread
  34. {
  35.         typedef std::pair<unsigned long long, unsigned int> queue_item;
  36.         struct plan
  37.         {
  38.                 unsigned int delay;
  39.                 std::function<void ()> function = nullptr;
  40.                 BasicThread* thread;
  41.         };
  42.         public:
  43.                 unsigned long long game_time = 0;
  44.                 std::string name = "Distributor";
  45.                 BasicThread * create(const char*);
  46.                 BasicThread * get(const char*);
  47.                 void join();
  48.                 void repeat_work(const char* thread_name, unsigned int delay, std::function<void ()> function);
  49.                 bool start();
  50.                 void stop();
  51.                 void work(const char* thread_name, std::function<void ()> function);
  52.         protected:
  53.                 unsigned int last_id = 0;
  54.                 std::unordered_map<std::string, std::unique_lock<std::mutex>> locks;
  55.                 std::map<unsigned int, plan> plans;
  56.                 std::priority_queue<queue_item, std::vector<queue_item>, std::greater<queue_item>> queue;
  57.                 bool running = true;
  58.                 std::unordered_map<std::string, BasicThread*> threads;
  59.                 std::thread *thread = nullptr;
  60.                 void run();
  61. };
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 21:01

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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