返回分配给malloc的字符串?
我正在创建一个返回字符串的函数。字符串的大小在运行时是已知的,因此我计划使用返回分配给malloc的字符串?,c,malloc,C,Malloc,我正在创建一个返回字符串的函数。字符串的大小在运行时是已知的,因此我计划使用malloc(),但我不想让用户负责在使用函数的返回值后调用free() 如何做到这一点?其他返回字符串(char*)的函数(例如getcwd(),\u getcwd(),GetLastError(),SDL\u GetError())是如何工作的?在C中不能这样做 返回一个指针,由调用函数的人调用free 可选地使用C++。code>shared_ptretc您可以将其包装在不透明结构中 允许用户访问指向结构的指针,但
malloc()
,但我不想让用户负责在使用函数的返回值后调用free()
如何做到这一点?其他返回字符串(
char*
)的函数(例如getcwd()
,\u getcwd()
,GetLastError()
,SDL\u GetError()
)是如何工作的?在C中不能这样做
返回一个指针,由调用函数的人调用free
可选地使用C++。code>shared_ptretc
您可以将其包装在不透明结构中 允许用户访问指向结构的指针,但不能访问其内部指针。创建一个函数来释放资源void release_resources(struct opaque *ptr);
当然,用户需要调用该函数。在C中无法执行此操作。您必须传递带有大小信息的参数,以便在被调用函数中调用
malloc()
和free()
,或者调用函数必须在malloc()之后调用free()
许多面向对象的语言(例如C++)处理内存的方式可以让你做你想做的事情,而不是C
编辑
通过size信息作为参数,我的意思是让被调用函数知道您传递的指针拥有多少字节的内存。如果已为被调用字符串赋值,则可以直接查看该字符串,例如:
char test1[]="this is a test";
char *test2="this is a test";
char *test3;
当这样称呼时:
readString(test1); // (or test2)
char * readString(char *abc)
{
int len = strlen(abc);
return abc;
}
这两个参数都将导致len
=14
但是如果创建未填充的变量,例如:
char test1[]="this is a test";
char *test2="this is a test";
char *test3;
和分配相同数量的内存,但不填充,例如:
test3 = malloc(strlen("this is a test") +1);
被调用函数无法知道分配了什么内存。变量len
在readString()
的第一个原型中将==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;
}
您面临的挑战是需要释放资源(即导致free()
发生)
通常,调用者通过直接调用free()
(例如,请参见strdup
用户如何工作)或通过调用您提供的函数来释放分配的内存。例如,您可能要求调用者调用foo\u destroy
函数。正如另一张海报所指出的,您可能会选择将其包装在不透明的结构中,尽管这不是必需的,因为即使没有它,拥有自己的分配和销毁功能也是有用的(例如,对于资源跟踪)
然而,另一种方法是使用某种形式的清理功能。例如,分配字符串时,可以将其附加到池中分配的资源列表中,然后在完成后释放池。这就是apache2
如何使用其apr\u池
结构。通常,在该模型下,您不需要任何特定的free()
。请参阅和(更易于阅读)
在C中不能做的事情(因为没有对malloc()
d结构的引用计数)是直接确定对对象的最后一次“引用”何时超出范围,然后释放它。那是因为你没有引用,你有指针
最后,您询问现有函数如何返回char*
变量:
- 有些(如
strdup
、get\u current\u dir\u name
和getcwd
在某些情况下)希望调用方释放
- 有些(如
strerror\r
和getcwd
在其他情况下)希望调用方传入足够大小的缓冲区
- 有些同时执行这两项操作:从
getcwd
手册页:
作为POSIX.1-2001标准的扩展,Linux(libc4、libc5、glibc)getcwd()
动态分配缓冲区
如果buf
为NULL
,则使用malloc(3)
。在这种情况下,分配的缓冲区具有长度size
,除非size
为零,当
buf
按需要分配。调用方应该释放(3)
返回的缓冲区
- 有些使用内部静态缓冲区,因此不可重入/线程安全(恶心-不要这样做)。请参见
strerror
以及strerror\u r
的发明原因
- 有些只返回指向常量的指针(因此可重入性很好),不需要空闲指针
- 有些函数(如
libxml
)要求您使用单独的free
函数(xmlFree()
)
- 一些(如
apr\u palloc
)依赖于上述池技术
您可以跟踪分配的字符串,并在atexit例程()中释放它们。在下文中,我使用了一个全局变量,但如果手头有一个,它可以是一个简单的数组或列表
#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;
}
#包括
#包括
#包括
char*freeme=NULL;
无效收敛释放(无效)
{
if(freeme!=NULL)
免费的(免费的);
}
字符*AStringGet(无效)
{
freeme=malloc(20);
strcpy(结果,“字符串”);
atexit(收敛释放);
还我自由;
}
许多库强制用户处理内存分配。这是一个好主意,因为每个应用程序都有自己的对象生存期和重用模式。对于图书馆来说,尽可能少地对用户做出假设是有好处的
假设用户希望像这样调用您的库函数:
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
}
int output_size(/*params*/);
void func(/*params*/, char *destination);
如果您的库malloc
每次都对字符串进行排序,则调用malloc
会浪费大量精力,并且如果malloc
每次选择不同的块,则可能会显示糟糕的缓存行为
依靠