[C][RUST][Python][Go]關於vector的push_back造成的記憶體參考(reference)問題

image

前言:

很基本的概念,是從RUST官方網頁在介紹他的記憶體管理的部分看到的.覺得是很有趣的vector與記憶體處理的問題,由於RUST有比對它的程式語言設計架構,於是很好奇地把其他手邊常用的程式語言找了一下相關的範例.

主要問題(C/C++/ObjectC)

  • 主要是講解,說在vector裡面的記憶體管理其實有一些技巧.尤其是在push_back的部分,每次的push_back如果目前的大小超過他的容量,就會放棄目前的記憶體位址,而去建立一個新的vector記憶體.而原本的記憶體位置就沒使用變成了garbage.
  • 如此一來會造成原本去參考v[0]的記憶體位置變成了garbage,而會crash.
  • 這邊可以參考vector的push_back說明.
  • 這裏在ObjectC與C/C++結果不同,他不會crash但是會沒值.(ObjectC原本設定概念)
  • 在C/C++/ObjectC解決方式:
    • 其實只要先把記憶體保留起來,就可以解決這樣的問題. vector.reserve(specific_size);
  
#include 
#include 
#include 

int main(int argc, const char * argv[]) {
    //Init new vector here
    std::vector<std::string> v;
    //v.reserve(128); could resolve this issue, 128 is arbitrarily value.
    
    //Put first element "hello" v: "Hello"
    v.push_back("Hello");
    // x refer to v[0] which is "Hello"
    std::string& x = v[0];
    
    //Push new element but size will over capacity (default is zero, after first push become 1)
    //So whole memory will deprence and create new memory size =2
    //Refer to http://en.cppreference.com/w/cpp/container/vector/push_back
    v.push_back("world");
    
    // Old reference memory aleady become to garbage, so app crash (depends OS)
    std::cout << x;    
    return 0;
}
</pre>

**在RUST方面**
    
