1. 程式人生 > >轉:iOS應用如何實現64位的支援

轉:iOS應用如何實現64位的支援

那們我們應該如何開始著手讓自己的App支援64-Bit呢?

基本知識

從iPhone 5S的A7 CPU開始到剛剛釋出的iPhone 6(A8 CPU)都已經支援64-bit ARM 架構。關於64-bit的介紹詳見維基百科。知乎上有很多關於蘋果使用A7,A8晶片的討論,可以參考 iPhone 6 的 Apple A8 晶片對比 Apple A7 提升明顯嗎?iPhone 5s 配備的 A7 處理器是 64 位,意味著什麼?

  • Xcode 5.0.1開始支援編譯32-bit和64-bit的Binary
  • 同時支援32-bit和64-bit,我們需要選擇的minimum deployment target為 iOS 5.1.1
  • 64-bit的Binary必須執行在支援64-bit的CPU上,並且最小的OS版本要求是 7.0.3

關於Xcode “Build Setting”中的Architectures引數問題

  • Architectures:你想支援的指令集。(支援指令集是通過編譯生成對應的二進位制資料包實現的,如果支援的指令集數目有多個,就會編譯出包含多個指令集程式碼的資料包,造成最終編譯的包很大。)
  • Valid architectures:即將編譯的指令集。(Valid architectures 和 Architecture兩個集合的交集為最終編譯生成的版本)
  • Build Active Architecture Only:是否只編譯當前裝置適用的指令集(如果這個引數設為YES,使用iPhone 6除錯,那麼最終生成的一個支援ARM64指令集的Binary。一般在DEBUG模式下設為YES,RELEASE設為NO)

關於指令集如下參考:

ARMv8/ARM64: iPhone 6(Plus), iPhone 5s, iPad Air(2), Retina iPad Mini(2,3)
ARMv7s: iPhone 5, iPhone 5c, iPad 4 
ARMv7: iPhone 3GS, iPhone 4, iPhone 4S, iPod 3G/4G/5G, iPad, iPad 2, iPad 3, iPad Mini   
ARMv6: iPhone, iPhone 3G, iPod 1G/2G

對於支援64-bit,我們可以設定Architectures為 Standard architectures

,在最新的Xcode 6上,它包括 armv7和arm64。

讓App支援32-bit和64-bit基本步驟

  • 確保Xcode版本號>=5.0.1
  • 更新project settings, minimum deployment target >= 5.1.1
  • 改變Architectures為 Standard architectures(include 64-bit)
  • 執行測試程式碼,解決編譯warnings and errors,對照本文件或者官方文件 64-Bit Transition Guide for Cocoa Touch對相應地方做出修改。(編譯器不能告訴我們一切)
  • 在真實的64-bit機器上測試
  • 使用Instruments檢視記憶體使用問題

64-bit主要的變化

64-bit執行時環境和32-bit執行時環境主要有以下兩點的不同:

  • 資料型別的改變
  • 方法呼叫上的改變

資料型別的改變

整型資料型別的變化如下:

浮點型型別的改變如下:

資料型別的改變可能會為我們的程式帶來這些影響:

  • 增加記憶體壓力
  • 64-bit到32-bit資料之間的相互轉化
  • 計算可能產生不同的結果
  • 當把一個值從大的資料型別拷貝到小的資料型別,資料可能被截斷。(NSInteger -> int)

方法呼叫上的改變

基於32-bit的CPU和基於64-bit上的CPU有不同數量的暫存器,在方法呼叫上有不同的協議。因此32-bit和64-bit在彙編層級上是不同的。如果我們在程式中不使用匯編程式設計,呼叫協議很少會遇到。

