সক্রিয় ব্যতিক্রম ছাড়াই C ++ সমাপ্তি বলা হয়


94

থ্রেডিং সহ আমি একটি সি ++ ত্রুটি পাচ্ছি:

terminate called without an active exception
Aborted

কোডটি এখানে:

#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>

template<typename TYPE>
class blocking_stream
{
public:
    blocking_stream(size_t max_buffer_size_)
        :   max_buffer_size(max_buffer_size_)   
    {
    }

    //PUSH data into the buffer
    blocking_stream &operator<<(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx); 
        while(buffer.size()>=max_buffer_size)
            stop_if_full.wait(mtx_lock);

        buffer.push(std::move(other));

        mtx_lock.unlock();
        stop_if_empty.notify_one();
        return *this;
    }
    //POP data out of the buffer 
    blocking_stream &operator>>(TYPE &other)
    {
        std::unique_lock<std::mutex> mtx_lock(mtx);
        while(buffer.empty())
            stop_if_empty.wait(mtx_lock);

        other.swap(buffer.front()); 
        buffer.pop();

        mtx_lock.unlock();
        stop_if_full.notify_one();
        return *this;
    }

private:
    size_t max_buffer_size;
    std::queue<TYPE> buffer;
    std::mutex mtx;
    std::condition_variable stop_if_empty,
                            stop_if_full;
    bool eof;   
};

আমি এই উদাহরণটির চারপাশে আমার কোড মডেল করেছি: http://www.justsoftwaresolutions.co.uk/threading/implementing-a-thread-safe-queue- using-condition- variables.html

আমি কী ভুল করছি এবং আমি কীভাবে ত্রুটিটি ঠিক করব?


9
আপনি কি joinআপনার মূল প্রোগ্রামটিতে আপনার সমস্ত থ্রেড যুক্ত করছেন?
কেরেক এসবি

আমাদের বাকী কোডটি দেখান।
ম্যাট

4
@ কেরেক আহ হা এটি সমস্যার সমাধান করেছে, শ্রমিকদের সমাপ্ত হওয়ার আগে মূল থ্রেডটি কেন শেষ হচ্ছে না তা নিশ্চিত আমি কেন জানি না। এছাড়াও আমার লকিং অ্যালগরিদমগুলি কি ঠিক দেখাচ্ছে?
111111

সংকলনযোগ্য কোড যা সমস্যাটি পুনরুত্পাদন করে দয়া করে।
মার্টিন ইয়র্ক

4
মনে হচ্ছে রানটাইম এই ক্ষেত্রে আরও ভাল ডায়াগনস্টিক ইস্যু করতে পারে?
নিমো

উত্তর:


127

যখন কোনও থ্রেড অবজেক্ট সুযোগের বাইরে চলে যায় এবং এটি যোগদানের স্থানে থাকে, প্রোগ্রামটি সমাপ্ত হয়। স্ট্যান্ডার্ড কমিটির কাছে একটি যোগদানযোগ্য থ্রেডের ধ্বংসকারীদের জন্য অন্য দুটি বিকল্প ছিল। এটি নিঃশব্দে যোগ দিতে পারে - তবে থ্রেড আটকে থাকলে যোগ দেওয়া কখনই ফিরে আসতে পারে না। অথবা এটি থ্রেডকে বিচ্ছিন্ন করতে পারে (একটি পৃথক থ্রেড সংযুক্ত হতে পারে না)। তবে, বিচ্ছিন্ন থ্রেডগুলি খুব জটিল, যেহেতু তারা প্রোগ্রামের শেষ অবধি বেঁচে থাকতে পারে এবং সংস্থানগুলি রিলিজ করতে পারে। সুতরাং আপনি যদি আপনার প্রোগ্রামটি শেষ করতে না চান তবে নিশ্চিত করুন যে আপনি প্রতিটি থ্রেডে যোগ দিয়েছেন (বা বিচ্ছিন্ন)।


4
"যখন কোনও থ্রেড অবজেক্ট সুযোগের বাইরে চলে যায় এবং এটি যুক্ত হতে পারে তখন প্রোগ্রামটি বন্ধ হয়ে যায়" আপনি কি এর কোনও মৃত সহজ, পুনরুত্পাদনযোগ্য উদাহরণ সরবরাহ করতে পারেন? ওপিতে উদাহরণটি কিছুটা জটিল।
আলেক জ্যাকবসন

4
এবং এই বিবৃতিটি এই উত্তরের সাথে সাংঘর্ষিক বলে মনে হচ্ছে: stackoverflow.com/a/3970921/148668
অ্যালেক জ্যাকবসন