- 根據[RUST官方網頁](http://www.rust-lang.org/)在介紹他的記憶體的管理方面,由於它定義兩種資料結構mutable 跟 let (這裏跟swift有點像).所以根據以下的程式碼,會造成編譯的時候不成功.

  
fn main() {
    let mut v = vec![];
    v.push("Hello");
    //let x = &v[0];  Cannnot compile. because the mutable variable cannot assign to static value.
    let x = v[0].clone();
    v.push("world");
    println!("{}", x);
}
**在Python的部分** - 沒有找到比較像vector的資料結構,我使用list來使用.我也有用codeskulptor來查看[視覺化(Viz mode)](http://www.codeskulptor.org/viz/index.html)的結果. - 在python內有分成兩種方式來參照(reference),如果你參照的是unmutable通常是使用copy,如果是參照mutable就會使用bind.而且整個list變大也不會影響參照的變數. - 這邊主要是python varaible assignment比較不一樣,有比較多的討論可以看: - [How do I write a function with output parameters (call by reference)?](https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference) - [[stackoverflow]How do I pass a variable by reference?](http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference) - 以下一段原文quote很值得了解: - "the parameter passed in is actually a reference to an object (but the reference is passed by value)" - ""some data types are mutable, but others aren't"
  

# Example in assign to first.
list_a = list()
list_a.append("hello")
item_b = list_a[0]   #copy value list_a first element to item_b, not point to.
list_a.append("world")
print item_b  #hello

# Example in bind to whole list.
list_a = list()
list_a.append("hello")
item_b = list_a    #item_b bind to list_a
list_a.append("world")   #in codeskulptor memory not relocate nd continue.
print item_b       #still "hello"

[iOS][Python][unix][golang][程式設計週記] 工作上的一些雜事筆記20141219

前言:

在上完一個禮拜的Intel課程後,本週可以在辦公室專心做事情.可以專心的好好的把工作進度來超前一下.加上coursera的課程都上完了,應該可以有更多的時間可以好好的看看. 本週重點是學習iOS HealthKit 跟 etcd,當然還是有工作上管理伺服器的一些事情…..

筆記:

  • [Unix] 如何增加一個客製化的服務(custom service)
    • 前言:
      • 新增一些伺服器,所以要把舊的伺服器上面的一些服務搬過來.
    • 流程:
      • 複製相關的shell script 到 /etc/default 與 /etc/init.d
        • 這裡要注意,透過windows檔案複製的話會出現”/bin/sh^M : bad interpreter”,解決方式可以參考這裡
        • 要使用dos2unix 去轉換這些script
      • 增加一些設定檔script到 /etc
      • 記得用”initctl reload-configuration”把這些services重讀,參考這裡
  • [iOS] 關於錯誤“Capturing [an object] strongly in this block is likely to lead to a retain cycle”
    • 前言:
      • 因為HealthKit都在搞Async process所以經常在GCD的過程中去使用原先的self process,所以容易產生這個問題.
    • 原因:
      • 根據stackoverflow上面的解釋,主要原因是因為block會保留一份在裡面,如果保留的是self就會造成循環的持有.
    • 解決方式:
      • 加上以下的部分就可以了
__weak typeof(self) weakSelf = self;

[someprocess setCompletionBlockWithSuccess:^(Operation *operation) {
    [weakSelf someOperationInSelf];

} 
  • [iOS] 關於IPWORKS整合
    • 前言:
      • 公司在用的3rd party component,不過每次整合都會忘記,紀錄一下.
    • 步驟:
      • copy IPWORKs, libSSL
      • Add related framework:
        • libz.dylib
        • libssl.a
        • libcrypto.a
      • Add “Preprocessor Macros” in debug
        • IPWORKS_MINSIZE
        • INCLUDE_IPWORKS_XMPP
      • Change “C++ compiler setting in Apple LLVM 6.0 - Language ++”
        • C++ Language Dialect -> Compiler default.
        • Standard Library -> Compiler default.
  • [Go] 準備好好研究一下etcd
    • 前言:
      • 主要起因是因為這個一月份的Golang聚會,裡面有提到etcd很適合作為IOT(Internet Of Thing)的資料庫,所以打算開始survey.看看是不是真的能讓速度快一點.
    • 筆記:
      • 基本上etcd是一個相當快速的key pairing 資料庫,可以透過http直接存取.
      • 其實發現etcd有以下的幾個優點:
        • 可以透過http來讀取與存取. (讀取直接打網址,存可以用Put跟Post)
        • 雖然是Key Pairing Database,但是還是存有index.所以可以記錄之前的資料.也可以透過wait=true達到key-value observing的效果.
    • 參考:
  • [iOS] 關於HealthKit的筆記
    • 玩HealthKit到現在,其實有點困難必須得承認就是對於單位與測量數值的標準化.
    • 簡單的說:
      • 你想要量個血壓,你就得知道你要量血壓單位名稱.還有血壓數值一般轉換的方式.
    • 舉例而言:
      • 你現在需要量血壓,血壓有兩種數值收縮壓(Diastolic)與舒張壓(Systolic),這時候你需要知道以下一些東西:
        • 舒張壓的資料型態(Type)是 HKQuantityTypeIdentifierBloodPressureDiastolic
          • HKQuantityType *DiastolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureDiastolic];
        • 舒張壓的單位是(millimeter Of Mercury)
          • HKUnit *DISUnit = [HKUnit millimeterOfMercuryUnit];
        • 接下來,還有取得資料的格式與data formaater的翻譯還沒有.
      • 應該會把這個部分整理一下,變成一篇教學.畢竟網路上教學算很少的.
    • 參考:
  • [Unix] 如何在crontab 裡面加入啟動系統服務的程式碼
    • 問題:
      • 想要從crontab裡面透過shell script去啟動背景服務,但是都會發生啟動失敗.
    • 原因與解決方法:
      • 權限的問題,原本在script裡面直接使用
        • service back_server_foo start
      • 發現會失敗,於是改成
        • root service back_server_foo start
      • 如此一來不會有失敗的訊息,但是還是無法正確的啟動.必須要改成
        • sudo /etc/init.d/ back_server_foo start
      • 這樣才會正確地執行成功.
  • [C++] 關於C++回傳char*的討論與挑錯
  • [Unix]針對SIGPIPE的繼續研究

[iOS] HealthKit的初體驗..

image

前言:

最近開始仔細瞭解HealthKit,發現使用上並沒有那麼的直覺.(可能是我對於許多醫療單位沒有那麼清楚的關係 XD) 使用上有一些要注意的與需要瞭解的部分,稍微做一些紀錄.

筆記:

[基本概念]

  • 到目前為止,HealthKit只有iPhone可以用,並且要有iOS8.所以iPad執行程式會失敗.
  • 每一個資料有所屬的資料格式數量(HKQuantity)與該數量的格式(HKQuantityType),而數量(Quantity)本身與單位的格式(HKUnit)有關.
  • 必須要清楚地瞭解,存取的資料數量單位與單位的格式.
    • 比如說,身高要確認是用cm還是inch,體重是使用pound還是kg.
  • 每一個存取都與使用者權限有關,去拿使用者不開放的資料,就會引發錯誤.
  • 所有的動作都是Async的方式:
    • 這邊比較麻煩的是,如果需要抽象化的話可能要把async改成sync這邊可以參考這邊的內容

[基本資料欄位]

  • 關於資料欄位舉例而言,要敘述關於血壓的舒張壓,你就得要撰寫以下的部分:
    //敘述你的血壓單位是 mmag mullumeter of mercyry unit
    HKUnit *BPUnit = [HKUnit millimeterOfMercuryUnit];
    //透過這個HKUnit去建立單位 HKQuantity 
    HKQuantity *BPSystolicQuantity = [HKQuantity quantityWithUnit:BPUnit doubleValue:SIS];
    // 透過建立的單位與數值來建立這個單位類型(HKQuantityType)
    HKQuantityType *BPSystolicType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBloodPressureSystolic];

[取得使用者權限]

  • 上面的方式僅僅是拿來作為處理資料欄位而已,接下來要開始去跟HealthKit查詢資料.在查詢資料之前,由於HealthKit上的資料都是儲存在手機上面,屬於個人私密資料.需要取得使用者的權限.
    //取出體重單位格式
    HKQuantityType *weightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
    //取出身高單位格式
    HKQuantityType *heightType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
    // 將身高體重加入要求的權限集合,這裡有分"讀取"與"寫入"的集合
    NSSet *writeDataTypes = [NSSet setWithObjects:heightType, weightType, nil];
    NSSet *readDataTypes = [NSSet setWithObjects:heightType, weightType, nil];

    // 確認HealthKit 存不存在,這裡如果還是iPad 是不會有的,請注意.
    if ([HKHealthStore isHealthDataAvailable]) {        
        // 要求使用者同意
        [self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
            if (!success) {
                NSLog(@"You didn't allow HealthKit to access these read/write data types. In your app, try to handle this error gracefully when a user decides not to provide access. The error was: %@. If you're using a simulator, try it on a device.", error);
                
                return;
            }
            
            //處理成功以後,可能需要的資料讀取部分.
        }];
    }

