2011-06-27 423 views
0

我正在將C庫集成到iOS的Objective-C應用程序中。我不是非常聰明的人......我只知道危險。忽略C函數中的參數

C函數的聲明是這樣的:

extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, 
         unz_file_info *pfile_info, 
         char *szFileName, 
         uLong fileNameBufferSize, 
         void *extraField, 
         uLong extraFieldBufferSize, 
         char *szComment, 
         uLong commentBufferSize)); 

我真的只在szFileName感興趣。我知道我可以通過NULL忽略void*char*。我可以通過某種NULL - 等效於uLong params嗎?我收到了一個編譯器警告,關於轉換爲沒有強制轉換的指針。

這是我的循環調用這個函數,以防有人想對此發表評論。我是否正確地做了malloc/free?我不習慣低級C的東西。我知道人們抱怨Objective-C的引用計數但相比之下它很豪華:)

unz_file_info pfile_info; 
char *szFileName = malloc(1024); 
uLong fileNameBufferSize; 
uLong commentBufferSize; 
uLong extraFieldBufferSize; 

do { 
    int ret = unzGetCurrentFileInfo(zipFile, &pfile_info, szFileName, fileNameBufferSize, NULL, extraFieldBufferSize, NULL, commentBufferSize); 
    NSLog(@"get info ret %i filename size %lu, filename %s", ret, pfile_info.size_filename, szFileName); 
    // do other stuff here with the filename 
} 
while (unzGoToNextFile(zipFile) == UNZ_OK); 
free(szFileName); 

回答

1

了ulong參數的緩衝參數的大小。這是因爲函數知道這些緩衝區有多大,所以它不會溢出。

如果您需要的文件名參數,你必須提供一個正確的fileNameBufferSize。

至於是否實際上,你可以在一個空指針傳遞到指針參數,只有文件(或源代碼),此功能可以告訴你。或者,如果文檔不告訴你,你就必須做在功能上的一些基本的科學實驗,看看它是如何工作。

假設該函數接受NULL指針,您不想填寫參數,您可能會傳遞0作爲ulong參數的值。

你必須做的:

unz_file_info pfile_info; 
char *szFileName = malloc(1024); 
uLong fileNameBufferSize = 1024; 
if(szFileName == NULL) { 
    //handle error 
    return; 
} 

do { 
    int ret = unzGetCurrentFileInfo(zipFile, &pfile_info, szFileName, fileNameBufferSize, NULL, 0, NULL, 0); 
    NSLog(@"get info ret %i filename size %lu, filename %s", ret, pfile_info.size_filename, szFileName); 
    // do other stuff here with the filename 
} 
while (unzGoToNextFile(zipFile) == UNZ_OK); 
free(szFileName); 

你也應該調查unzGetCurrentFileInfo的返回值的含義。如果失敗,則不太可能使用szFileName或函數的其他任何參數 - 因此,如果函數失敗,請不要使用這些變量調用NSLog

在這種情況下,malloc似乎不是必需的。只需使用本地數組,然後刪除free()調用即可。

char szFileName[1024]; 
uLong fileNameBufferSize = sizeof szFileName; 
+0

哦,優良的...我誤解了什麼fileNameBufferLength東西是,我還以爲是要與文件名的長度填寫,我不知道我說的是功能有多大的我分配的緩衝區! (這似乎怪我,因爲如果我分配一個太小的緩衝?我猜的功能它只是截斷結果,但是這似乎是一個愚蠢的事。) – jsd

+0

截斷結果可能看起來像一個愚蠢的事情這樣做,但功能沒有選擇。如果它想寫100個字節,但你給它一個只有80個字節的緩衝區,它不能再寫入額外的20個字節,否則它會覆蓋內存,並帶來潛在的災難性後果。沒有什麼可以做_except_截斷字符串。 –

0

我可以通過某種 NULL,相當於ULONG則params的?

0怎麼樣?

我是否正確地做了malloc/free

對我來說還可以。

雖然有一些其他錯誤:fileNameBufferSize應該是szFileName緩衝區的大小(在您的代碼中爲1024)。你沒有填滿它,這意味着它是垃圾,要小心。

編輯

是的,你應該檢查是否爲NULL的malloc返回值,忘了提及。

5

我可以通過某種NULL換算到ULONG PARAMS?我收到了一個編譯器警告,關於轉換爲沒有強制轉換的指針。

不一般;參數的允許值應該在你所嵌入的庫的手冊中列出(zlib,喜歡它)。不要將NULL傳遞給期望long的函數,這是無效的。

更糟的是:你逝去的未初始化的變量fileNameBufferSizeextraFieldBufferSizecommentBufferSize給函數的值。你的程序有未定義的行爲。適當地設置這些變量,或者爲參數使用文字/表達式。

我是否正確地做了malloc/free

你忘了從malloc檢查返回值。總是檢查NULL。更妙的是:因爲你分配的內存恆定的量,只是這樣做的堆棧:

char szFileName[1024]; 

無需mallocfree(你可能想使用PATH_MAX,而不是任意的1024,如果有什麼路徑名可能長於你的平臺上?)

編輯:從不介意的PATH_MAX部分;最大。這個字符串的長度應該記錄在zlib文檔中,因爲它不是最大值。系統中某個部件的長度,但最大值長度zlib願意存儲。

1

我可以通過某種NULL,相當於ULONG則params的?

對於非指針參數沒有全局接受的NULL;它取決於功能。在某些情況下,您可以傳入0,但並非總是如此。

在這種情況下,你傳遞一個緩衝區的大小和緩衝區提供NULL,所以它似乎是合乎邏輯的傳球0是正確的。

0

我會在這裏做一些這方面的工作。我刪除了未使用的變量,而不是malloc/free,堆棧中的簡單分配將會執行。

#define FNAME_SZ 1024 //should really read the docs on your target platform to find the proper size 
unz_file_info pfile_info; 
char szFileName[FNAME_SZ]; 

//initialize. important just to be sure 
memset(szFileName, 0, FNAME_SZ); 

do { 
    int ret = unzGetCurrentFileInfo(zipFile, &pfile_info, szFileName, FNAME_SZ, NULL, 0, NULL, 0); 
    NSLog(@"get info ret %i filename size %lu, filename %s", ret, pfile_info.size_filename, szFileName); 
    // do other stuff here with the filename 
} 
while (unzGoToNextFile(zipFile) == UNZ_OK);