4
@ মঙ্গলেডর্ফ: লক্ষ্য করুন যে তারা অবোট বুস্ট :: থ্রেডে কথা বলছেন এবং আমি স্টাড :: থ্রেডের কথা বলছি এই দুজনের পৃথক পৃথক ধ্বংস আচরণ রয়েছে। কমিটির পক্ষ থেকে এটি ছিল একটি সচেতন সিদ্ধান্ত।
বার্টোস মাইলিউস্কি

আপনি যদি এই সমস্যাটি নিয়ে চলে যান তবে std::async? সেখানে তৈরি হওয়া যে কোনও থ্রেডকে আপনি কীভাবে যুক্ত করবেন / বিচ্ছিন্ন করবেন? ফলস্বরূপ ভবিষ্যতের জন্য অপেক্ষা করা যথেষ্ট হবে বলে মনে হয় না, কারণ এটি বলে যে থ্রেডটি সম্ভবত "একটি থ্রেড পুল হতে পারে" এবং ভবিষ্যতের অপেক্ষার () সত্যিই কোনও পুলের মধ্যে থ্রেডকে সমাপ্ত করার ইঙ্গিত দেয় না (এবং এটি হবে না সনে থ্রেড পুলের জন্য কোনওভাবেই বোঝা যাবে না)।
জেসন সি

4
কেবলমাত্র একটি আপডেট যা সি ++ ২০ এ, ডেস্ট্রাক্টরকে std::jthreadকল করবে .join()(এটি সুযোগের বাইরে চলে যায়)। যা আমি ব্যক্তিগতভাবে আরও ভাল পছন্দ করি যেহেতু এটি আরআইআইকে আরও ভালভাবে অনুসরণ করে।
pooya13

46

কীভাবে সেই ত্রুটিটি পুনরুত্পাদন করবেন:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  return 0;
}

সংকলন এবং চালান:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
terminate called without an active exception
Aborted (core dumped)

আপনি এই ত্রুটিটি পেয়েছেন কারণ আপনি নিজের থ্রেডে যোগ দেন বা আলাদা করেননি।

এটির সমাধানের একটি উপায়, থ্রেডে এভাবে যুক্ত করুন:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() { 
  std::thread t1(task1, "hello"); 
  t1.join();
  return 0;
}

তারপরে সংকলন করুন এবং চালান:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

এটি ঠিক করার অন্যান্য উপায়, এটিকে আলাদা করুন:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <thread>
using namespace std;
void task1(std::string msg){
  cout << "task1 says: " << msg;
}
int main() 
{ 
     {

        std::thread t1(task1, "hello"); 
        t1.detach();

     } //thread handle is destroyed here, as goes out of scope!

     usleep(1000000); //wait so that hello can be printed.
}

সংকলন এবং চালান:

el@defiant ~/foo4/39_threading $ g++ -o s s.cpp -pthread -std=c++11
el@defiant ~/foo4/39_threading $ ./s
task1 says: hello

সি ++ থ্রেডগুলি বিচ্ছিন্নকরণ এবং সি ++ থ্রেডগুলিতে যোগদানের বিষয়ে পড়ুন।


4
এই প্রসঙ্গে, কেবলমাত্র থ্রেড বিচ্ছিন্ন হয়ে গেলে এবং হ্যান্ডেলটি (ক্ষেত্রের বাইরে গিয়ে) নষ্ট হয়ে গেলে কেবলমাত্র ঘুমের ব্যবহারটি বোঝায়। সুতরাং আমি আপনার কোডটি সম্পাদন করে এটি প্রতিফলিত করতে পারি।
নওয়াজ

17

এরিক লেসচিনস্কি এবং বার্টোস মাইলিউস্কি ইতিমধ্যে উত্তর দিয়েছেন। এখানে, আমি এটি আরও প্রাথমিকভাবে বন্ধুত্বপূর্ণ উপায়ে উপস্থাপন করার চেষ্টা করব।