[讀取資料]

  • 關於讀取資料這邊,需要注意的就是必須要取得正確的單位.
  • 還是一樣,讀到資料以後是async,所以可以用另外的thread來更新UI
  • 以下提供取得”心跳(Heart Rate)”的方式
    //心跳屬於複合資料欄位,需要用字串來找到HKUnit.文件不好找到.
    HKUnit *dataUnit = [HKUnit unitFromString:@"count/min"];
    
    //取得心跳的單位
    HKQuantity *HRQuantity = [HKQuantity quantityWithUnit:dataUnit doubleValue:heartRate];
    
    //取得心跳單位格式,注意HKQuantityTypeIdentifierHeartRate
    HKQuantityType *HeartRateType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];

    //建立資料回傳的sort敘述    
    NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate ascending:NO];

    //建立查詢的指令,注意因為我們只需要最近的所以把limit設定成1
    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:HeartRateType predicate:nil limit:1 sortDescriptors:@[timeSortDescriptor] resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
        if (!results) {
            //錯誤發生            
            return;
        }
        
        //取得心跳資料
        double usersHR = [mostRecentQuantity doubleValueForUnit:dataUnit];
    }];
    
    //執行查詢的指令
    [self.healthStore executeQuery:query];

[寫入資料]

  • 其實跟讀取一樣,主要也是要把HKUnit,HKQuantity與HKQuantityType搞定.
  • 這邊需要注意的是,儲存的資料都是有時間格式的.你必須要設定開始時間與結束時間.

    //建立心跳的單位
    HKUnit *dataUnit = [HKUnit unitFromString:@"count/min"];

    //建立心跳的數量單位
    HKQuantity *HRQuantity = [HKQuantity quantityWithUnit:dataUnit doubleValue:heartRate];

    //建立心跳的單位格式  
    HKQuantityType *HRType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeartRate];
    NSDate *now = [NSDate date];

    //建立數量取樣
    HKQuantitySample *HRSample = [HKQuantitySample quantitySampleWithType:HRType                                                                          
                                                   quantity:HRQuantity                                                                         
                                                   startDate:now                                                                           
                                                   endDate:now];
    
    //存取該資料
    [self.healthStore saveObject:HRSample withCompletion:^(BOOL success, NSError *error) {
        if (!success) {
            NSLog(@"An error occured saving the sample %@. In your app, try to handle this gracefully. The error was: %@.", dataQuantityType, error);
            abort();
        }
        
        // 成功了之後,可以去更新資料.
        [self some_UI_update];
    }];

[iOS][Android][Python]工作上的一些雜事筆記20141212

前言:

本週都在Intel上課,大部份內容屬於NDA.只能找空閒時間看看其他的部分.

