0

ネイティブのc++コードを書いているときに、同じプログラムがxcode(iOS)で正常に動作するのを確認しましたが、eclipse(android)ではクラッシュします。問題のあるコードを見つけることができましたが、それはメモリアクセスが悪いためでした。なぜxcode(iOS)が同じ悪いアクセスにヒットしなかったので、クラッシュしたのだろうか。

実際、私は「class_A」というクラスを作成しました。これは、class_Bという他のクラスを継承します。コードの後半で、同じクラスインスタンスポインタを作成し、スーパークラスタイプのオブジェクト、つまりclass_Bを返す関数foo()(class_Bに属する)の戻りオブジェクトを割り当てました。

コードスニペット ...

class class_A : public class_B
{
public:

};

class_A *tempPart = (class_A *)class_A::foo("abc.png"); 

if(tempPart)
                {


                    -------------------
                   --------------------

 }

現在、_tempPartにアクセスしている間、プログラムはandroid(eclipse)でクラッシュしますが、xcode(iOS)は常に正常に動作します。fn foo()がclass_B型のオブジェクトを返すので、スーパークラス(小さいサイズのオブジェクト)class_Bのオブジェクトを継承されたクラス(大きいサイズのオブジェクト)Class_Aのオブジェクトに割り当てていたため、メモリアクセスが悪くなっていることがわかりました。

しかし、なぜ同じ問題がxcode(iOS)で見られないのか理解できませんでした。私はxcodeとc++を初めて使用するので、これを理解するのを手伝ってください。

4

3 に答える 3

2

未定義の動作は未定義です。

無効なメモリにアクセスするなどの操作を行うと、C++で未定義の動作が発生します。結果はクラッシュになることがよくありますが、C++はそのようなことを保証しません。代わりに、プログラムは単に奇妙に動作するか、エラーの兆候がなく、意図したとおりに動作する可能性があります。実装が異なれば、動作も異なる可能性があります。

これは、C ++が未定義の動作をする理由を説明するのに役立つかもしれないいくつかの情報です(未定義の動作を除外するために非常に懸命に働くJavaのような言語とは対照的です)。

すべてのCプログラマーが未定義動作について知っておくべきこと


あなたの説明から、何が本当に間違っているのかは完全には明らかではありません。大きなオブジェクトを小さなオブジェクトに割り当てるとメモリアクセスが悪くなるということですが、それはC ++での割り当ての仕組みではなく、サンプルコードはとにかくポインタを使用しています。次のコードは完全に合法であり、明確に定義されています。例:

struct B {};
struct D : B {
  int i;
  void foo() { i = 100; }
};

B b = D(); // works fine, does not overwrite anything outside b. Slicing occurs.

B *bar() {
  return new D;
}

D *d = (D*)bar(); // works fine because the dynamic type matches.

問題が発生する場所は次のとおりです。

B *baz() { return new B; }

D *d = (D*)baz(); // not okay, undefined behavior. Anything can happen now, later, or even before this point.
d->foo(); // might crash, might not.

したがって、これがプログラムの実行内容であると仮定すると、Javaでの同じエラーは、例外を引き起こすように明確に定義されています。Objective-Cでは、メッセージパッシング機構は実行時にセレクターの実装を見つけようとしますが、何も見つからない場合は、「認識されないセレクター」例外が発生します。

于 2012-12-17T03:44:14.123 に答える
0

@ Bames53 が答えたように、これは未定義の動作です。簡単な修正はclass_B::foo、テンプレート関数を作成し、次のように書き直すことです。

template <class ReturnClassType>
ReturnClassType *foo(std::string str){

次に、次のように呼び出します

class_A::foo<class_A>("abc.png"); 

public/protected 関数を使用して返されたオブジェクトを初期化する場合、これは機能するはずです。

于 2012-12-17T03:49:16.833 に答える
0

B を A に安全にアップキャストすることはできません。B には _useShader メンバーがありません。逆にできるのは B* = A* だけですが、A* = B* はできません。A オブジェクト用に別のファクトリ メソッドを作成したい場合があります。

于 2012-12-17T03:51:35.720 に答える