3

プロジェクトを (Windows Mobile から) iPhone に移植し、Objective-C++ を使用して、汎用の C および C++ コードの多くを可能な限り共有しています。ただし、テスト中に、デバイスで実行している場合にのみ現れる、好奇心旺盛で厄介な問題に遭遇しました。再現性を証明し、簡単に共有できるように、問題のコードを新しいプロジェクトにまとめました。

// MemoryTestAppDelegate.mm
#include "MemoryTestAppDelegate.h"
#include "Widget.h"

@implementation MemoryTestAppDelegate

@synthesize window;

- (void)applicationDidFinishLaunching: (UIApplication*)application {
    Widget widget;
    const wchar_t wideHello[] = L"Hello, world!";
    const char narrowHello[] = "Hello, world!";
    widget.Go();
    widget.Go(wideHello);

    [window makeKeyAndVisible];
}

- (void)dealloc {
    [window release];
    [super dealloc];
}

@end

 

// MemoryTestAppDelegate.h
#import <UIKit/UIKit.h>

@interface MemoryTestAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow* window;
}

@property (nonatomic, retain) IBOutlet UIWindow* window;

@end

 

// Widget.h
#include <iostream>

class Widget {
public:
    Widget() { };
    ~Widget() { };

    void Go() const { std::wcout << L"Widget is GO." << std::endl; };
    void Go(const wchar_t* message) const { std::wcout << message << std::endl; };
};

 

// main.mm
#import <UIKit/UIKit.h>

int main(int argc, char* argv[]) {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, @"MemoryTestAppDelegate");
    [pool release];
    return retVal;
}

 

残りのプロジェクト ファイルと設定は、新しい iPhone ウィンドウ ベースのアプリケーションを作成することによってデフォルトで提供されます。(.xib を削除し、MemoryTest-Info.plist から「メイン nib ファイルのベース名」を削除し、main.mm で UIApplicationMain の 4 番目のパラメーターとして @"MemoryTestAppDelegate" を指定して、Interface Builder を削除しました。)

シミュレーターはこの例を期待どおりに実行しますが、デバイスには問題があります。ただし、wideHello と wideHello の両方が Locals ウォッチ エリアで破損しているように見えます。(wideHello は表示されませんが、正しい文字数が示され、narrowHello は "`K3\x10f\x11" と表示されます。) メモリ ウィンドウで 2 つの文字列を調べると、正しい内容が表示されます - 想定されたアドレスを 64 バイト超えています。 wideHelloとnarrowHelloの

オーバーロードされたメソッド Widget::Go(const wchar_t*) const の 2 番目の呼び出しで示されるように、wideHello 文字列は std::wcout を介して表示され、applicationDidFinishLaunching をステップ実行すると、文字列が正しく出力されます。ただし、wcscpy/memcpy を使用したコピー操作は、実際のコンテンツの 64 バイト先の「前の」データから読み取られたため、実際のデバイス上のアプリケーションに多くの問題が発生しました。ローカル スタック上のウィジェットの初期化を Widget* と動的割り当てに置き換えると、メモリ レイアウトは期待どおりになります。他のバリエーションも試しましたが、スタックに割り当てられた C++ オブジェクトだけが問題を引き起こしているようです。

読んでくれてありがとう。

4

1 に答える 1

1

Apple 自身でさえ、シミュレーターとデバイスの間にいくつかの相違点があることを認めています。

悲しいことに、私はあなたの問題を解決することはできませんが、シミュレーターコードは、Intel、i386 アーキテクチャでコンパイルおよび実行されるように、Mac のプロセッサで文字通りコンパイルおよび実行されることに注意してください。デバイスの armv6。

i386 arch の問題であると思われる癖は、おそらくデバイスに表示されることはありません。逆の場合も同様です。

于 2010-02-16T19:12:36.907 に答える