如何編寫健壯的64-bit程式碼

  • 不要將長整型long賦值給整型int (64-bit上會導致資料丟失)
  • 不要將指標型別pointer賦值給整型int (64-bit導致地址資料丟失)
  • 留意數值計算(掩碼計算,無符號整數和有符號整數同時使用等)
  • 留意對齊方法帶來的變化
  • 32-bit到64-bit之間資料轉化(通過網路傳遞的使用者資料,可能同時存在於32-bit和64-bit的環境下)
  • 重寫彙編程式碼
  • 不要在可變引數方法和不可變引數方法之前進行強制轉化

在LLVM編譯器中,列舉型別也可以定義列舉的大小。我們在使用中,指派列舉值到一個變數時,應該使用適當的資料型別。

不要將指標型別pointer賦值給整型int

int a = 5;
int *c = &a;

/* 32-bit下正常,64-bit下錯誤。最新的Xcode6.0編譯提示警告:'Cast to int* for smaller integer type int'*/
int *d = (int *)((int)c + 4); 

/* 正確, 指標可以直接增加*/
int *d = c + 1;

如果我們一定要把指標轉化為整型,可以把上述程式碼改為:

/* 32-bit和64-bit都正常。*/
int *d = (int *)((uintptr_t)c + 4);

檢視uintptr_t定義為 typedef unsigned long uintptr_t;

保持資料型別一致

方法使用時,入參,出參和賦值都需要注意保持資料型別一致。在iOS App中尤其要注意以下幾個型別的正確使用:

  • long
  • NSInteger
  • CFIndex
  • size_t

在32-bit和64-bit下,fpos_t和off_t都是64 bits的資料大小,永遠不要把它們指向int整型。

long PerformCalculation(void);
int c = PerformCalculation(); // 錯誤 64-bit上資料將被擷取
long y = PerformCalculation(); // 正確

int PerformAnotherCalculation(int input);
long i = LONG_MAX;
int x = PerformCalculation(i); // 錯誤

int ReturnMax()
{
    return LONG_MAX; // 錯誤
}

Cocoa中常見的資料型別轉化問題

NSInteger : 在32-bit和64-bit下有分別的定義:

#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
        typedef long NSInteger;
    #else
        typedef int NSInteger;
    #endif

我們永遠不應該假設NSInteger和int是一樣大的,下面的例子在使用中就需要注意:

  • 使用NSNumber物件轉化時
  • 使用NSCoder編解碼的時候,如果在64-bit裝置下對NSInteger編碼,在32-bit裝置下對NSInteger解碼。解碼時如果值的大小超過了32-bit,這個時候就會出現異常
  • Famework中使用NSInteger定義的一些常量

CGFloat: 和NSInteger一樣有不同的定義

typedef CGFLOAT_TYPE CGFloat;

#if defined(__LP64__) && __LP64__
# define CGFLOAT_TYPE double
#else
# define CGFLOAT_TYPE float
#endif

下面給出錯誤示範:

CGFloat value = 200.0;
CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &value); //64-bit下出現錯誤

CGFloat value = 200.0;
CFNumberCreate(kCFAllocatorDefault, kCFNumberCGFloatType, &value); //正確

整型數值計算問題

我們直接來看例子:

int a = -2;

    unsigned int b = 1;

    long c = a + b;

    long long d = c;

    printf("%lld\n", d);

問題:這段程式碼在32-bit下執行結果符合我們的預期,輸出為 -1(0xffffffff)。在64-bit下執行結果為:4294967295 (0x00000000ffffffff)。

原因:一個有符號的值和一個同樣精度的無符號的值相加結果是無符號的。這個無符號的結果被轉換到更高精度的數值上時採用零擴充套件。

解決方案:把變數b換成長整型long

建立資料結構時使用合適的資料大小

C99提供了內建的資料型別保證了一致的資料大小,即使底層的硬體結構不同。在某些case下,我們知道資料是一個固定的大小或者一個特定的變數擁有一個有限的取值範圍。這個時候,我們應該選擇特定的型別以避免浪費記憶體。

型別如下:

永遠不要使用malloc去為變數申請特定記憶體的大小,改為使用sizeof來獲取變數或者結構體的大小。

另外我們還需要注意修改格式化字串來同時支援32-bit和64-bit。

小心處理方法和方法指標

int fixedFunction(int a, int b);
int variadicFunction(int a, ...);

int main
{
    int value2 = fixedFunction(5,5);
    int value1 = variadicFunction(5,5);
}

上述兩個方法中,在32-bit下使用相同的指令讀取引數的資料,但是在64-bit上,是使用完全不同的協議來編譯的。

如果在程式碼中傳遞方法指標,應該保證方法呼叫的協議是一致的。永遠不要將一個可變引數的方法轉化成固定引數的方法。

int MyFunction(int a, int b, ...);

int (*action)(int, int, int) = (int (*)(int, int, int)) MyFunction;
action(1,2,3); // 錯誤示範

上述錯誤的寫法,編譯器是不會提示警告或者錯誤的,並且在模擬器中也不會暴露出問題來。在釋出自己的App前,一定記得要使用真機去測試。

總結

在支援64-bit過程中,應該按照Apple文件中提供的7個步驟完整檢查專案工程。如果工程中涉及到大量的C或者C++程式碼,在支援64-bit中要更加謹慎。

相關推薦

iOS應用如何實現64支援

那們我們應該如何開始著手讓自己的App支援64-Bit呢? 基本知識 從iPhone 5S的A7 CPU開始到剛剛釋出的iPhone 6(A8 CPU)都已經支援64-bit ARM 架構。關於64-bit的介紹詳見維基百科。知乎上有很多關於蘋果使用A7,A8晶片的討論,可以參考 iPhone 6

ios應用64問題,Missing 64-bit support

理方法如下:1、確保Xcode版本號>=5.0.12、更新project settings, minimum deployment target >= 5.1.13、Valid Architectures 新增設定 armv7 armv7s arm644、改變A

IOS應用如何實現64支援

那們我們應該如何開始著手讓自己的App支援64-Bit呢? 基本知識 從iPhone 5S的A7 CPU開始到剛剛釋出的iPhone 6(A8 CPU)都已經支援64-bit ARM 架構。關於64-bit的介紹詳見維基百科。知乎上有很多關於蘋果使用A7,A8晶片的

配置使安裝在64系統上的IIS7支援32應用程式

       在軟體開發領域,最重要的一點也是保持軟體業穩步推進的因素是:軟體的向下相容。這節我們討論如何配置IIS7,讓32位的Web應用程式在64位的系統上執行。1.開啟IIS,並在IIS上建立一個

IOS工程適配64-BIT 經驗分享

原文連結:http://www.oschina.net/question/1590538_220777 終究還是來了。Apple下發了支援64位的最後通牒: As we announced in October, beginning February 1, 2015

iOS與函數式編程

理解 返回 說過 沒有 可能 依賴 翻譯 外部 函數 函數式編程當中的函數f(x)強調無狀態,其實是強調將狀態鎖定在函數的內部,一個函數它不依賴於任何外部的狀態,只依賴於它的入參的值,一旦值確定,這個函數所返回的結果就是確定的。可能有人會覺得入參也是狀態,是外部傳入的狀態,

unigui應用64apache部署

時間 har readonly 報警 3-0 mea apache2 MF mdr 在64位apache下部署unigui的isapi模塊1. 建立一個unigui程序 2. 在程序中寫入簡單的內容 3. 增加64位程序編譯選項,在列表中選擇

iTOP-4412實現NFS網路檔案系統

[學習嵌入式開發板]iTOP-4412實現NFS網路檔案系統 <div class="extra ui horizontal list meta-wrap"> <div class="item">

快速判斷一個32的字中是否存在值為"0"的byte

http://www.spongeliu.com/421.html p { margin-bottom: 0.25cm; line-height: 120% } a:link { }   首先為什麼要做這樣的判斷呢? 當你要strcpy活著strcmp或者hash一個字串的時候,傳統的方法是

