SSHFSをマウントするためのGUIユーティリティであるKeyChainと連携するObjective-Cのメモリ管理

私の記事の目的は、Objective-Cでメモリを操作する方法の最初のアイデアを読者に提供し、KeyChainでの作業について話し、数日で(合計で)書かれたSSHFSマウントアプリケーションの新しいバージョンを示すことです。面倒なMacfusion.appと競合しますこのファイルはファイルなしで機能し、パスワードをクリアテキストでシステムログに書き込みません。



メモリ管理



一般に、もちろん、Mac OS X 10.5以降では、ガベージコレクション(GC)のサポートが追加されたため、メモリ管理がはるかに簡単になりました。 したがって、プロジェクトでデフォルトで単純に有効にして、悪夢としてそれを忘れることができます。



画像



ただし、説明を注意深く読むと、次のように記述されます。「このアプリケーションによってリンクまたはロードされるすべてのObjective-Cコードは、GCにも対応している必要があります。」 つまり、GCサポートなしでコンパイルされたサードパーティのフレームワークを閉じた形式で使用する場合、それらを放棄するか、保持/リリースの形式で古いメモリ管理メカニズムを使用する必要があります。 また、 GCサポートはiPhoneでは使用できないため、アプリケーションをiPhone OS向けに作成することにした場合は、いずれにせよそれに直面する必要があります。



Objective-Cについての最初の知識がまだあると仮定します。たとえば、 このトピックはすでに読んでいます



Objective-Cは標準の参照カウントメカニズムを使用します。NSObject/ NSProxyの後継である作成されたすべてのオブジェクトには、作成後に1に設定される内部参照カウンターがあります。 オブジェクトの参照カウンターを増やすには、 retainを呼び出して、参照カウンター-releaseを減らす必要があります。 参照カウントが0に達すると、オブジェクトは解放されます。



NSString *someString = [[NSString alloc ] initWithFormat: @"usage: %s first-arg second-arg\n" , argv[0]]; // 1



// ... -



[someString release]; //






NSAutoreleasePoolと呼ばれる非常に便利なメカニズムがあります。これは、ほとんどの場合、NSAutoreleasePoolと呼ばれます。合意に従って、メソッドがオブジェクトへの参照を返し、キーワードalloccopyを含まない場合、参照カウンターは1に設定されます、ただし、イベントが完了した後、またはプールが手動で空になった後、その参照カウンターは自動的に1つ減らされます(リリースの代わりに自動解放メッセージを送信することにより、手動で選択したオブジェクトを自動解放プールに送信することもできます)。



NSString *someString = [NSString stringWithFormat: @"usage: %s first-arg second-arg\n" , argv[0]]; // 1, , retain ( release retain)



// ... -



// !








コードを別のスレッドで実行する場合は、このスレッドでNSAutoreleasePoolを手動で作成する必要があります。そうしないと、自動解放オブジェクトからのすべてのメモリがリークします(コンソールのエントリ数が膨大なため、簡単に推測できます)。



Xcodeには、メモリ操作のデバッグと分析のための優れたユーティリティがあります。たとえば、オプションBuild→Build and Analyzeを選択する 、Clang静的アナライザーによってコードが分析され、メモリを管理する際の一般的なエラーが通知されます(だけでなく)。 また、リークを検出するためにアプリケーションを実行することもできます。そのためには、プロジェクトで[ 実行]→[パフォーマンスツールで実行]→[リーク]を実行します。 アプリケーションのプロセスでメモリリークを監視し、Objective-Cコードだけでなく、通常のC(malloc / freeを使用)、および閉じたフレームワーク(Appleを含む)でもリークを見つけることができます!



キーチェーンを使用する



キーチェーンを操作するための関数は非常に低レベルで(ユーザーインターフェイスで動作するほとんどのフレームワークとは異なり)、CでAPIを使用します。Appleのドキュメントには、キーチェーンサービスサブシステムサポートされるすべての呼び出しに関する非常に包括的なガイドがありますが 、シンプルで基本的なことができることを示します。



