naoya_t
naoya****@gmail*****
2008年 8月 22日 (金) 15:01:13 JST
naoya_tです。 来たる9月20日にアルクから出版される「英辞郎 第四版」にMac OS X用検索ソフトとして拙作「DiDi」のカスタマイズ版が同梱されるのですが、Cocoa(Objective-C)にGauche.frameworkをバンドルして使わせて頂いております。 (特に検索条件文をパースして、マッチ判定関数にコンパイルする辺りでGaucheが活躍しています) 開発中に以下のような不具合を発見しましたので、修正のためのパッチを送らせて頂きます。 ・sitelibdir は正しくフルパスに展開されるのに、syslibdir は ./share/gauche/0.8.13/lib のように展開され、結果としてライブラリファイルが読み込めない ・sysarchdir も同様に ./lib/gauche/0.8.13/i386-apple-darwin8 のように展開されてしまうため dynamic-load に失敗し、can't find dlopen-able module "srfi-1-lib" のようなエラーが出まくる ・なぜか Intel Mac, OS X 10.4.x に限って発生し、PowerPC ないし Leopard上では再現しない 原因箇所は src/getdir_darwin.c の get_install_dir()関数なのですが、CFBundleGetBundleWithIdentifier()で取得したbundleオブジェクトをCFRetain()していないのにCFRelease()しているため二重解放になっていて、その結果初回(sitelibdirの展開時)にはバンドルが取得できるものの次のsyslibdir展開時にはNULLが返り、暫定出力の "." が返されていました。 本来どのCPU、どのOSバージョンで出てもおかしくないのですが、不思議なことに Mac OS X 10.4.x で Intel Mac の場合に限ってこの問題が発生していました。 ;; この問題の原因究明にあたり、REPLが使える便利さを実感しました。 以下のコードでは error: 以下にエラー時の対応をまとめたりしていますが、ここでどうしてもやるべきなのは CFRetain(bundle); の1点です。あとはshiroさんの判断におまかせします。 --- src/getdir_darwin.c.orig 2005-10-24 10:37:21.000000000 +0900 +++ src/getdir_darwin.c 2008-08-22 13:45:57.000000000 +0900 @@ -22,36 +22,57 @@ static int get_install_dir(char *buf, int buflen, void (*errfn)(const char *, ...)) { - CFBundleRef bundle; - CFURLRef bundleURL; - CFStringRef bundlePath; + CFBundleRef bundle = NULL; + CFURLRef bundleURL = NULL; + CFStringRef bundlePath = NULL; bundle = CFBundleGetBundleWithIdentifier(CFSTR(LIBGAUCHE_ID)); if (bundle == NULL) { /* This call fails when gosh is called during the build process (thus, the framework hasn't been created). For the time being, we just return a dummy directory. */ - strcpy(buf, "."); - return 1; + goto error; } + /* Ownership of bundle follows the Get Rule of Core Foundation. + ie. we must claim ownership (with the CFRetain function). + We are then responsible for relinquishing ownership when we have finished with it. */ + CFRetain(bundle); + bundleURL = CFBundleCopyBundleURL(bundle); if (bundleURL == NULL) { errfn("CFBundleCopyBundleURL failed"); + goto error; } + /* Ownership of bundleURL follows the Create Rule of Core Foundation. + ie. it is our responsibility to relinquish ownership (using CFRelease) when we have finished with it. */ + bundlePath = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle); if (bundlePath == NULL) { errfn("CFURLCopyFileSystemPath failed"); + goto error; } + /* Ownership follows the Create Rule. */ + if (!CFStringGetCString(bundlePath, buf, buflen, kCFStringEncodingUTF8)) { errfn("CFStringGetCString failed"); + goto error; } if (strlen(buf) + strlen(SUBDIR) + 1 >= buflen) { errfn("pathname too long"); + goto error; } + strcat(buf, SUBDIR); CFRelease(bundlePath); CFRelease(bundleURL); CFRelease(bundle); return strlen(buf); +error: + /* For the time being, we just return a dummy directory. */ + strcpy(buf, "."); + if (bundlePath) CFRelease(bundlePath); + if (bundleURL) CFRelease(bundleURL); + if (bundle) CFRelease(bundle); + return 1; } -------- naoya_t / Naoya Tozuka E-mail: naoya****@gmail*****