समस्याएं होती हैं, तो समस्याएं होती हैं, अगर समस्याएं होती हैं: मैथवर्क समर्थन के साथ कुछ चर्चाओं के बाद, यह एक संघर्ष साबित हुआ सिस्टम बूस्ट और मैटलैब के भेजे गए बूस्ट लाइब्रेरीज़ के बीच: जब मैंने सिस्टम बूस्ट हेडर के साथ संकलित किया और मैटलैब बूस्ट लाइब्रेरीज़ (पुराने) मैटलब बूस्ट लाइब्रेरी से जुड़े, तो यह सीगफॉल्ट हो गया। जब मैंने सिस्टम बूस्ट के साथ संकलित और गतिशील रूप से जुड़ा हुआ था, लेकिन फिर यह गतिशील रूप से मैटलैब बूस्ट पुस्तकालयों को लोड करता था, यह हमेशा के लिए लटका हुआ था।मैटलैब से बूस्ट :: थ्रेड का उपयोग करते समय लटकाएं और/या segfault, जब सीधे
सिस्टम बूस्ट कार्यों के लिए स्टेटिक लिंकिंग, जैसा कि मैटलैब जहाजों के साथ चिपकने और संकलित करने के बढ़ावा के लिए सही शीर्षलेख डाउनलोड करता है। बेशक, मैकबैब के मैक का निर्माण उनके फ़ाइल नामों में संस्करण संख्या नहीं है, हालांकि लिनक्स और माना जाता है कि विंडोज़ करता है। संदर्भ के लिए R2011b बूस्ट 1.44 का उपयोग करता है।
मैं कुछ बहु कोड है कि ठीक काम करता है जब यह सीधे संकलित है है, लेकिन segfaults और/या गतिरोध जब यह एक मैटलैब mex
इंटरफ़ेस से कहा जाता है। मुझे नहीं पता कि अलग-अलग वातावरण मेरे कोड में एक दोष दिखा रहा है, या क्या, लेकिन मैं इसे समझ नहीं सकता ....
मैं इसे तीन मशीन कॉन्फ़िगरेशन पर चला रहा हूं (हालांकि कई हैं CentOS बक्से के):
- OSX 10.7, जी ++ 4.2, को बढ़ावा देने के 1.48, मैटलैब R2011a (बजना ++ 2.1 भी स्टैंडअलोन के लिए काम करता है,
- प्राचीन CentOS बजना उपयोग करने के लिए) MEX प्राप्त करने की कोशिश नहीं की है, जी ++ 4.1 .2, 1.33.1 को बढ़ावा दें (डीबग करें और डीबग न करें), मैटलैब आर 2010 बी
- प्राचीन सेंटोस, जी ++ 4.1.2, 1.40 बढ़ाएं (कोई डीबग संस्करण स्थापित नहीं है), मैटलैब आर 2010 बी
यहां इस व्यवहार के साथ एक पारे हुए संस्करण है।
#include <queue>
#include <vector>
#include <boost/thread.hpp>
#include <boost/utility.hpp>
#ifndef NO_MEX
#include "mex.h"
#endif
class Worker : boost::noncopyable {
boost::mutex &jobs_mutex;
std::queue<size_t> &jobs;
boost::mutex &results_mutex;
std::vector<double> &results;
public:
Worker(boost::mutex &jobs_mutex, std::queue<size_t> &jobs,
boost::mutex &results_mutex, std::vector<double> &results)
:
jobs_mutex(jobs_mutex), jobs(jobs),
results_mutex(results_mutex), results(results)
{}
void operator()() {
size_t i;
float r;
while (true) {
// get a job
{
boost::mutex::scoped_lock lk(jobs_mutex);
if (jobs.size() == 0)
return;
i = jobs.front();
jobs.pop();
}
// do some "work"
r = rand()/315.612;
// write the results
{
boost::mutex::scoped_lock lk(results_mutex);
results[i] = r;
}
}
}
};
std::vector<double> doWork(size_t n) {
std::vector<double> results;
results.resize(n);
boost::mutex jobs_mutex, results_mutex;
std::queue<size_t> jobs;
for (size_t i = 0; i < n; i++)
jobs.push(i);
Worker w1(jobs_mutex, jobs, results_mutex, results);
boost::thread t1(boost::ref(w1));
Worker w2(jobs_mutex, jobs, results_mutex, results);
boost::thread t2(boost::ref(w2));
t1.join();
t2.join();
return results;
}
#ifdef NO_MEX
int main() {
#else
void mexFunction(int nlhs, mxArray **plhs, int nrhs, const mxArray **prhs) {
#endif
std::vector<double> results = doWork(10);
for (size_t i = 0; i < results.size(); i++)
printf("%g ", results[i]);
printf("\n");
}
ध्यान दें कि बढ़ावा 1.48 पर, मैं एक ही व्यवहार करता है, तो मैं एक मानक समारोह में functor बदल सकते हैं और सिर्फ boost::thread
करने के लिए अतिरिक्त तर्कों के रूप mutexes/आंकड़ों के boost::ref
रों पारित मिलता है। बूस्ट 1.33.1 हालांकि इसका समर्थन नहीं करता है।
जब मैं इसे सीधे संकलन, यह हमेशा ठीक चलाता है - मैं कभी नहीं देखा है यह किसी भी स्थिति में असफल:
$ g++ -o testing testing.cpp -lboost_thread-mt -DNO_MEX
$ ./testing
53.2521 895008 5.14128e+06 3.12074e+06 3.62505e+06 1.48984e+06 320100 4.61912e+06 4.62206e+06 6.35983e+06
मैटलैब से चल रहा है, मैं एक बहुत देखा है कोड में अलग-अलग बदलाव करने के बाद विभिन्न व्यवहारों के बारे में और फिर भी, हालांकि कोई बदलाव नहीं जो वास्तव में मुझे कोई समझ में आता है। लेकिन यहाँ क्या मैं ऊपर सटीक कोड के साथ देखा गया है:
- पर OSX/बढ़ावा 1.48:
- यह एक रिलीज-संस्करण को बढ़ावा देने से लिंक किया गया है, मैं एक segfault एक लगभग 0 तक पहुंच की कोशिश
boost::thread::start_thread
के अंदर पता,t1
के कन्स्ट्रक्टर से बुलाया जा रहा है। - यदि यह डीबग-वेरिएंट बूस्ट से जुड़ा हुआ है, तो यह पहले
boost::thread::join
में हमेशा के लिए लटकता है। मैं पूरी तरह से निश्चित नहीं हूं, लेकिन मुझे लगता है कि कार्यकर्ता धागे वास्तव में इस बिंदु पर पूरा हो गए हैं (info threads
में कुछ भी न देखें जो स्पष्ट रूप से उन्हें है)।
- यह एक रिलीज-संस्करण को बढ़ावा देने से लिंक किया गया है, मैं एक segfault एक लगभग 0 तक पहुंच की कोशिश
- CentOS/बढ़ावा 1.33.1 और 1.40 पर:
-
रिहाई को बढ़ावा देने के साथ
- , मैं
pthread_mutex_lock
में एक segfault मिलता है,t1
परboost::thread::join
से बुलाया जा रहा है। - डिबगिंग बूस्ट के साथ, यहमें
pthread_mutex_lock
के अंदर एक ही स्थान पर हमेशा के लिए लटकता है। जैसा कि नीचे दिखाया गया है, कार्यकर्ता धागे इस बिंदु पर पूरा हो गए हैं।
- , मैं
मैं कुछ भी segfaults साथ बहुत कुछ करने के लिए कैसे, क्योंकि वे कभी नहीं हो जब मैं डिबगिंग प्रतीकों है कि वास्तव में मुझे बता सकते हैं क्या नल पॉइंटर है पता नहीं है।
मटरगश्ती हमेशा के मामले में, मैं अगर मैं GDB में के माध्यम से आगे बढ़ रहा हूँ हमेशा कुछ इस तरह प्राप्त करने के लिए लग रहे हैं: दोनों धागे की तरह लगती है t1.join()
को कॉल करने से पहले पूरी हो
99 Worker w1(jobs_mutex, jobs, results_mutex, results);
(gdb)
100 boost::thread t1(boost::ref(w1));
(gdb)
[New Thread 0x47814940 (LWP 19390)]
102 Worker w2(jobs_mutex, jobs, results_mutex, results);
(gdb)
103 boost::thread t2(boost::ref(w2));
(gdb)
[Thread 0x47814940 (LWP 19390) exited]
[New Thread 0x48215940 (LWP 19391)]
[Thread 0x48215940 (LWP 19391) exited]
105 t1.join();
है। तो मैंने ताले के बीच "काम करने" अनुभाग में sleep(1)
कॉल जोड़ने का प्रयास किया; जब मैं के माध्यम से आगे बढ़ रहा हूँ, t1.join()
करने के लिए कॉल के बाद धागे से बाहर निकलें और यह अभी भी हमेशा के लिए लटका हुआ है:
106 t1.join();
(gdb)
[Thread 0x47814940 (LWP 20255) exited]
[Thread 0x48215940 (LWP 20256) exited]
# still hanging
मैं up
doWork
कार्य करने के लिए बाहर, results
एक ही परिणाम के साथ से भर जाता है तो उस पर स्टैंडअलोन संस्करण प्रिंट यह मशीन, तो ऐसा लगता है कि यह सब कुछ हो रहा है।
मुझे नहीं पता कि सीजीफाल्ट या पागल लटकने वाली नस्ल के कारण क्या हो रहा है, या ऐसा क्यों है कि यह हमेशा मैटलैब के बाहर काम करता है और अंदर कभी नहीं, या यह डिबगिंग प्रतीकों के साथ/बिना अलग क्यों है, और मुझे नहीं पता इसे समझने में कैसे आगे बढ़ें। कोई विचार?
@ alanxz के सुझाव पर, मैं valgrind के Memcheck, helgrind, और DRD उपकरण के तहत कोड का स्टैंडअलोन संस्करण हुई:
- valgrind 3.5 का उपयोग कर CentOS पर, उपकरण में से कोई भी किसी भी देना गैर दबाए गए त्रुटियां।
- ओएसएक्स पर valgrind का उपयोग 3.7:
- मेमचेक कोई भी गैर-दबाने वाली त्रुटियां नहीं देता है।
- ओएसएक्स पर किसी भी बाइनरी (उदा।
valgrind --tool=helgrind ls
सहित) पर चलने पर हेल्ग्रिंड क्रैश हो जाता है, जो असमर्थित निर्देश के बारे में शिकायत करता है। - डीआरडी सौ से अधिक त्रुटियों देता है।
DRD त्रुटियाँ सुंदर मेरे लिए गूढ़ हैं, और हालांकि मैं मैनुअल और इतने पर पढ़ा है, मैं उनमें से कोई मतलब नहीं कर सकते हैं। यहाँ पहले एक है, कोड, जहां मैं बाहर दूसरे कार्यकर्ता/धागा टिप्पणी की के एक संस्करण पर:
Thread 2:
Conflicting load by thread 2 at 0x0004b518 size 8
at 0x3B837: void boost::call_once<void (*)()>(boost::once_flag&, void (*)()) (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib)
by 0x2BCD4: boost::detail::set_current_thread_data(boost::detail::thread_data_base*) (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib)
by 0x2BA62: thread_proxy (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib)
by 0x2D88BE: _pthread_start (in /usr/lib/system/libsystem_c.dylib)
by 0x2DBB74: thread_start (in /usr/lib/system/libsystem_c.dylib)
Allocation context: Data section of r/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib
Other segment start (thread 1)
at 0x41B4DE: __bsdthread_create (in /usr/lib/system/libsystem_kernel.dylib)
by 0x2B959: boost::thread::start_thread() (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib)
by 0x100001B54: boost::thread::thread<boost::reference_wrapper<Worker> >(boost::reference_wrapper<Worker>, boost::disable_if<boost::is_convertible<boost::reference_wrapper<Worker>&, boost::detail::thread_move_t<boost::reference_wrapper<Worker> > >, boost::thread::dummy*>::type) (thread.hpp:204)
by 0x100001434: boost::thread::thread<boost::reference_wrapper<Worker> >(boost::reference_wrapper<Worker>, boost::disable_if<boost::is_convertible<boost::reference_wrapper<Worker>&, boost::detail::thread_move_t<boost::reference_wrapper<Worker> > >, boost::thread::dummy*>::type) (thread.hpp:201)
by 0x100000B50: doWork(unsigned long) (testing.cpp:66)
by 0x100000CE1: main (testing.cpp:82)
Other segment end (thread 1)
at 0x41BBCA: __psynch_cvwait (in /usr/lib/system/libsystem_kernel.dylib)
by 0x3C0C3: boost::condition_variable::wait(boost::unique_lock<boost::mutex>&) (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib)
by 0x2D28A: boost::thread::join() (in /usr/local/boost/boost_1_48_0/stage/lib/libboost_thread-mt-d.dylib)
by 0x100000B61: doWork(unsigned long) (testing.cpp:72)
by 0x100000CE1: main (testing.cpp:82)
लाइन 66 धागे के निर्माण है, और 72 join
कॉल है, बीच में टिप्पणी के अलावा कुछ भी नहीं है। जहां तक मैं कह सकता हूं, यह कह रहा है कि मास्टर थ्रेड के उस हिस्से और कार्यकर्ता थ्रेड के प्रारंभिकरण के बीच एक दौड़ है ...लेकिन मैं वास्तव में समझ में नहीं आता कि यह कैसे संभव है?
डीआरडी is here से बाकी उत्पादन; मुझे इससे कुछ भी नहीं मिल रहा है।
क्या आपने इसे वालग्रिंड के तहत चलाने की कोशिश की है, [हेल्ग्रिंड] (http://valgrind.org/docs/manual/hg-manual.html), या [DRD] (http://valgrind.org/docs/manual /drd-manual.html)? इससे क्या हो रहा है इसके बारे में कुछ संकेत बता सकते हैं। – alanxz
@alanxz सुझाव के लिए धन्यवाद, मुझे हेल्ग्रिंड/डीआरडी के बारे में पता नहीं था। मैंने सवाल के बारे में कुछ कहने के बारे में कुछ विवरण जोड़ा है। मुझे ओएसएक्स पर डीआरडी त्रुटियां मिलती हैं, लेकिन मैन्युअल पढ़ने के बावजूद उनका क्या मतलब है, इसका कोई मतलब नहीं है .... – Dougal
क्या कोई भी पर्यावरण जैसे लिनक्स पर @rpath सेट अप करने का प्रयास करता है? मेरे पास वर्तमान में एक ही समस्या है, मैं सोच रहा हूं कि मेक्सिको को अपनी निर्भरताओं के उचित अलगाव करना चाहिए। – Raffi