2009-04-19 7 views
6

मैं अपने विश्वविद्यालय के लिए एक समूह वरिष्ठ परियोजना पर काम कर रहा हूं और मैंने अपना कोड काम करने की कोशिश में एक बड़ी बाधा में भाग लिया है।जब आप अपने एम्बेडेड कंपाइलर में ऑपरेटर नया या एसटीएल समर्थन नहीं होता है तो आप सी ++ कैसे कर सकते हैं?

हमारे 8 बिट एटमेल माइक्रोकंट्रोलर के लिए हमारे पास कंपाइलर नया या समर्थन ऑपरेटरों का समर्थन नहीं करता है, और यह सी ++ एसटीएल का समर्थन नहीं करता है। मैं इसे सी में प्रोग्राम कर सकता हूं, लेकिन मुझे ए * एल्गोरिदम लागू करना है जिसे मैंने पहले कभी नहीं किया है। जबकि मैंने शुरुआत में सी की कोशिश की है, मुझे जल्द ही एहसास हुआ कि मैंने पहले कभी शुद्ध सी नहीं किया था। Structs और कार्यों के साथ वस्तुओं को मॉडल करने का प्रयास करना मुझे धीमा कर रहा है क्योंकि मुझे बहुत क्लीनर सी ++ वाक्यविन्यास में इतना उपयोग किया जाता है।

परवाह किए बिना, मेरी compilers कमियों के लिए सटीक शब्द यहां पाया जा सकता है: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus

उन्हें दूर करने के लिए और अभी भी सी ++ मैं निम्नलिखित संभावनाओं पर विचार किया है का उपयोग करें। 1) कुछ भी आवंटित न करें, केवल ढेर पर निश्चित सरणी उत्पन्न करने के लिए टेम्पलेट का उपयोग करें। 2) ऑब्जेक्ट्स के लिए कन्स्ट्रक्टर को कॉल करने के लिए कुछ हैक आवंटित करें और एक बार मैंने उनके लिए जगह आवंटित की है। प्लेसमेंट नया विकल्प नहीं है क्योंकि नया ऑपरेटर नहीं है। 3) बस सी का उपयोग करें और इसे चूसो, यह एक माइक्रोकंट्रोलर क्यों मुझे कल्पना मिल रही है? 4) एक बेहतर कंपाइलर खोजें जो शायद $$$ खर्च करेगा।

दूसरा विकल्प सबसे कठिन है लेकिन इस कोड को मैं कैसे लिख सकता हूं इसके संदर्भ में सबसे बड़ा भुगतान होगा। हालांकि, मुझे लगता है कि अगर मुझे यह गलत लगता है तो इसे डिबगिंग करना एक बड़ा दर्द हो सकता है। मैं ढेर पर वस्तुओं को बनाने, आवंटित स्थान में अपनी बिट्स की प्रतिलिपि बनाने और फिर ऑब्जेक्ट में बिट्स को शून्य करने के बारे में सोच रहा हूं, इसलिए यह इसके विनाशक को नहीं बुलाता है। ऐसा करने के लिए मैं बाइट गिनती प्राप्त करने के लिए सीधे एक हस्ताक्षरित चार सूचक और आकार के ऑपरेटर के साथ बिट्स तक पहुंच जाएगा।

यह भयानक लगता है और मुझे नहीं पता कि यह विश्वसनीय रूप से काम कर सकता है, लेकिन मैं इसे देख रहा हूं। मुझे पता है कि vtables एक समस्या हो सकती है लेकिन मुझे कोई vtables होने का इरादा नहीं है क्योंकि यह केवल 8 बिट माइक्रोकंट्रोलर है।

+3

यदि मुझे सही याद है कि 8 बिट एटमल्स में गतिशील स्मृति एला मॉलोक/नई के बारे में सोचने के लिए पर्याप्त RAM नहीं है। – lothar

+0

अगर मैं उन ऑपरेटरों को अधिभारित कर सकता हूं तो मैं नियंत्रित कर सकता हूं कि स्मृति कहां से आती है। यह ढेर या ढेर पर हो सकता है। –

+0

मुझे पता चला कि मेरे पास केवल 1 केबी खेलने के लिए था, जिसने अनिवार्य रूप से ए * को मेरे रोबोट के लिए व्यवहार्य पथ खोजक के रूप में अस्वीकार कर दिया था। अब मैं एक साधारण डीएफएस का उपयोग कर रहा हूं जब तक कि मैं एक और रैम के साथ एक प्राप्त नहीं कर सकता। –

उत्तर

10