筆記:

  • [Mac OSX]一些常用的工具
    • 想要尋找Mac上面類似pietty一樣好用的軟體,卻忘記terminal 本身就有一樣的功能.更何況我有裝iTerm2
      • [指令] ssh -l username -p portnumber host
      • 參考:
    • 除了想要尋找類似pietty一樣的軟體外,也想要尋找可以一次完成SSH跟SFTP的軟體
      • Fugu 就是我想找的.
  • [Android][iOS] PhoneGap Beta Release
  • [Android] Android Studio 1.0 official release
  • [iOS] Parse支援Crash Log,可以考慮要不要加進去自己的App.不過我App用的是Parse 1.2.19現在已經到1.6了.
  • [IaaS][PaaS] 在Azure上面架設VM(Virtual Machine)很方便.但是對外的port要透過設定不然預設都是關閉的.這件事情讓我很困擾.
    • 問題:
      • 建立了伺服器與服務,但是對外都無法找到相對應的服務
      • 內部自己用curl或是其他client app可以找到相對應的服務
    • 解決方式:
      • 在Endpoint得加入你要開放給外面的port
      • 甚至可以做一個簡單的port 修改,比如說把xmpp 從5222改到80,裡面的80 Apache改到8080
    • 此外,現在Azure是有Preview的Manager Dashboard,東西有變多了.

[MH4G][MonsterHunter4G]雙刀畢業考心得(師匠からの試練)

第一次打給我驚險在最後八秒過了。

可以關柵欄覺得比較容易。

極限很機車、雙劍刷腳很快倒。如果有極限強化可以更快

[iOS][Android][Python]工作上的一些雜事筆記20141205

前言:

本週工作依舊五花八門,下週要去Intel上課.要看看能寫多少出來.

筆記:

  • [MSFT] 關於Visual Studio 2013 upate 4更新過後,整個編輯器變慢.
    • 新增的功能會預設把git當作他的source control plugin這樣會有一些問題.
    • 問題:
      • 更新VS2013 update4 之後,編輯器變慢.尤其是開啟檔案與關閉檔案的時候.
    • 原因:
      • VS2013 source control plugin 會讀取該目錄git的資料,並且加入自已的source control plugin.
      • 如果你已經有用到其他的source control system,可能會造成衝突而變慢.
    • 解決方法:
      • 也不算正式解決方法,只是先關閉這個plugin.可以幫助整體效能的提升.
      • Option -> Source Control -> Plug-in Selection -> Current Source control plugin -> None.
    • 參考:
  • [iOS] 關於這週的一些小修改
    • 有些App需要在背景的時候強制重啟,以確保連線狀態(尤其是xmpp).對於類似的App設計,可能可以考慮強制不要App進入背景模式.
    • 關於dispatch_async(dispatch_get_main_queue() 大家都會用它來把工作移到別的thread
      • 但是其實他也是有照順序的,所以如果你依照順序跑三次,他就會依序跑那些你指定的指令.
      • 用法上對於需要等待回應的程式,其實相當的方便.
    • 關於NSUserDefaults的預設值總是會錯~如果第一次安裝App
      • 錯誤狀況:
        • 第一次安裝App後,讀取NSUserDefaults會無法讀到預設為True的值()或是其他預設值)
      • 解決方式:
        • 原因是因為你沒有把plist的數值去註冊,這邊有兩種方式可以選擇.
        • 第一種: 讀取數值不要用boolValue 而用NSNumber接起來~然後判斷是不是nil
        • 第二種: 執行NSUserDefaults registerDefaults把預設值先讀進App
      • 參考資料:
    • XCode更新了6.1.1:
      • 很希望他有把IDE穩定性修好,不過有看到一個特別的詞 (SourceKit),去查了一下原來SourceKit是用來給swift作為Source code parser,Syntax highlighter 還有cross-language header generator…
      • 這裏有詳細的解釋: http://www.jpsim.com/uncovering-sourcekit/
  • [Android] Android Studio 1.0RC版本出來,有些地方要注意:
  • [Linux][Ubuntu][Python] 手工打造process watcher and recovery
    • 遇到的問題:
      • 工作上遇到的問題主要是有管一些雲端服務,自然要監測這幾個service的狀況.如果遇到service出錯必須要有自動的回覆機制.
    • 解決方式:
      • 原本是透過Python寫一個透過grep來找特定的service的方式,這裡有程式碼
      • 不過研究過後,或許採取pidof的方式是不容易重複的方式.也改寫成shell script. 參考這裡
      • 這篇討論很值得思考,偵測process要考慮會不會產生額外的資源消耗.