關於Win7 64Navicat無法連線64Oracle 11gR2Cannot load OCI DLL 87 解決方法

來自:http://douglas890116.blog.163.com/blog/static/9754590120146281041810/ 錯誤描述 在Win7下安裝了Oracle 11g R2,在用Navicat去連線Oracle時,提示以下錯誤: Cann

App Store 64支援遇到LUAJIT被忽略的問題

很遺憾,之所以2.2.6要加XXTEA,就是給你們說,這個問題LUAJIT自己如果沒有及時搞定,咱就怒用XXTEA吧。 zejian ju | 20 Nov 05:15 2014 Picon Re: Will luajit v2.1 support the arm64 a

iOS 工程 相容64 容易遇到的問題

tips: 相信目前大部分APP的工程框架已經是支援64bit,但是就在幾天前,遇到一個公司幾年前的框架,SQLCipher資料庫加密,AES加密,ASI網路請求,JSONKit,ZipArchive。。全是32bit,全打包成了.a靜態庫,我曹,如果讓工程支

ARM指令--adc 實現64加法運算

今天剛剛接觸到ARM指令,對於adc指令的理解,用adc指令實現64位的加法運算。 (1)adc指令:帶進位的加法 (2)基本思路:(r0,r1) = (r0,r1) + (r2, r3) 即高位與高位運算r0 = r0 + r2                  

termsrv.dll XP SP3 / Win7 32/64 支援多使用者遠端桌面連線 雙開3389

1. 下載破解的termsrv.dll 版本:5.1.2600.5512  2. 複製到C:\Windows\system32資料夾覆蓋同名檔案  3. 執行MultipleTS.bat檔案; 4. 執行Gpedit.msc開啟組策略,終端服務,限制連線數量改到2

EF多租戶例項如何快速實現和同時支援多個DbContext

前言 上一篇隨筆我們談到了多租戶模式,通過多租戶模式的演化的例子。大致歸納和總結了幾種模式的表現形式。 並且順帶提到了讀寫分離。 通過好幾次的程式碼調整,使得這個庫更加通用。今天我們聊聊怎麼通過該類庫快速接入多租戶。 類庫地址: https://github.com/woailibain/kiwiho.EFc

iOS 音訊錄製AMR和WAV互(支援64)

公司專案中涉及到語音錄製的功能,在錄音格式方面遇到一些小問題現在拿出來與大家分享一下。 眾所周知,iOS 音訊錄製是不支援AMR格式的。但 Android 好像是預設是AMR格式的。兩邊格式不同必然有一方做出妥協的。這裡只簡單介紹一下iOS 格式轉碼的方法。 1、音訊錄製簡介 在AVFoun

iOS音訊格式之AMR和WAV互(更新支援64)

---------------------------2016.6.15---------------------------------- ------- ---------------------------2015.8.25---------------------------------- --

Ubuntu16.04 64下安裝VMware Tools過程

因為在虛擬機器下安裝Ubuntu16.04 64位時無法進入全屏模式,採用另外一種方法解決了,但是還是想安裝一下VMware Tools,防止以後出現相關問題,好啦,下面進入正題。 1、在虛擬機器下會看到安裝 VMware Tools,單擊安裝。 2、在

3264 區別 CPU 作業系統 應用程式

https://www.cnblogs.com/mlgjb/p/8385658.html   原文連結 1.64位CPU與32位CPU 這兩者的指令集合、運算元位數、暫存器名稱和個數等等都不相同。 一、比如一條mov eax,1指令,可能在32bCPU上

字元碼開源庫libiconv目前還不支援64

最新版的libiconv 1.14目前還不支援64位系統,只能編譯出32位庫。libiconv 1.14下載地址:libiconv介紹:linux系統編譯安裝方法:$ ./configure --prefix=/usr/local $ make $ make install執