ãã€ã¯ãã³ã³ãããŒã©ã«ã¯C ++ã¯å¿ èŠãªããšèãã人ãããªãããããšã¯ç¥ã£ãŠããŸãã ã³ã¡ã³ããæžãåã«ãèšäºã®æåŸã®ã»ã¯ã·ã§ã³ãèªãããã«ãé¡ãããŸãã
Arduinoææè åãã®æ©èœ
Arduinoã¯ãéå®çãªC ++ãµããŒããæäŸããŸãã ããããç§ãç解ããŠããããã«ãarduinoéçºè ã¯C ++ã奜ãŸãªããããåŽåè ã®èŠæ±ã«å¿ããŠãæåã«æãŸã£ãæŸèæã察å¿ããã¢ãžã¥ãŒã«ã«æ¿å ¥ãããŸããã ããã¯ã avrfreaksã§èª¬æãããæŸèæã§ããããšãå€æãããããã¯ãžã®ã³ã¡ã³ãã§æå®ãããä¿®æ£ã¯ãããŸããã§ãã ã ãããã£ãŠãæåã«ãããåãé€ãå¿ èŠããããŸãã ãã¡ã€ã«ãåé€ãã- ããŒããŠã§ã¢/ arduino /ã³ã¢/ arduino / new.h
- ããŒããŠã§ã¢/ arduino /ã³ã¢/ arduino / new.cpp
çŽç²ã«ä»®æ³ããã³ãªã¢ãŒãã®æ¹æ³
ä»®æ³ã¡ãœããã®ã¡ã«ããºã ã¯ãéåžžvtableãä»ããŠå®è£ ãããŸãã ããã¯èŠæ Œã«ãã£ãŠèŠå¶ãããŠããŸãããããã¹ãŠã®ã³ã³ãã€ã©ã§äœ¿çšãããŠããŸãã ã¡ãœãããçŽç²ã«ä»®æ³çã«å®£èšããå Žåãã€ãŸãå®è£ ãæããªãå Žåã§ããvtableã«ã¯ãã®ã¡ãœãããžã®ãã€ã³ã¿çšã®ã¹ããŒã¹ããããŸãã ããã¯ãåã¯ã©ã¹ã察å¿ããå®è£ ãžã®ãã€ã³ã¿ãŒãåããªãã»ããã«é 眮ããããã«å¿ èŠã§ãã æ¬ èœããŠããã¡ãœãããžã®ãã€ã³ã¿ãŒã®ä»£ããã«ãã³ã³ãã€ã©ãŒã¯vtableã®ã¹ã¿ãé¢æ°__cxa_pure_virtualãžã®ãã€ã³ã¿ãŒãæžã蟌ã¿ãŸãã 誰ããçŽç²ã«ä»®æ³é¢æ°ãåŒã³åºãããšã«æåããå Žåãã³ã³ãããŒã«ã¯ã¹ã¿ãã«ç§»åããã©ã³ãã ãªã¡ã¢ãªãå®è¡ããããšãã代ããã«ããã°ã©ã ãåæ¢ããŸãã ãã®ä¿è·ã¯ã»ãšãã©ç¡æã§ããããšã«æ³šæããŠãã ãããåäžã®åŒã³åºããå«ã__cxa_pure_virtualå®è£ ã¯ããã©ãã·ã¥ã6ãã€ããã䜿çšããŸãããåççãªçåãçããŸãããæœè±¡ã¯ã©ã¹ã®ãªããžã§ã¯ããäœæããããšãäžå¯èœãªå Žåãã©ãããã°çŽç²ã«ä»®æ³é¢æ°ãåŒã³åºãããšãã§ããŸããïŒ äœæããããšã¯ã§ããŸããããå¥åŠãªã³ãŒããèšè¿°ããå Žåã¯åŒã³åºãããšãã§ããŸãã
class B { public: B() { // C , vtable B // , // virt(), non_virtual(); } void non_virtual() { // , // , // B virt(); // pure virtual method called // terminate called without an active exception // (core dumped) } virtual void virt() = 0; }; class C : public B{ public: virtual void virt() {} }; int main(int argc, char** argv) { C c; return 0; }
ãã®ãããªãšã©ãŒãåé¿ããã«ã¯ãåæåããããŸã§ãªããžã§ã¯ãã®ã¡ãœãããåŒã³åºããªãããã«ããå¿
èŠããããŸãã ã€ãŸããã³ã³ã¹ãã©ã¯ã¿ãŒã§è€éãªäœæ¥ãè¡ãå¿
èŠã¯ãããŸããã ãããŠãã³ã³ãã€ã©ãŒãã¢ããªã±ãŒã·ã§ã³ããã«ãããããã«ã次ã®é¢æ°ã®å®è£
ãè¿œå ããŸãã void __cxa_pure_virtual(void) { // We might want to write some diagnostics to uart in this case std::terminate(); } void __cxa_deleted_virtual(void) { // We might want to write some diagnostics to uart in this case std::terminate(); }
æšæºã©ã€ãã©ãªããçµäºããstd ::ã®å®è£
ãå¿
èŠã«ãªããŸãã 2ãã€ãã®RAMãš14ãã€ãã®ãã©ãã·ã¥ãæ¬åœã«ä¿åããå¿
èŠãããå Žåã¯ãabortïŒïŒãçŽæ¥åŒã³åºãããšãã§ããŸãããåŸã§std :: terminateãæãŸããçç±ã説æããŸãã
éçå€æ°
é¢æ°å ã§å€æ°ã宣èšã§ããŸããããã«ãããå®éã«ã°ããŒãã«å€æ°ãé¢æ°å ã§ã®ã¿è¡šç€ºãããŸãã int counter(int start) { static int cnt = start; return ++cnt; }
Cã§ã¯ã.dataã»ã¯ã·ã§ã³ã«åæå€ãããã«é
眮ããããã«éçå€æ°ãå®æ°ã§åæåããå¿
èŠãããããããã®ã³ãŒãã¯ã³ã³ãã€ã«ãããŸããã C ++ã§ã¯ããã¯èš±å¯ãããŠããŸãããã2ã€ã®ã¹ã¬ãããåæã«å€æ°ãåæåããããšããå Žåã«äœãèµ·ããããæå®ããŠããŸããã§ããã ãã®å Žåãå€ãã®ã³ã³ãã€ã©ãããã¯ãè¿œå ããŠã¹ã¬ããã»ãŒããæäŸããããšãéžæããŠãããC ++ 11ã§ã¯ãã®åäœãæšæºã®äžéšã«ãªããŸããã ãããã£ãŠãéçå€æ°gccã®éå®æ°å€ã«ããåæåã¯ã次ã®ã³ãŒãã«å±éãããŸãïŒgcc / cp / decl.c static <type> guard; if (!guard.first_byte) { if (__cxa_guard_acquire (&guard)) { bool flag = false; try { // Do initialization. flag = true; __cxa_guard_release (&guard); // Register variable for destruction at end of program. } catch { if (!flag) __cxa_guard_abort (&guard); } } }
ããã§ãguardã¯ãã©ã°ãšãã¥ãŒããã¯ã¹ãä¿æããã®ã«ååãªå€§ããã®æŽæ°åã§ãã gccã®ãœãŒã¹ãèŠããšããã®æé©åã¯ARMã¢ãŒããã¯ãã£ã®ã¿ãæ©ãŸããŠããããšãããããŸããã
gcc / config / arm / arm.c
/* The generic C++ ABI says 64-bit (long long). The EABI says 32-bit. */ static tree arm_cxx_guard_type (void) { return TARGET_AAPCS_BASED ? integer_type_node : long_long_integer_type_node; }
ãã以å€ã®å Žåã¯ãã¹ãŠãããã©ã«ãã®ã¿ã€ãlong_long_integer_type_nodeã䜿çšãããŸãã avrã§ã¯ã-mint8ãªãã·ã§ã³ã«å¿ããŠã64ããããŸãã¯32ãããã«ãªããŸãã ãã©ã°ã眮ãããŠãã16çªã®guard.first_byteã§ååã§ããã³ã³ãã€ã©ãŒã¯ãæäžäœã¢ãã¬ã¹*ïŒreinterpret_cast <char *>ïŒgïŒïŒãæã€ãã€ããšããŠèªèããŸãã äŸå€ã¯ãæåã®ãã€ãã®1ãããã®ã¿ã䜿çšãããARMãã©ãããã©ãŒã ã§ãã
ã©ãã§ããïŒ
ã¹ã¬ããã»ãŒããªéçå€æ°ãå¿ èŠãªãå Žåã¯ã-fno-threadsafe-staticsãªãã·ã§ã³ã§ç¡å¹ã«ããŸããè€éãªããã¯ã®ä»£ããã«ã³ã³ãã€ã©ãŒãåçŽãªãã©ã°ãã§ãã¯ãèšå®ããŸãã ãã®å Žåã__cxa_guard_ *ãå®è£ ããå¿ èŠã¯ãããŸããã ããããããããæäŸããå ŽåïŒarduinoã§è¡ãããããã«ïŒãå€æ°ãéåžžã®ã³ãŒããšå²ã蟌ã¿ããåæã«åæåãããå Žåãå®è£ ã¯æ£ããåäœãä¿èšŒããå¿ èŠããããŸãã ã€ãŸãã__ cxa_guard_acquireã¯å²ã蟌ã¿ããããã¯ãã__ cxa_guard_releaseãš__cxa_guard_abortã¯ãããã以åã®ç¶æ ã«æ»ãå¿ èŠããããŸãã RTOSã®å Žåãããããå²ã蟌ã¿ã®æ£ç¢ºããç ç²ã«ããŠ2ã€ã®ã¹ã¬ããã®æ£ç¢ºããæ®ããŠæºåãã§ããŠããã§ããããæ£ããå®è£ ã¯æ¬¡ã®ããã«åäœããã¯ãã§ãã namespace { // guard is an integer type big enough to hold flag and a mutex. // By default gcc uses long long int and avr ABI does not change it // So we have 32 or 64 bits available. Actually, we need 16. inline char& flag_part(__guard *g) { return *(reinterpret_cast<char*>(g)); } inline uint8_t& sreg_part(__guard *g) { return *(reinterpret_cast<uint8_t*>(g) + sizeof(char)); } } int __cxa_guard_acquire(__guard *g) { uint8_t oldSREG = SREG; cli(); // Initialization of static variable has to be done with blocked interrupts // because if this function is called from interrupt and sees that somebody // else is already doing initialization it MUST wait until initializations // is complete. That's impossible. // If you don't want this overhead compile with -fno-threadsafe-statics if (flag_part(g)) { SREG = oldSREG; return false; } else { sreg_part(g) = oldSREG; return true; } } void __cxa_guard_release (__guard *g) { flag_part(g) = 1; SREG = sreg_part(g); } void __cxa_guard_abort (__guard *g) { SREG = sreg_part(g); }
ããã
éçå€æ°ã䜿çšããªãå ŽåããŸãã¯å®æ°å€ãå²ãåœãŠãå Žåã¯ãç¡æã§ãã -fno-threadsafe-staticsãã©ã°ãæå®ããå Žåããã©ã°ã«8ãã€ãã®RAMããåå€æ°ã«12ãã€ãã®ãã©ãã·ã¥ãæ¯æããŸãã ã¹ã¬ããã»ãŒããªåæåã䜿çšããå Žåã¯ãåå€æ°ã«ããã«38ãã€ããããã°ã©ã å šäœã«ããã«44ãã€ãã䜿çšããŸãã ããã«ãéçå€æ°ã®åæåäžã«å²ã蟌ã¿ããããã¯ãããŸãã ããããããªãã¯ãã¶ã€ããŒã§é£ããä»äºãããŠããŸãããïŒéžæã¯ããªã次第ã§ãããã©ããªå Žåã§ããã©ã€ãã©ãªã__cxa_guard_ *é¢æ°ãæäŸããå Žåããããã¯æ£ããå®è£ ãããã¹ãã§ãããã©ãã§ãæäŸããããã©ã°ã§ã¯ãããŸããã äžè¬ã«ãéçå€æ°ã䜿çšããªãããã«ããããšããå§ãããŸãã
å ¥æå
abi.hããã³abi.cppæŒç®ånewããã³æŒç®ådelete
newæŒç®åãšdeleteæŒç®åã«é¢ããŠã¯ããã€ã¯ãã³ã³ãããŒã©ãŒã®ã¡ã¢ãªã¯éåžžã«å°ãªããšèª°ããèšãã§ããããããåçã¡ã¢ãªãŒã¯èš±ãããªãèŽ æ²¢ã§ãã ãããã®äººã ã¯ãnewããã³deleteãåçã¡ã¢ãªç®¡çã ãã§ã¯ãªãããšãç¥ããŸããã ããã°ã©ããŒã«ãã£ãŠå²ãåœãŠããããããã¡ãŒã«ãªããžã§ã¯ããé 眮ããæ°ããé 眮ããããŸãã ãããªãã§ã¯ãã¡ãã»ãŒãžãã¥ãŒãå®è£ ããããã¡ãŒã ãŠã§ã¢ã®éçºè ã«æãããŠãããªã³ã°ãããã¡ãæžã蟌ãããšã¯ã§ããŸããã ããŠãåçã¡ã¢ãªãäžèŠã§ãããšç¢ºä¿¡ããŠããã®ãªãããªãmallocãšfreeã®å®è£ ãæžããã®ã§ããïŒ ãã®ãããããããªãã§ã¯å®è¡ã§ããªãã¿ã¹ã¯ããããŸããæ°ããæŒç®åãšåé€æŒç®åã®çš®é¡
ãŸããåäžãªããžã§ã¯ãã«ã¡ã¢ãªãå²ãåœãŠãæŒç®ånewãšãé åã«ã¡ã¢ãªãå²ãåœãŠãæŒç®ånew []ããããŸãã æè¡çã«ã¯ãæ°ãã[]ãé åã®ãµã€ãºãèšæ¶ããŠãåèŠçŽ ãåé€ããããšãã«ãã¹ãã©ã¯ã¿ãåŒã³åºããšããç¹ã§ç°ãªããŸãã ãããã£ãŠãã¡ã¢ãªã解æŸããå Žåã¯ããã¢æŒç®ådeleteãŸãã¯operator delete []ã䜿çšããããšãéèŠã§ãã第äºã«ããããã®åæŒç®åã¯ãC ++ã®é¢æ°ãšåæ§ã«ãªãŒããŒããŒãã§ããŸãã ãŸãããã®èŠæ Œã§ã¯3ã€ã®ãªãã·ã§ã³ãå®çŸ©ãããŠããŸãã
void* operator new(std::size_t numBytes) throw(std::bad_alloc);
void* operator new(std::size_t numBytes, const std::nothrow_t& ) throw();
inline void* operator new(std::size_t, void* ptr) throw() {return ptr; }
æŒç®ååé€ã§ã¯ãç©äºã¯å°ãè€éã§ãã void *æŒç®ååé€ïŒstd :: size_t numBytesïŒãšvoid *æŒç®ååé€[]ïŒstd :: size_t numBytesïŒããããŸãã ä»ã®ãã©ã¡ãŒã¿ãŒã«å¯ŸããŠãªãŒããŒããŒãã§ããŸãããèšèªã«ã¯å¯Ÿå¿ããæ§æããªãããããããã®ãªãŒããŒããŒããåŒã³åºãããšã¯ã§ããŸããã ã³ã³ãã€ã©ãåé€æŒç®åã®ãªãŒããŒããŒãããŒãžã§ã³ãåŒã³åºãã±ãŒã¹ã¯1ã€ã ãã§ãã åçã¡ã¢ãªã«ãªããžã§ã¯ããäœæããnewæŒç®åãã¡ã¢ãªãæ£åžžã«å²ãåœãŠãã³ã³ã¹ãã©ã¯ã¿ããããåãå§ããäŸå€ãã¹ããŒãããšæ³åããŠãã ããã ã³ãŒãã¯ãŸã ãªããžã§ã¯ããžã®ãã€ã³ã¿ãèªç±ã«åãåã£ãŠããªãããã倱æãããªããžã§ã¯ãã®ã¡ã¢ãªãã·ã¹ãã ã«è¿ãããšã¯ã§ããŸããã ãããã£ãŠãã³ã³ãã€ã©ãŒã¯ãdeleteãåŒã³åºãããšã«ãã£ãŠãããè¡ãããšã匷å¶ãããŸãã ããããæ°ããé 眮ã䜿çšããŠã¡ã¢ãªããå²ãåœãŠããããå Žåã¯ã©ããªããŸããïŒ ãã®å Žåãéåžžã®åé€ãåŒã³åºãããšã¯ã§ããŸããããããã£ãŠãã³ã³ã¹ãã©ã¯ã¿ãŒãäŸå€ãã¹ããŒããå Žåãã³ã³ãã€ã©ãŒã¯ãnewãåŒã³åºãããã®ãšåããã©ã¡ãŒã¿ãŒã§åé€ã®ãªãŒããŒããŒãããŒãžã§ã³ãåŒã³åºããŸãã ãã®ãããæšæºã©ã€ãã©ãªã¯ãæŒç®ååé€ã®3ã€ã®ããŒãžã§ã³ãšæŒç®ååé€ã®3ã€ã®ããŒãžã§ã³ãå®çŸ©ããŸã[]ã
bad_allocã®åŠç
åè¿°ã®ãšããããšã©ãŒãçºçããå Žåã«äŸå€ãã¹ããŒããã«ã¯ãnewã®æãäžè¬çã«äœ¿çšãããããŒãžã§ã³ãå¿ èŠã§ãã ãã ããgccã¯avrã®äŸå€ããµããŒãããŠããŸãããäŸå€ãã¹ããŒãŸãã¯ãã£ããã§ããŸããã ãããããã£ããã§ããªãå Žåãããã°ã©ã ã«ã¯åäžã®tryã»ã¯ã·ã§ã³ããããŸãããã€ãŸããäŸå€ãã¹ããŒãããå Žåãstd :: terminateãåŒã³åºãããŸãã ããã«ãC ++æšæºã§ã¯ããã®å ŽåïŒ15.5.1ãåç §ïŒãã¹ã¿ãã¯ãå·»ãæ»ããªãããšãèš±å¯ãããŠããŸãã ãããã£ãŠãnewã¯std ::ãçŽæ¥åŒã³åºãããšãã§ããããã¯æšæºã«æºæ ããŸããæšæºã©ã€ãã©ãªããã¡ãŒã ãŠã§ã¢ãååŸããŠå®äºããããšãæããŠã¯ãããŸããïŒ bad_allocãçºçããå Žåãã©ããããã®é »åºŠã§ä¿®æ£ã§ããŸããïŒ éåžžã¯äœããããŸããã ãã¡ãŒã ãŠã§ã¢ã¯æ£ããåäœãç¶ããããšãã§ããããšã©ãŒãçºçãããšãã«å®äºããããšãç¥ã«æè¬ããŸãã ãã ããç¶æ³ãä¿®æ£ããæ¹æ³ãããã£ãŠããå Žåã¯ãnewhrowããŒãžã§ã³ã®newæŒç®åã䜿çšã§ããŸãã ãããå®å šãªmallocãšããŠèŠãŠãè¿ãããå€ããã§ãã¯ããªãå Žåã«æ£ããåäœããããã«ããŠãã ããã
å ¥æå
UClibc ++ã«ã¯ãnewããã³deleteã®å®å šã§æ£ããå®è£ ããããŸãã Trueãstd :: terminateã®ä»£ããã«ãããã§abortïŒïŒãåŒã³åºãããŸãã ããã§ã æ¹èšçãäœæããŸããã åæã«ãåæåãªã¹ãstd :: moveããã³std :: forvardãè¿œå ãããŸãããstd ::çµäºvsäžæ¢ïŒïŒ
avr-libcã®ããã¥ã¡ã³ãã«ãããšãabortïŒïŒé¢æ°ã¯ãã¹ãŠã®å²ã蟌ã¿ããããã¯ãããã®åŸãç¡éã«ãŒãã«é¥ããŸãã ããã¯ç§ãæããã®ã§ã¯ãããŸããã 2ã€ã®çç±ããããŸãã ãŸããããã€ã¹ãå±éºãªç¶æ ã«ããŸãã ã·ã¹ãã ãçºç±äœãå¶åŸ¡ããããã°ã©ã ããªã³ã«ãªã£ãç¬éã«ãµã€ã¯ã«ããã©ãããšãæ³åããŠãã ããã ãšã©ãŒãçºçããå ŽåãããŒãã®ãã¹ãŠã®åºåã0ã«èšå®ããããšã§å®å šãªç¶æ ã«åãæ¿ããããšæã£ãŠããŸãã次ã«ããã¹ãŠãæªãããšããã§ã«ç¥ã£ãŠããã®ã§ããŠã©ããããã°ãåäœããŠã·ã¹ãã ãåèµ·åãããŸã§åŸ ã€å¿ èŠã¯ãããŸããã ããã¯ããã«å®è¡ã§ããŸãããã¡ãŒã ãŠã§ã¢ãstd :: terminateã§çµäºããå Žåãç¬èªã®ãã³ãã©ãŒãã€ã³ã¹ããŒã«ããããã§å¿ èŠãªãã¹ãŠã®ã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã ç§ã¯äžæ¢ãç¡å¹ã«ããããšã¯ã§ããŸããïŒunixã§ããã®ããã«æäŸãããã¡ã«ããºã ã¯avrã§ã¯åäœããŸããã ãããã£ãŠãstd :: terminateå®è£ ãå æãã2ãã€ãã®RAMãš14ãã€ãã®ãã©ãã·ã¥ã䜿çšããæ¹ãããã§ãããã