malloc()
,但我不想让用户在使用我的函数返回值后负责调用 free()
。如何实现这一点?其他返回字符串(
char *
)的函数是如何工作的(例如 getcwd()
、_getcwd()
、GetLastError()
、SDL_GetError()
)?free()
发生)。free()
(例如查看strdup
用户工作方式)或调用您提供的包装free
的函数来释放分配的内存。例如,您可能要求调用者调用foo_destroy
函数。正如另一篇文章所指出的那样,您可以选择将其封装在不透明的struct
中,但这并不是必需的,因为即使没有它(例如用于资源跟踪),拥有自己的分配和销毁函数也很有用。apache2
与其apr_pool
结构一起工作的方式。通常情况下,在该模型下,您不会特别地free()
任何东西。请参见此处和(更易于阅读的)此处。char *
变量:strdup
、get_current_dir_name
和某些情况下的getcwd
)期望调用者进行释放。strerror_r
和其他情况下的getcwd
)期望调用者传入足够大小的缓冲区。getcwd
手册页中:getcwd()
使用malloc(3)
动态分配缓冲区,如果buf
为NULL
。在这种情况下,分配的缓冲区具有长度size
,除非size
为零,此时buf
分配为必要的大小。调用者应该free(3)
返回的缓冲区。
有些函数使用内部静态缓冲区,因此不可重入/线程安全(糟糕 - 不要这样做)。参见 strerror
以及为什么发明了 strerror_r
。
有些函数仅返回常量指针(因此可重入),无需释放。
有些函数(如 libxml
)需要使用单独的 free
函数(在本例中是 xmlFree()
)
有些函数(如 apr_palloc
)依赖于上述池技术。
在C语言中没有办法做到这一点。您必须传递一个带有大小信息的参数,以便可以在被调用的函数中调用malloc()
和free()
,或者调用函数必须在调用malloc()
后调用free()
。
许多面向对象的语言(例如C ++)以这种方式处理内存,以实现您想要的功能,但C语言不支持。
编辑
通过大小信息作为参数,我指的是让被调用的函数知道您正在传递的指针拥有多少字节的内存。如果字符串已经被分配了一个值,可以通过直接查看被调用的字符串来完成这个操作,例如:
char test1[]="this is a test";
char *test2="this is a test";
readString(test1); // (or test2)
char * readString(char *abc)
{
int len = strlen(abc);
return abc;
}
这两个参数都会导致 len
= 14
但是如果您创建一个未填充的变量,例如:
char *test3;
test3 = malloc(strlen("this is a test") +1);
被调用的函数无法知道已分配了哪些内存。在 readString()
的第一个原型中,变量 len
会等于 0。但是,如果你将 readString()
的原型更改为:
readString(char *abc, int sizeString); Then size information as an argument can be used to create memory:
void readString(char *abc, size_t sizeString)
{
char *in;
in = malloc(sizeString +1);
//do something with it
//then free it
free(in);
}
int main()
{
int len;
char *test3;
len = strlen("this is a test") +1; //allow for '\0'
readString(test3, len);
// more code
return 0;
}
for (a lot of iterations)
{
params = get_totally_different_params();
char *str = your_function(params);
do_something(str);
// now we're done with this str forever
}
malloc
分配字符串,那么它将浪费大量调用 malloc
的工作,而且如果 malloc
每次选择不同的块,则可能会显示出较差的缓存行为。根据您的库的具体情况,您可以像这样做:int output_size(/*params*/);
void func(/*params*/, char *destination);
其中destination
的大小必须至少为output_size(params)
,或者您可以像socket recv
API一样执行其他操作:
int func(/*params*/, char *destination, int destination_size);
返回值为:
< desination_size: this is the number of bytes we actually used
== destination_size: there may be more bytes waiting to output
你可以将它包装在一个不透明的结构体中。
让用户可以访问到指向你的结构体的指针,但不能访问其内部。创建一个释放资源的函数。
void release_resources(struct opaque *ptr);
当然用户需要调用该函数。
你可以跟踪已分配的字符串,并在 atexit 程序中释放它们(http://www.tutorialspoint.com/c_standard_library/c_function_atexit.htm)。在下面的示例中,我使用了一个全局变量,但如果你有一个简单的数组或列表,也可以使用它。
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
char* freeme = NULL;
void AStringRelease(void)
{
if (freeme != NULL)
free(freeme);
}
char* AStringGet(void)
{
freeme = malloc(20);
strcpy(result, "A String");
atexit(AStringRelease);
return freeme;
}
在 C 语言中无法做到这一点。
返回一个指针,由调用函数的人来调用 free
。
或者使用 C++。例如 shared_ptr
等。
char*
,不需要释放它。 - cdontsgetcwd
取决于调用约定。我的 Linux 开发机器没有其他函数的 man 页面,但我相信 API 的适当文档将存在。 - abligh