2017-01-02 95 views
5

Genel olarak dinamik ayırmaya izin verilmeyen ve istisnalara izin verilmeyen güvenlik yazılımını göz önünde bulundurun. Dinamik ayırma, yalnızca sınıf açıklığı, operatör new ve delete'u tanımladığında kullanılabilir. Başkaları sınıfı için operatör new'u kullanarak derleme başarısızlığına neden olabilir. Bir yandan standart kütüphane ile bu neden yan etkileriKüresel operatör olmadan çıplak metal yeni

void* operator new(std::size_t) = delete; 

:

anlatılan durumda derleme yetmezliğine neden en basit yolu, küresel yeni operatörünü kaldırmaktır. Örneğin, <array> dahil, <stdexcept> tarafından <new_allocator>'a dahil edilir. <new_allocator>, ::new operatörünü kullanır ve bu durum, istisna ve bellek ayırma kullanmak istemediğinizde bile oluşturma başarısız olur. Scoot Meyers'e göre <array> çıplak metal dostudur. derleyici ile

Öte yandan

bu neden hata yerleşik operatör

src/main.cpp:91:31: error: deleted definition of 'void* operator new(std::size_t)' 
void* operator new(std::size_t) = delete;        ^
<built-in>: note: previous declaration of 'void* operator new(std::size_t)' 

::new yasaklama ve <array> kullanmak için herhangi bir çözüm var mı?

::new numaralı telefon numarasından genel numaralı telefonu yasaklamak için herhangi bir çözüm var mı? Ne olursa olsun Kullandığınız programlama dili

+0

Bağlantı süresinde biraz daha sonra oluşan bir hata ile tamam mısınız? –

+0

@Marc Yapıyı hiç engelleyemeyen herhangi bir çözümle birlikte iyiyim. –

+1

Bazen C için iyi sebepler vardır. Bu onlardan biri gibi geliyor. C gizli ek yük oluşturmaz. "yeni" tek sorun değildir, ancak bozulma da sorunlara yol açabilir, örn. kesme işleyicileri ve diğer zaman kritik yolları için. – Olaf

cevap

4

GCC ve GNU LD kullanıyorsanız, bağlantı bayraklarınıza yalnızca --wrap=malloc kodunu ekleyebilirsiniz. Global ::new dahili olarak malloc()'u kullanıyorsa, uygulamanızda malloc() numaralı tüm çağrılar __wrap_malloc() ile değiştirilecektir. Bu işlev tanımlanmamışsa, bağlantı başarısız olur.

Başka bir, muhtemelen daha basit bir seçenek, linker komut dosyasına ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!"); eklemektir. Bu, malloc()'un tanımlanmadığını iddia edecektir.

Bu seçeneklerden hiçbiri, diğer bir genel ayırma biçimini kullanmak için genel ::new yeniden tanımlamanızı önler. iki şey vurgulamak istiyorum vardır

3

:

herhangi bir ses, çıplak metal sisteminde

, sadece tamamen bağlayıcı komut .heap segmenti kaldırın. Dinamik ayırmaya dayanan herhangi bir kod daha sonra bağlantı kuramaz. Ve yine de kullanmayacağınız bir segment için RAM ayırmanız gerekmeyecek.

+4

Bu çözüm, yalnızca yeni platformlarda ve “yeni” ve/veya “malloc()” nin böyle bir bölümün varlığına bağlı olduğu yerlerde çalışacaktır. Pek çok platformda bu bölüme ihtiyacınız olmaz ve yeni libz'i libc olarak kullanan tüm sistemler, sadece kendi "_sbrk_r()" işlevini uygulamanıza gerek duyar ve bu bölümle hiçbir ilgisi yoktur. –

2

... Sen bağlayıcı komut küresel sembolü ::new için aynı yapabilirdi, fakat isminin (burada _Znwj olarak) karıştırılmış, dolayısıyla bu biraz garip olacak:

  1. İstisnalarla ilgili üstbilgilerin tanımlarıyla birlikte eklenmesi, istisnalar kodunuza girmediğinde sizi rahatsız etmemelidir.
  2. İstisnaları devre dışı bıraktığınızda, bunları kodunuzda kullanamazsınız (eğer derleme yaparsanız derleme başarısız olur). Ancak, standart kitaplıktan istisnaların kullanımını kaldırmaz. Standart kitaplık, std::string (örneğin std::basic_string<char, ...>) veya std::streambuf (yani std::basic_streambuf<char, ...>) gibi şablon sınıflarının önceden derlenmiş sürümlerini içerebilir ve kodunuzda kullandığınızda, derleyici şablonları yeniden oluşturmaya çalışmaz, yalnızca yeniden kullanır istisnalar ile önceden derlenmiş sürümü.

Kodunuz üzerinde çok daha iyi bir kontrole sahip olmak için, standart kitaplığı tamamen G + + derleyici ile -nostdlib derleme seçeneğini kullanarak hariç tutmanızı kesinlikle öneririz. STL'den std::array gibi çeşitli şablon sınıflarını kullanmanız engellenmez, sadece C++ kütüphanesinin tamamını ve sizin için çalışma zamanını hariç tutar.

Ayrıca Practical Guide to Bare Metal C++ okumanızı öneririz. C++ çıplak metal içlerine biraz daha derin bir bakış açısı verebilir.

+1

BTW - tam olarak nr 2 numaralı öğe yüzünden C++ istisnalarının tüm libstdC++ için uygun şekilde devre dışı bırakıldığı ARM mikro denetleyiciler için kendi takım zincirimi derledim - https://github.com/FreddieChopin/bleeding-edge-toolchain –

İlgili konular