बस रिकॉर्ड के लिए, किसी ऑब्जेक्ट में बिट्स को शून्य करने से यह प्रभावित नहीं होगा कि क्या विनाशक को बुलाया जाता है (जब तक कि कंपाइलर के पास विशेष व्यवहार नहीं होता है जो इस व्यवहार को सक्षम करता है)। इसका परीक्षण करने के लिए बस अपने विनाशक में कुछ लॉगिंग स्टेटमेंट लिखें।

किसी भी कार्यक्रम को आवंटित न करने के लिए आपके प्रोग्राम को संरचित करना शायद सिस्टम को डिज़ाइन किया गया था। मैंने पहले एम्बेडेड सिस्टम के साथ काम नहीं किया है, हालांकि मैंने कुछ अनुभवी एम्बेडेड दुकानों को पढ़ा है जो गतिशील स्मृति के उपयोग को हतोत्साहित करते हैं क्योंकि रनटाइम पर्यावरण की दुर्लभ मात्रा होती है।


हालांकि, यदि आपको जरूरी है, तो भी आप प्लेसमेंट का उपयोग कर सकते हैं। आप <new> हेडर की जरूरत नहीं है, तो यहां प्रासंगिक लाइनों से सीधे जीसीसी की मेरी संस्करण पर हैं:

// Default placement versions of operator new. 
inline void* operator new(std::size_t, void* __p) throw() { return __p; } 
inline void* operator new[](std::size_t, void* __p) throw() { return __p; } 

// Default placement versions of operator delete. 
inline void operator delete (void*, void*) throw() { } 
inline void operator delete[](void*, void*) throw() { } 

छड़ी है कि नियुक्ति नए का उपयोग करता है हर स्रोत फ़ाइल से शामिल एक हेडर फाइल में कहीं/हटा सकते हैं।

नमूना फ़ाइल है कि इस परीक्षण:

#include <cstdio> 
#include <new> 

int 
main(int argc, char** argv) 
{ 
    typedef char const* cstr; 
    char foobar[16]; 
    cstr* str = new (&foobar) cstr(argc > 1 ? argv[1] : "Hello, world!"); 
    std::puts(*str); 
    str->~cstr(); 
} 

जीसीसी की मेरी संस्करण पर, यह सब पर libstdc++ उपयोग नहीं करता है (यदि -fno-exceptions प्रयोग किया जाता है)।


अब, अगर आप (अपने मंच इस प्रदान करता है तो) कि गठबंधन करने के लिए malloc साथ चाहते हैं, तो आप ऐसा कर सकते हैं:

#include <cstdio> 
#include <cstdlib> 

inline void* operator new (std::size_t n) {return std::malloc(n);} 
inline void* operator new[](std::size_t n) {return std::malloc(n);} 
inline void operator delete (void* p) {std::free(p);} 
inline void operator delete[](void* p) {std::free(p);} 

int 
main(int argc, char** argv) 
{ 
    typedef char const* cstr; 
    cstr* str = new cstr(argc > 1 ? argv[1] : "Hello, world!"); 
    std::puts(*str); 
    delete str; 
} 

यह आपको मानक new/delete का उपयोग करने की अनुमति देता है कि आप libstdc++ के उपयोग की आवश्यकता के बिना परिचित हैं।

शुभकामनाएं!

+0

वाह, ऐसा लगता है कि यह काम करता है। मैं आपके द्वारा प्रदान किए गए हेडर का उपयोग नहीं कर सका लेकिन उन ऑपरेटर फ़ंक्शंस काम करने लगते हैं। मैंने उन ऑपरेटरों के बारे में जो कुछ पढ़ा है [] और हटाएं [] को सभी आवश्यक विनाशकों को कॉल करने के लिए सरणी आकार को जानने की आवश्यकता है, लेकिन मेरे परीक्षण में आवश्यक सभी विनाशकों को बुलाया गया था। –

0

क्यों इसे अपने डेस्कटॉप कंप्यूटर पर पहले लिखना नहीं है, संकलक की सीमाओं को ध्यान में रखते हुए, इसे डीबग करें, सुनिश्चित करें कि यह पूरी तरह से काम करता है और केवल तब एम्बेडेड वातावरण में स्थानांतरित हो जाता है?

+0

मुझे नहीं लगता कि यह एक बहुत अच्छा विचार है क्योंकि एम्बेडेड प्लेटफॉर्म पर कुछ सीमाएं और अंतर हैं (कुछ रैम, 32 बिट्स के बजाय 8 बिट्स) ताकि आप इसे इस तरह से काम नहीं कर पाएंगे। – mmmmmmmm