C呼び出しを使用する場合、Appleは主にCoreFoundationを使用します。 CoreFoundationは、Cocoaフレームワークを備えたObjective-Cで使用されるのと実質的に同じデータ型を使用およびサポートし、CoreFoundation <-> Cocoaの透過的なキャストもサポートします。 CoreFoundationへのすべての呼び出しはCFで始まり(NSと比較)、型名はNSをCFで置き換え、最後にアスタリスク[*]を接尾辞Ref (参照、参照)で取得します(たとえば、NSString * <-> CFStringRef、NSArray * <-> CFArrayRef)。 メモリを操作するには、CFRelease( CFTypeRef )/ CFRetain( CFTypeRef )を使用します。この目的と使用方法は、自分で推測できます。



そのため、キーチェーンを開始するには、いくつかのヘッダーを追加し、 Security.frameworkフレームワークを接続する必要があります。



#import <CoreFoundation/CoreFoundation.h>

#import <Security/Security.h>






アプリケーションのインターネットパスワードをデフォルトのキーチェーンに追加するには、 SecKeychainAddInternetPassword呼び出しを使用します。 彼には多くの議論があり、そのほとんどはオプションです。 使用例を次に示します。



const char *serverName = "habrahabr.ru" ;

int serverNameLength = strlen(serverName);



const char *accountName = "youROCK" ;

int accountNameLength = strlen(accountName);



char *path = "/" ;

int pathLength = strlen(path);



int port = 22;



const char *passwordData = "myExtremelySecretPassword" ;

int passwordLength = strlen(passwordData);



/* , ( SSH :)), . , */



SecKeychainAddInternetPassword(NULL, serverNameLength, serverName, 0, NULL, accountNameLength, accountName, pathLength, path, port, kSecProtocolTypeSSH, kSecAuthenticationTypeDefault, passwordLength, passwordData, NULL);




* This source code was highlighted with Source Code Highlighter .








キーチェーンからインターネットパスワードを取得するには、 SecKeychainFindInternetPassword呼び出しを使用します。以下に例を示します。



const char *serverName = "habrahabr.ru" ;

int serverNameLength = strlen(serverName);



const char *accountName = "youROCK" ;

int accountNameLength = strlen(accountName);



char *path = "/" ;

int pathLength = strlen(path);



int port = 22;



UInt32 passwordLength;

void *passwordData;



OSStatus retVal;



if ( (retVal = SecKeychainFindInternetPassword(NULL, serverNameLength, serverName, 0, NULL, accountNameLength, accountName, pathLength, path, port, kSecProtocolTypeSSH, kSecAuthenticationTypeDefault, &passwordLength, &passwordData, NULL)) == 0)

{

// , passwordData (void *) ,

// ,

NSString *passValue = [[NSString alloc] initWithBytes:passwordData length:passwordLength encoding:NSUTF8StringEncoding];



// ,



SecKeychainItemFreeContent(NULL, passwordData);

[passValue release];

} else

{

// 2 — -, copy,

// — (NSString*), NSString CFStringRef



CFStringRef reason = SecCopyErrorMessageString(retVal, NULL);

NSLog( @"Could not fetch info from KeyChain, recieved code %d with following explanation: %@" , retVal, (NSString*) reason);

CFRelease(reason);

}




* This source code was highlighted with Source Code Highlighter .








このコードがどのOSで実行されるか想像できなかったため、Mac OS XとiPhoneOSの両方で動作します(さらに、iPhoneOSでは、アプリケーションからキーチェーンにアクセスするためにユーザーの確認は必要ありません)。



SSHFSを使用してSSH経由でボリュームをマウントするGUIユーティリティ



HabréでSSHFSとGUIを使用してリモートFSに接続できるユーティリティについて繰り返し書いていますが、最終的には使用できる状態にまで成長したことを報告したいと思います。





MacFUSEpqrs.orgユーティリティを使用して、リモートファイルシステムをマウントできます。 最近のサーバーのリスト、sshユーティリティへの安全なパスワード転送(私の特別な誇り:)) 、キーチェーンでのパスワードのオプションストレージ、圧縮サポートがあります。 MacFusion.appと比較すると、確かに機能は少なくなりますが、使いやすく、コードベースは11(!)回小さく(28 Kb対318 Kb)、開始時にキーチェーンから大量のリクエストをスローせず、起動する必要がありません個々の悪魔など また、ExpanDriveと比較して、無料でオープンソースです。

PSこれは私の8番目のhabratopikです。あまり蹴らないでください。



All Articles