iPhone デバイス用にはコンパイルされるが、シミュレーター用にはコンパイルされないコード
質問
C++ を使用して iPhone アプリケーションのアルゴリズム部分を開発しているのですが、奇妙なバグに遭遇しました。私が持っているコードは、Linux、Mac、iPhone デバイスの両方で gcc-4.2 で正常にコンパイルされますが、シミュレーターではコンパイルできません。そのため、デバッグとテストが非常に困難になります。
シミュレーター用にコンパイルしようとした際のエラー メッセージは 4.0.x の既知のバグに似ていますが、gcc-4.2 をデフォルトのコンパイラーとして明示的に設定しているため、その理由はあまり明確ではありません。
バグを示すために、次の短いコード スニペットを用意しました。
バグ.cpp
#include <tr1/unordered_map>
#include <iostream>
/* a hash key for the visitedTrip table */
struct X {
int x;
X() : x(0){};
X(int x) : x(x){};
};
typedef std::tr1::unordered_map<int,X> dict;
int main()
{
dict c1;
X a(0);
X b(1);
X c(2);
c1[0] = a;
c1[1] = b;
c1[2] = c;
dict::const_iterator it;
for(it = c1.begin(); it != c1.end(); it++)
std::cout << it->first << std::endl;
return (0);
}
そして次のようにコンパイルしようとしました:
コンパイル.sh
#!/bin/bash
#
# Compiling for the simulator and compiling under gcc-4.0 return the same error message
#
#SUCCESS
c++-4.2 -arch i386 bug.cpp
#FAIL
c++-4.0 -arch i386 bug.cpp
#SUCCESS
gcc-4.2 -arch i386 -c bug.cpp
#FAIL
gcc-4.0 -arch i386 -c bug.cpp
#FAIL
gcc-4.2 -arch i386 -c bug.cpp -isysroot /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk
シミュレーター用にコンパイルするために gcc-4.2 を使用しているにもかかわらず、gcc-4.0 でコンパイルしている場合と同じエラー メッセージが表示されます。
bug.cpp:27: error: no matching function for call to ‘Internal::hashtable_iterator<std::pair<const int, X>, false, false>::hashtable_iterator()’
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/usr/include/c++/4.2.1/tr1/hashtable:236: note: candidates are: Internal::hashtable_iterator<Value, is_const, cache>::hashtable_iterator(const Internal::hashtable_iterator<Value, true, cache>&) [with Value = std::pair<const int, X>, bool is_const = false, bool cache = false]
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/usr/include/c++/4.2.1/tr1/hashtable:234: note: Internal::hashtable_iterator<Value, is_const, cache>::hashtable_iterator(Internal::hash_node<Value, cache>**) [with Value = std::pair<const int, X>, bool is_const = false, bool cache = false]
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/usr/include/c++/4.2.1/tr1/hashtable:232: note: Internal::hashtable_iterator<Value, is_const, cache>::hashtable_iterator(Internal::hash_node<Value, cache>*, Internal::hash_node<Value, cache>**) [with Value = std::pair<const int, X>, bool is_const = false, bool cache = false]
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/usr/include/c++/4.2.1/tr1/hashtable:225: note: Internal::hashtable_iterator<std::pair<const int, X>, false, false>::hashtable_iterator(const Internal::hashtable_iterator<std::pair<const int, X>, false, false>&)
実際にはシミュレータはこのバグが修正された gcc-4.2.x を使用しているはずなのに、この gcc-4.0.x のバグがシミュレータに忍び込む理由について何か考えはありますか?
解決
これが正確に正しい答えかどうかはわかりませんが、おそらく 4.2 の使用中に 4.0 の動作が発生する理由はこれで説明されるでしょう。
> pwd
/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator3.1.sdk/usr/include/c++
> ls -l
total 4
drwxr-xr-x 10 root wheel 2278 10 Sep 09:32 4.0.0/
lrwxr-xr-x 1 root wheel 5 10 Sep 09:30 4.2.1@ -> 4.0.0
少なくとも Xcode 3.2 を搭載した Snow Leopard では、両方のバージョンで 4.0 ヘッダー セットを使用しようとしているようです。
他のヒント
シミュレーターが参照しているライブラリ (STL) ヘッダーを注意深くチェックします。
Xcode にはコンパイラの問題が発生する場合があります。おそらく、ここで説明したものと同様の問題が発生している可能性があります。
この場合、デバイスとシミュレータ専用のコンパイラを指定する必要があります。これでは意味がないとわかっていますが、問題は解決しました。
gcc-4.0.x では、unowned_map のイテレータにデフォルトのコンストラクタがないという問題があります。
http://bytes.com/topic/c/answers/607427-error-tr1-unowned_map-iterator
宣言時に初期化すると、それが修正されるはずです。
for(dict::const_iterator it = c1.begin(); it != c1.end(); it++)
std::cout << it->first << std::endl;