23

अपने टूल्स से लड़ें मत। यदि आपके एम्बेडेड सिस्टम के लिए आपके पास एकमात्र कंपाइलर है तो सी संकलक है, सी सीखें - यह मुश्किल नहीं है। एक साधारण सरल प्रोग्रामिंग समस्या को हल करने के लिए केवल दो भाषाओं के कुछ बेस्टर्डिज्ड संस्करण का उत्पादन करने की कोशिश कर रहे हैं केवल आँसू में समाप्त होगा।

इसे एक और तरीके से देखने के लिए, यदि आपका एम्बेडेड प्लेटफार्म सी संकलक का समर्थन भी नहीं करता है, लेकिन केवल एक असेंबलर है, तो क्या आपका पहला आवेग नीचे बैठना होगा और असेंबलर में सी ++ कंपाइलर लिखना होगा? मुझे उम्मीद नहीं है, मुझे उम्मीद है कि आप इसके बजाय बैठकर अपने असाइनमेंट को पूरा करने के लिए असेंबलर का उपयोग करना सीखेंगे - एक सी ++ कंपाइलर (या यहां तक ​​कि एक सी कंपाइलर) लिखना आपके समय का पूरी तरह से अनुचित उपयोग होगा, और लगभग निश्चित रूप से विफलता का परिणाम होगा ।

+0

हालांकि मैं मानता हूं कि लड़ने वाले उपकरण मूर्ख हैं, उपकरण विकास में निवेश आम तौर पर खुद का भुगतान करता है। यदि, और जब मैंने एक छोटे से प्रीप्रोसेसर आधारित डीएसएल लिखने वाले असेंबलर का उपयोग किया है तो यह इसके लायक था। हालांकि मैं कभी भी एक सी ++ कंपाइलर लिखने के लिए कभी नहीं जाऊंगा :) –

+0

ओह, मैं सहमत हूं, और जब मैंने असेंबलर लिखा था (एक लंबे समय पहले) मैंने मैक्रो पुस्तकालयों का उपयोग किया था जो मैंने लिखा था। और मैंने वास्तव में जेड 80 असेंबलर (हालांकि किसी विशेष समस्या को हल करने के लिए) में एक सी कंपाइलर लिखा था, इससे पहले कि मैं अपनी इंद्रियों पर आया, इसे सी में फिर से लिखा और क्रॉस इसे संकलित किया। यह अभी भी काम नहीं करता है, लेकिन यह बहुत कम काम था :-) –

+0

और यह मत भूलना कि सबसे एम्बेडेड सी कंपाइलर केवल सी पुस्तकालय के बहुत सीमित उप सेट के साथ आते हैं। महत्वपूर्ण भागों में से एक मुझे लगता है कि उनमें कमी का प्रबंधन ढेर प्रबंधन (मॉलोक/फ्री) है। – mmmmmmmm

4

सिर्फ इसलिए कि इन उपकरणों में यह नहीं है कि इसका मतलब यह नहीं है कि आप सी ++ से लाभ नहीं उठा सकते हैं। यदि परियोजना काफी बड़ी है, तो अकेले ऑब्जेक्ट ओरिएंटेड डिज़ाइन तक पहुंच पर्याप्त प्रेरणा हो सकती है।

यदि यह 'नया' का समर्थन नहीं करता है तो शायद यह इसलिए है क्योंकि एक ढेर और ढेर के बीच स्वचालित अंतर बनाने के लिए यह समझ में नहीं आता है। यह आपकी स्मृति विन्यास के कारण हो सकता है। यह भी हो सकता है क्योंकि स्मृति संसाधन इतने सीमित हैं कि केवल बहुत सावधान आवंटन समझ में आता है। यदि आपको बिल्कुल अपना 'नया' ऑपरेटर लागू करना है, तो आप Doug Lea's malloc को अनुकूलित करने में लग सकते हैं। मेरा मानना ​​है कि उन्होंने एक समान परिस्थिति में अपना आवंटन शुरू किया (सी ++ के नए को फिर से लागू करना)।

मुझे एसटीएल पसंद है लेकिन इसके बिना उपयोगी सामान करना अभी भी संभव है। प्रोजेक्ट के दायरे के आधार पर आप केवल सरणी का उपयोग करके बेहतर हो सकते हैं।

2