একবার কোনও সূত্র কোনও স্কোপের মধ্যে শুরু হয়ে গেলে (যা নিজেই থ্রেডের উপর দিয়ে চলছে), থ্রেডটি সুযোগের বাইরে চলে যাওয়ার আগে একটিকে অবশ্যই স্পষ্টভাবে নিশ্চিত করতে হবে:

  • রানটাইম সুযোগ থেকে প্রস্থান করে, কেবল তখনই থ্রেডটি সম্পাদন শেষ করে। এই থ্রেডের সাথে যোগ দিয়ে এটি অর্জন করা হয়। ভাষাটি নোট করুন, এটি বাহ্যিক সুযোগ যা এই থ্রেডের সাথে মিলিত হয়।
  • রানটাইমটি থ্রেডটি নিজে থেকে চালানোর জন্য ছেড়ে দেয়। সুতরাং, এই থ্রেডটি কার্যকর করা শেষ হয়েছে কিনা, প্রোগ্রামটি সুযোগ থেকে প্রস্থান করবে। এই থ্রেডটি কার্যকর করে এবং নিজে থেকে প্রস্থান করে। এটি থ্রেড বিচ্ছিন্ন করে অর্জিত হয়। এটি সমস্যার কারণ হতে পারে, উদাহরণস্বরূপ, যদি থ্রেডটি বাহ্যিক ক্ষেত্রের ভেরিয়েবলগুলিকে বোঝায়।

দ্রষ্টব্য, থ্রেডের সাথে যুক্ত হওয়ার বা বিচ্ছিন্ন হওয়ার সময়টির মধ্যে এটি কার্যকরভাবে শেষ হতে পারে। তবুও দুটি অপারেশনের কোনওটি অবশ্যই স্পষ্টভাবে সম্পাদন করতে হবে।


1

যতক্ষণ না আপনার প্রোগ্রামটি মারা যায়, ততক্ষণ থ্রেডের বিচ্ছিন্নতা বা যোগদান ছাড়া এই ত্রুটি ঘটবে। থ্রেডটিকে বিচ্ছিন্ন করা এবং যোগ না করে থ্রেড তৈরির পরে আপনার অন্তহীন লুপ দেওয়া উচিত।

int main(){

std::thread t(thread,1);

while(1){}

//t.detach();
return 0;}

এটি আকর্ষণীয়ও যে, ঘুমানো বা লুপিংয়ের পরে, থ্রেডটি বিচ্ছিন্ন বা যোগদান করতে পারে। এছাড়াও এই ভাবে আপনি এই ত্রুটি পাবেন না।

নীচে উদাহরণে আরও দেখানো হয় যে, তৃতীয় থ্রেড মূল মৃত্যুর আগে তার কাজটি করতে পারে না। আপনি এই কোডটি কোথাও আলাদা করে না রেখে এই ত্রুটিটিও ঘটতে পারে না। তৃতীয় থ্রেডটি 8 সেকেন্ডের জন্য ঘুমায় তবে মূলটি 5 সেকেন্ডের মধ্যেই মারা যাবে।

void thread(int n) {std::this_thread::sleep_for (std::chrono::seconds(n));}

int main() {
std::cout << "Start main\n";
std::thread t(thread,1);
std::thread t2(thread,3);
std::thread t3(thread,8);
sleep(5);

t.detach();
t2.detach();
t3.detach();
return 0;}

1

বছর, থ্রেড অবশ্যই যোগদান করা উচিত ()। যখন প্রধান প্রস্থান


4
এই উত্তরটি সম্ভবত অন্য উত্তরের সাথে যুক্ত একটি মন্তব্যে আরও উপযুক্ত। এবং আমাকে বলতে হবে, স্ট্যাক ওভারফ্লোতে স্বাগতম!
কনটাঙ্গো

0

প্রথমে আপনি একটি থ্রেড সংজ্ঞায়িত করুন। এবং যদি আপনি থ্রেড ডেস্ট্রাক্টরকে কল করার আগে কখনও যোগদান () বা বিচ্ছিন্ন () কল না করেন তবে প্রোগ্রামটি বাতিল হয়ে যাবে।

নীচে, একটি থ্রেড ডেস্ট্রাক্টরকে কল না করে প্রথমে যোগদানের যোগ দিন (এটি শেষ হওয়ার জন্য অপেক্ষা করতে) বা বিচ্ছিন্নভাবে তাত্ক্ষণিক স্টাড :: কল বন্ধ করে প্রোগ্রামটি শেষ করার নিশ্চয়তা দেওয়া হয়।

তার ডেস্ট্রাক্টরে স্পষ্টতই কোনও সংযুক্ত () থ্রেডকে বিচ্ছিন্ন করা বা যোগদান করা এর ফলে যখন কোনও ব্যতিক্রম উত্থাপিত হয় তখনই সংশোধন (বিচ্ছিন্নতার জন্য) বা কর্মক্ষমতা (যোগদানের জন্য) বাগগুলি সম্মুখীন হতে পারে। সুতরাং প্রোগ্রামারকে অবশ্যই নিশ্চিত করতে হবে যে থ্রেডটি এখনও যুক্ত হতে পারে এমন সময়ে ডেস্ট্রাক্টর কখনই কার্যকর হয় না।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.