Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
返回分配给malloc的字符串?_C_Malloc - Fatal编程技术网

返回分配给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
每次选择不同的块,则可能会显示糟糕的缓存行为

依靠