मेरे पास एक समान संकलक था जिसने Embedded-C++ standard का एक विचित्र संस्करण लागू किया था। हमारे पास operator new था जो हमारे लिए कन्स्ट्रक्टर को कॉल करेगा और अधिकांश मामलों में विनाशकों को कहा जाता है। कंपाइलर/रनटाइम विक्रेता try और catchsetjmp और longjmp का उपयोग इंजीनियर के लिए सुविधा के साथ पर चला गया और लागू किया। समस्या यह थी कि उन्होंने कभी उल्लेख नहीं किया कि throw स्थानीय वस्तुओं के विनाशकों का आह्वान नहीं करेगा!

वैसे भी, हमारे समूह ने कोड कोड को विरासत में मिला है जब किसी ने इसे मानक सी ++ कहा था: आरएआईआई तकनीक और अन्य सभी भलाई का उपयोग करना। हमने इसे फिर से लिखना समाप्त कर दिया है जिसमें हम में से कई लोग ऑब्जेक्ट-ओरिएंटेड सी पर कॉल करते हैं। आप केवल बुलेट को काटने और सीधे सी में लिखने पर विचार करना चाहेंगे। रचनाकारों के बजाय, स्पष्ट रूप से प्रारंभिक विधि कहा जाता है। विनाशक एक स्पष्ट रूप से बुलाया जाने वाला तरीका बन जाते हैं। सी ++ में बहुत कुछ नहीं है कि आप सी में बहुत जल्दी नकल नहीं कर सकते हैं। हां, एमआई में दर्द है ... लेकिन एकल विरासत बहुत आसान है। कुछ विचारों के लिए this PDF पर एक नज़र डालें। यह लगभग उस दृष्टिकोण का वर्णन करता है जिसे हमने लिया था। मैं वास्तव में चाहता हूं कि मैंने कहीं हमारी विधि लिखी है ...

0

एम्बेडेड काम करते समय, मैं एक बार स्मृति बाधाओं के लिए सी रनटाइम को भी लिंक नहीं कर सका, लेकिन हार्डवेयर में डीएमए (गतिशील स्मृति आवंटक) निर्देश था इसलिए मैंने उस हार्डवेयर के साथ अपना स्वयं का मॉलोक लिखा था, आपके हार्डवेयर की संभावना है इसी तरह की सुविधा, ताकि आप एक मॉलोक लिख सकें और फिर मॉलोक पर आधारित एक नया।

अंत में मैंने 99% स्टैक आवंटन का उपयोग किया, और कुछ सीमाएं स्थिर वस्तुओं को सेट करती हैं जिन्हें मैं रीसायकल करता हूं, जगह पर घूमने के द्वारा। यह मुझे एक अच्छा समाधान हो सकता है।

6

मुझे लगता है कि आप एक दृष्टिकोण से समस्या का सामना कर रहे हैं जो इष्टतम से कम है।

आप हार्डवेअर पर ध्यान केंद्रित करने के बजाय संकलक (या इसकी कमी) पर ध्यान केंद्रित कर रहे हैं।

आपके मुख्य प्रश्नों का सबसे संभावित उत्तर यह है कि "हार्डवेयर उन सभी C++ सामग्री का समर्थन नहीं करता है"। एम्बेडेड हार्डवेयर (माइक्रोकंट्रोलर) हार्डवेयर डिज़ाइन के अनुकूलन के लिए नोट किए जाते हैं - मेमोरी मैप्स, इंटरप्ट हैंडलर, आई/ओ इत्यादि

मेरी राय में, आपको पहले माइक्रोकंट्रोलर के लिए हार्डवेयर पुस्तक के साथ कुछ समय बिताना चाहिए डिवाइस के इन्स और आउट - यानी यह कैसे डिजाइन किया गया था और किस प्राथमिक उद्देश्य के लिए। कुछ को फास्ट मेमोरी मैनिपुलेशन के लिए डिजाइन किया गया था, कुछ तेजी से I/O हैंडलिंग के लिए, कुछ ए/डी प्रकार के काम के लिए, कुछ सिग्नल प्रोसेसिंग के लिए। माइक्रोकंट्रोलर का प्रकार उनके द्वारा लिखे गए असेंबलर निर्देशों को निर्देशित करता है, और यह निर्धारित करता है कि कोई उच्च स्तरीय कंपाइलर कुशलता से क्या कर सकता है।

यदि यह महत्वपूर्ण है, तो असेंबलर को देखने के लिए कुछ समय बिताएं - यह आपको बताएगा कि डिजाइनरों को क्या महत्वपूर्ण माना जाता है। यह आपको एक उच्च स्तरीय कंपाइलर से कितना प्राप्त कर सकता है इसके बारे में भी बताएगा।

