Soru Clang ++ -stdlib = libc ++ ile libstdc ++ derlenmiş kütüphaneleri kullanma


Mac OS X (10.8.2) altında C ++ çalışıyorum ve son zamanlarda c ++ ++ derleyici libc ++ stdlib kullanarak C ++ 11 özelliklerini kullanma ihtiyacını buldum. Bununla birlikte, libstdc ++ (MacPorts'dan geliyor) 'a karşı derlenmiş ve bağlantılı bazı eski kütüphaneleri kullanmam gerekiyor.

Bunu yaparken, eski kütüphanelerin başlıkları, ör. std::string, std::__1::basic_string (yani libc ++ uygulaması std::string) onun yerine std::basic_string uygulanması.

İki kütüphaneyi geliştirme aşamasında karıştırmanın bir yolu var mı (örneğin bazı önişlemci bayrakları kullanarak?)


66
2017-09-22 10:31


Menşei




Cevaplar:


Gördüğünüz şey satır içi ad alanları ABI versiyonlama elde etmek için.

Bu ne demek:

Libstdc ++ std::string libc ++'dan farklı bir veri yapısıdır std::string. İkincisi referans sayılan bir tasarıma sahipken, ikincisi ise değil. API uyumlu olsalar da ABI uyumlu değildirler. Bu, eğer bir std::string libstdc ++ ile ve sonra libc ++ ile bağlantılı başka bir koda aktarırsanız, alıcı kod libc ++ olduğunu düşünür. std::string. Yani Alıcı, referans sayımlarının arttırılması veya azaltılması gerektiğine dair bir ipucu içermeyecektir.

Satır içi ad alanları olmadan, sonuç bir çalışma zamanı hatası olur. Umduğun en iyisi kazadır. Satır içi ad alanları ile bu çalışma zamanı hatası bir bağlantı zamanı hatasına dönüştürülür.

Programcı için libstdc ++ std::string ve libc ++ std::string aynı tipe benziyor. Ama bağlayıcıya, tamamen farklı tipler gibi görünüyorlar (ipucu std::__1 ad). Linker'ın görüşü doğrudur. Onlar Hangi tamamen farklı tipler.

Evet, bağlantı kurmak için bazı önişlemci bayraklarını değiştirebilirsin. Ama sonuçta ortaya çıkan çalışma zamanı hatalarının hatalarını ayıklayan bir şeytan olur.

İstediğiniz şeyi yapmanın tek yolu, bu dylib'ler arasındaki ara yüzleri içermemektir. std:: gibi türler string. Örneğin, char yerine. Bellek sahipliğini libstdc ++ - bağlantılı koddan libc ++ - linked koduna ve tersine aktarabiliyorsunuz (ikisi de aynı malloc havuzuna düşecek).


87
2017-09-22 17:57



Yani özetlemek gerekirse, libc ++ ile eski kütüphaneleri (yani libstdc ++ ile bağlantılı kütüphaneleri) kullanma umudu yoktur. Bu gerçekten ciddi bir sınırlama - user1690715
Maksimum bir umut var: Sürüm kütüphanelerini dylib sınırları boyunca geçmediğiniz sürece iki kütüphaneyi bir süreç içinde karıştırabilirsiniz. Ve yanlışlıkla yaparsanız, hata bağlantı zamanında yakalanır. Atabilirsin std::exception- dylib sınırları boyunca var olan istisnalar ve dylib sınırları boyunca bellek sahipliğini aktarır. Bunun, gcc'nin kendi 4.2 sürümü ile sağlayacağından daha iyi ABI uyumluluğu olabileceğinden şüpheleniyorum. Std spec tarafından bile, unutmayın std::string ABI, C ++ 98/03 ve C ++ 11 arasında uyumludur. Birincisi yaygın olarak kabul edilirken, ikincisi de yasaklanmıştır. - Howard Hinnant
Başka bir örnek: Pre-C ++ 11 gcc std::list ABI C ++ 11 ile uyumlu değildir std::list. Başka bir deyişle: libc ++ ile ilgili sözleriniz, libstdc ++ 'nin pre-C ++ 11 sürümlerine eşit derecede iyi uygulanır (daha fazla değilse). libc ++, pre-C ++ 11 libstdc ++ ile uyumsuz bir C ++ 11'e uymayan bir libstdc ++ olacaktır. - Howard Hinnant
@ user1690715 STL nesnelerini kendi API'lerine maruz bıraktıklarında, iki çalışma zamanına karşı bir araya getirilen kütüphaneler için bir umut olmadığını söylemek daha doğru olur - bu her zaman çok dicey bir öneri olmuştur. - marko
Std :: string için bir atama aşırı yüklemesi std :: _ 1 :: string ve tersi oluşturmak mümkün olmaz mıydı? - Michael