OSXでrubyに書いたC++ライブラリをエクスポートするためのRuby拡張機能の作成に問題があります。この単純な例:スローさbad_cast例外でC++ルビ拡張子を作成できません
#include <boost/regex.hpp>
extern "C" void Init_bayeux()
{
boost::regex expression("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
}
結果:
#0 0x00000001014663bd in __cxa_throw()
#1 0x00000001014cf6b2 in __cxa_bad_cast()
#2 0x00000001014986f9 in std::use_facet<std::collate<char> >()
#3 0x0000000101135a4f in boost::re_detail::cpp_regex_traits_base<char>::imbue (this=0x7fff5fbfe4d0, [email protected]) at cpp_regex_traits.hpp:218
#4 0x0000000101138d42 in cpp_regex_traits_base (this=0x7fff5fbfe4d0, [email protected]) at cpp_regex_traits.hpp:173
#5 0x000000010113eda6 in boost::re_detail::create_cpp_regex_traits<char> ([email protected]) at cpp_regex_traits.hpp:859
#6 0x0000000101149bee in cpp_regex_traits (this=0x101600200) at cpp_regex_traits.hpp:880
#7 0x0000000101142758 in regex_traits (this=0x101600200) at regex_traits.hpp:75
#8 0x000000010113d68c in regex_traits_wrapper (this=0x101600200) at regex_traits.hpp:169
#9 0x000000010113bae1 in regex_data (this=0x101600060) at basic_regex.hpp:166
#10 0x000000010113981e in basic_regex_implementation (this=0x101600060) at basic_regex.hpp:202
#11 0x0000000101136e1a in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::do_assign (this=0x7fff5fbfe710, p1=0x100540ae0 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", p2=0x100540b19 "", f=0) at basic_regex.hpp:652
#12 0x0000000100540a66 in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign (this=0x7fff5fbfe710, p1=0x100540ae0 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", p2=0x100540b19 "", f=0) at basic_regex.hpp:379
#13 0x0000000100540a13 in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign (this=0x7fff5fbfe710, p=0x100540ae0 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", f=0) at basic_regex.hpp:364
#14 0x000000010054096e in basic_regex (this=0x7fff5fbfe710, p=0x100540ae0 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", f=0) at basic_regex.hpp:333
#15 0x00000001005407e2 in Init_bayeux() at bayeux.cpp:10
#16 0x0000000100004593 in dln_load (file=0x1008bc000 "/Users/todi/sioux/lib/debug/rack/bayeux.bundle") at dln.c:1293
私は拡張子をコンパイル:
g++ ./source/rack/bayeux.cpp -o /Users/todi/sioux/obj/debug/rack/bayeux.o -Wall -pedantic -Wno-parentheses -Wno-sign-compare -fno-common -c -pipe -I/Users/todi/sioux/source -ggdb -O0
そして最後に動的ライブラリをリンク:
g++ -o /Users/todi/sioux/lib/debug/rack/bayeux.bundle -bundle -ggdb /Users/todi/sioux/obj/debug/rack/bayeux.o -L/Users/todi/sioux/lib/debug -lrack -lboost_regex-mt-d -lruby
私はウェブをイヤリングし、あらゆる種類のリンクとコンパイラスイッチを試しました。実行可能ファイルをビルドする場合、そのような問題はありません。他の誰かがこのような問題を抱えていて解決策を見つけましたか?
は、私はこれをさらに調査し、例外を発生させた関数はこのようになっていることを発見しました:STDのソースで
std::locale loc = std::locale("C");
std::use_facet< std::collate<char> >(loc);
:: <を照合>私はスローなステートメントを見つけました:
use_facet(const locale& __loc)
{
const size_t __i = _Facet::id._M_id();
const locale::facet** __facets = __loc._M_impl->_M_facets;
if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
__throw_bad_cast();
#ifdef __GXX_RTTI
return dynamic_cast<const _Facet&>(*__facets[__i]);
#else
return static_cast<const _Facet&>(*__facets[__i]);
#endif
}
これは意味を持ちますか?
更新:
Todis-MacBook-Pro:rack todi$ g++ -shared -fpic -o bayeux.bundle bayeux.cpp
Todis-MacBook-Pro:rack todi$ ruby -I. -rbayeux -e 'puts :ok'
terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast
Abort trap
バージョン:私はヤンの提案を試してみた
Todis-MacBook-Pro:rack todi$ ruby -v
ruby 1.9.2p136 (2010-12-25 revision 30365) [x86_64-darwin10.6.0]
Todis-MacBook-Pro:rack todi$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/opt/local/libexec/gcc/x86_64-apple-darwin10/4.5.2/lto-wrapper
Target: x86_64-apple-darwin10
Configured with: ../gcc-4.5.2/configure --prefix=/opt/local --build=x86_64-apple-darwin10 --enable-languages=c,c++,objc,obj-c++,fortran,java --libdir=/opt/local/lib/gcc45 --includedir=/opt/local/include/gcc45 --infodir=/opt/local/share/info --mandir=/opt/local/share/man --datarootdir=/opt/local/share/gcc-4.5 --with-local-prefix=/opt/local --with-system-zlib --disable-nls --program-suffix=-mp-4.5 --with-gxx-include-dir=/opt/local/include/gcc45/c++/ --with-gmp=/opt/local --with-mpfr=/opt/local --with-mpc=/opt/local --enable-stage1-checking --disable-multilib --enable-fully-dynamic-string
Thread model: posix
gcc version 4.5.2 (GCC)
更新:
それだではないスローuse_facet()でバインドチェックが、次の行は、実際には動的キャストを行います。この例では、RTTIと多分何かにそれをダウン沸騰:
#define private public
#include <locale>
#include <iostream>
#include <typeinfo>
extern "C" void Init_bayeux()
{
std::locale loc = std::locale("C");
printf("size: %i\n", loc._M_impl->_M_facets_size);
printf("id: %i\n", std::collate<char>::id._M_id());
const std::locale::facet& fac = *loc._M_impl->_M_facets[ std::collate<char>::id._M_id() ];
printf("name: %s\n", typeid(fac).name());
printf("name: %s\n", typeid(std::collate<char>).name());
const std::type_info& a = typeid(fac);
const std::type_info& b = typeid(std::collate<char>);
printf("equal: %i\n", !a.before(b) && !b.before(a));
dynamic_cast< const std::collate<char>& >(fac);
}
COUTの使用も失敗したので、私はprintfの()を使用しました。上記のコードの出力は次のようになります。私は(メインにInit_bayeuxの名前を変更)し、実行可能にリンクした場合、出力された
:
更新:
size: 28
id: 5
name: St7collateIcE
name: St7collateIcE
equal: 1
terminate called after throwing an instance of 'std::bad_cast'
what(): std::bad_cast
Abort trap
はしてビルドします同じですが、終了する呼び出しはありません。
アップデート:私は共有ライブラリをロードするとInit_bayeuxを()を実行する小さなプログラムを書くとき
、再び、例外がスローされない:
#include <dlfcn.h>
int main()
{
void* handle = dlopen("bayeux.bundle", RTLD_LAZY|RTLD_GLOBAL);
void(*f)(void) = (void(*)(void)) dlsym(handle, "Init_bayeux") ;
f();
}
だから、それはそれことを、私には見えますruby.exeがどのようにビルドされたかに問題があるかもしれません。それは理にかなっていますか?
更新: 私は2つのtype_infoオブジェクトの名前を含むアドレスを見ました。同じ内容ですが、住所が異なります。リンクコマンドに-flat_namespaceスイッチを追加しました。これでdynamic_castが動作します。ブースト正規表現ライブラリの元の問題はまだ存在しますが、これは共有ライブラリにブーストを静的にリンクするか、-flat_namespaceスイッチを使ってブーストライブラリを再構築することで解決できると思います。
更新:
g++ -shared -flat_namespace -fPIC -o bayeux.bundle /Users/todi/boost_1_49_0/stage/lib/libboost_regex.a bayeux.cpp
しかし、Rubyインタプリタに拡張をロードするときに、静的シンボルの初期化が失敗した: は今、私は、このコマンドを使用して構築し、ブースト正規表現式に戻って非常に最初の例によ:
ruby(59384,0x7fff712b8cc0) malloc: *** error for object 0x7fff70b19500: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Program received signal SIGABRT, Aborted.
0x00007fff8a6ab0b6 in __kill()
(gdb) bt
#0 0x00007fff8a6ab0b6 in __kill()
#1 0x00007fff8a74b9f6 in abort()
#2 0x00007fff8a663195 in free()
#3 0x0000000100541023 in boost::re_detail::cpp_regex_traits_char_layer<char>::init (this=0x10060be50) at basic_string.h:237
#4 0x0000000100543904 in boost::object_cache<boost::re_detail::cpp_regex_traits_base<char>, boost::re_detail::cpp_regex_traits_implementation<char> >::do_get ([email protected]) at cpp_regex_traits.hpp:366
#5 0x000000010056005b in create_cpp_regex_traits<char> (l=<value temporarily unavailable, due to optimizations>) at pending/object_cache.hpp:69
#6 0x0000000100544c33 in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::do_assign (this=0x7fff5fbfe090, p1=0x100567158 "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", p2=0x100567191 "", f=0) at cpp_regex_traits.hpp:880
#7 0x0000000100566280 in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign()
#8 0x000000010056622d in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::assign()
#9 0x0000000100566188 in boost::basic_regex<char, boost::regex_traits<char, boost::cpp_regex_traits<char> > >::basic_regex()
#10 0x0000000100566025 in Init_bayeux()
#11 0x0000000100003a23 in dln_load (file=0x10201a000 "/Users/todi/sioux/source/rack/bayeux.bundle") at dln.c:1293
#12 0x000000010016569d in vm_pop_frame [inlined]() at /Users/todi/.rvm/src/ruby-1.9.2-p320/vm_insnhelper.c:1465
#13 0x000000010016569d in rb_vm_call_cfunc (recv=4303980440, func=0x100042520 <load_ext>, arg=4303803000, blockptr=0x1, filename=<value temporarily unavailable, due to optimizations>, filepath=<value temporarily unavailable, due to optimizations>) at vm.c:1467
#14 0x0000000100043382 in rb_require_safe (fname=4303904640, safe=0) at load.c:602
#15 0x000000010017cbf3 in vm_call_cfunc [inlined]() at /Users/todi/.rvm/src/ruby-1.9.2-p320/vm_insnhelper.c:402
#16 0x000000010017cbf3 in vm_call_method (th=0x1003016b0, cfp=0x1004ffef8, num=1, blockptr=0x1, flag=8, id=<value temporarily unavailable, due to optimizations>, me=0x10182cfa0, recv=4303980440) at vm_insnhelper.c:528
...
上記の小さなcプログラムで共有ライブラリを読み込むと、これもやはり失敗しません。
アップデート:-Lコマンドotool
ruby(15197,0x7fff708aecc0) malloc: *** error for object 0x7fff7027e500: pointer being freed was not allocated
は、すべてのライブラリを静的リンクされていることを確認:同じエラーで
g++ -shared -fPIC -flat_namespace -nodefaultlibs -o bayeux.bundle -static -lstdc++ -lpthread -lgcc_eh -lboost_regex-mt bayeux.cpp
: は、今私は、静的な最初の例をリンク
bayeux.bundle:
bayeux.bundle (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
デバッグ:
私がブーストデバッグバージョンとリンクすると、期待どおりに動作します。
について。 'g ++ -shared -fpic -o bayeux.so -lboost_regex bayeux.cpp'と' ruby -I 'を使ってサンプルC++ファイルをコンパイルしました。 -rbayeux -e 'puts:ok''は問題なく拡張モジュールをロードしました。しかし、 '-lboost_regex'を省略したときにいくつか問題がありました。さらに、使用しているRubyとBoostのバージョンを指定できますか?この問題をどのように再現できますか? – Jan
@Jan、お試しいただきありがとうございます。 OS Xでは、 'so'拡張子を 'bundle'に変更しなければなりません(そうしないとrequireはライブラリを見つけられません)が、結果は変わりません。 –
@Jan、あなたはブーストライブラリを省略することができます、それなしで失敗します。それは失敗するuse_facet <>の呼び出しです。 –