आम तौर पर, माइक्रोकंट्रोलर सी ++ का समर्थन नहीं करते हैं क्योंकि डिज़ाइन वास्तव में वस्तुओं, या फैंसी मेमोरी हैंडलिंग (सी ++ परिप्रेक्ष्य से) की परवाह नहीं करता है। यह किया जा सकता है, लेकिन आप अक्सर माइक्रो पर्यावरण में काम करने के लिए कन्स्ट्रक्टर और विनाशक (और 'नया' और 'हटाएं') प्राप्त करने के लिए स्क्वायर होल में एक गोल पेग पाउंड करने की कोशिश कर रहे हैं।

यदि आपके पास इस इकाई के लिए सी कंपाइलर है, तो इसे एक आशीर्वाद मानें। उत्कृष्ट एम्बेडेड सॉफ़्टवेयर बनाने के लिए एक अच्छा सी कंपाइलर अक्सर "पर्याप्त से अधिक" होता है।

चीयर्स,

-Richard

1

तुम मेरे A* tutorial website पर कुछ उपयोगी कोड मिल सकता है। हालांकि code मैंने एसटीएल का समर्थन करने के लिए लिखा है एसटीएल समर्थन को पट्टी करना आसान होना चाहिए। इसके अलावा इसमें पूल आवंटन भी शामिल है (fsa.h) जिसे मैंने गेम कंसोल पर एसटीएल को गति देने के लिए लिखा था। यह सी ++ कोड है, लेकिन मैंने इसे मूल रूप से सी से पोर्ट किया है और मुझे नहीं लगता कि इसे दूसरी तरफ करना मुश्किल होगा। कोड का परीक्षण 10,000 से अधिक लोगों द्वारा किया जाता है, इसलिए यह शुरू करने के लिए एक अच्छा आधार है।

मैं जो एसटीएल संरचनाओं का उपयोग कर रहा हूं उसे बदलना कोई समस्या नहीं है क्योंकि यह वेक्टर तक ही सीमित है। मैं ढेर कार्यों (make_heap और push_heap) का उपयोग कर प्राथमिकता कतार के रूप में वेक्टरों में से एक का उपयोग करता हूं। आप इसे मेरे old C code के साथ प्रतिस्थापित कर सकते हैं जिसमें सी में लागू प्राथमिकता कतार है जो केवल आपके कोड में आनी चाहिए। (जो केवल एक आवंटन करता है, इसलिए आप इसे अपनी मेमोरी के आरक्षित क्षेत्र में पॉइंटर के साथ बदल सकते हैं।

जैसा कि आप हेडर से इस कोड खंड में देख सकते हैं, सी कोड में मुख्य अंतर यह है कि ऐसा नहीं है पॉइंटर, कोई ऑब्जेक्ट नहीं है, इसलिए आपका कोड आमतौर पर ऑब्जेक्ट पॉइंटर को पहले तर्क के रूप में लेता है।

void PQueueInitialise(PQUEUE *pq, int32 MaxElements, uint32 MaxRating, bool32 bIsAscending); 
void PQueueFree(PQUEUE *pq); 
int8 PQueuePush(PQUEUE *pq, void *item, uint32 (*PGetRating) (void *)); 
int32 PQueueIsFull(PQUEUE *pq); 
int32 PQueueIsEmpty(PQUEUE *pq); 
void *PQueuePop(PQUEUE *pq, uint32 (*PGetRating) (void *)); 
+0

आपका "पुराना सी कोड" malloc() को कॉल करता है। मुझे नहीं लगता कि 8 बिट एम्बेडेड प्लेटफार्मों के लिए बहुत सी सी कंपाइलर्स हैं जो आपको सीएपी लाइब्रेरी का समर्थन करते हैं ताकि आपको ढेर प्रबंधन (मॉलोक/फ्री) दिया जा सके! – mmmmmmmm

+0

यदि आप इसे अधिक सावधानी से देखते हैं तो यह निश्चित आकार प्राथमिकता कतार के लिए स्मृति के ब्लॉक को आवंटित करने के लिए मॉलोक को कॉल करता है। कतार स्वयं ही इस एकल ब्लॉक का बहुत कुशलता से उपयोग करती है। इसलिए इसे कोड की एक पंक्ति के साथ मॉलोक का उपयोग न करने के लिए परिवर्तित किया जा सकता है। – justinhj

+0

किसने इसे वोट दिया? यह उपयोगी सामान है, मुझे ए * सहायता भी चाहिए। मेरे पास कुछ Google कोड और एआई पर एक पुस्तक है लेकिन मैं अभी भी इसे सब कुछ समझ रहा हूं। –

संबंधित मुद्दे

 संबंधित मुद्दे