2011-06-27 526 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);