是否可以释放在 printf 内部调用的函数(仅)的返回值(在 c 中)?
Is it possible to free the returned value of a function (only) called inside of printf (in c)?
假设我正在编写一个类似 strdup() 的函数,或者任何其他使用 malloc() 的函数。如果我只像这样在 printf() 内部调用此函数:
printf("%s", my_function(arg));
是否可以释放函数返回的值?如果是,如何?据我所知,free() 将一个空指针作为参数,但如果您从不将返回值存储在变量中,您如何获得该指针?
否 - 您需要将其命名为:
char *p;
p = my_function(arg);
printf("%s", p);
free(p);
编辑
如果你喜欢代码滥用,你可以这样做:
for(char *p = my_function(arg); p != NULL ; free(p), p = NULL)
printf("%s", p);
但这太可怕了...
Is it possible to free the returned value of a function (only) called inside of printf (in c)?
没有
备选方案:使用复合文字“分配”。
而不是在 my_function(char *arg)
中分配,确定所需的大小并将 复合文字 传递给 my_function(char *arg, char *buf)
,然后 returns buf
.
如果最大大小不是太大,则不在 my_function(char *arg)
中分配,而是将 复合文字 传递给 my_function(char *arg, char *buf)
,然后 [=44] =] buf
.
#define MY_FUNCTION_SIZE 42
printf("%s", my_function(arg, char [MY_FUNCTION_SIZE]{0}));
复合文字在代码块结束前有效。然后它是“未分配的”。 malloc()
、free()
也不需要明确命名的临时对象。
Example.
嗯....您可以执行以下操作(保存指针以供以后处理,例如 free()
ing 它)
char *p;
printf("%s", p = my_function(arg));
free(p);
或者,更易读
void *p = my_function(arg);
printf("%s", p);
free(p);
第二种方法是设计my_function()
在预先分配的(稍后解释)缓冲区上运行。
char *my_function(some_type arg, char *buffer, size_t buff_sz)
{
/* use buffer as a work buffer */
/* ... */
return buffer;
}
然后将它与一些缓冲区一起使用,分配在 auto
变量中:
if (something) {
char buffer[1000];
printf("%s", my_function(arg, buffer, sizeof buffer));
}
/* buffer is gone here */
这是一种非常灵活的工作方式,一旦你掌握了它。
一旦我编写了一个例程,将一系列分配的指针保存到 free()
(或者可能 post 处理指针),一旦工作完成,它们就会全部保存。为了允许像你提出的那样的表达式,函数采用一个指针(分配的指针)并将其保存在一个结构中,函数返回它的参数,所以上面的构造是可能的
它仅由一个头文件和一个包含两个函数的简单文件组成:
mf_save()
,保存一个指针供以后释放。
mf_free()
,到 post-处理(并释放)一次性保存的所有指针。此例程还 free()
分配了用于保存指针的内存,因此 post 处理仅完成一次,之后所有保存的指针都将丢失,因此您最好 free()
它们在您传递给它的 post-processing 例程指针。一个常见的使用它来传递它只是 free
.
mf.h
/* mf.h -- types and definitions for mf.c.
* Author: Luis Colorado <luiscoloradourcola@gmail.com>
* Date: Sun Sep 19 12:16:18 EEST 2021
* Copyright: (c) 1992-2021 Luis Colorado. All rights reserved.
* License: BSD.
*/
#ifndef _MF_H
#define _MF_H
#define MF_F(_fmt) "%s:%d:%s: "_fmt, __FILE__, __LINE__, __func__
typedef struct mf_s *mf_t;
void *mf_save(mf_t *safe_ref, void *ptr);
void mf_free(mf_t *safe_ref, void (*proc)(void *));
#endif /* _MF_H */
mf.c
这是模块的核心。
/* mf.c -- a module to save pointers for batch free()ing, after
* work is done.
* Author: Luis Colorado <luiscoloradourcola@gmail.com>
* Date: Sun Sep 19 11:54:37 EEST 2021
* Copyright: (c) 1992-2021 Luis Colorado. All rights reserved.
* License: BSD.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "mf.h"
#define MF_SIZE (3)
#define THIS (*safe_ref)
struct mf_s {
size_t mf_n; /* num of saved in this block */
mf_t mf_nxt; /* nxt chunk pointer */
mf_t mf_vec[MF_SIZE];/* saved pointers */
};
static mf_t
mf_alloc(mf_t prev)
{
/* call calloc, so the block is zeroed */
mf_t ret_val = calloc(1, sizeof * ret_val);
assert(ret_val != NULL);
ret_val->mf_nxt = prev;
return ret_val;
}
void *
mf_save(mf_t *safe_ref, void *ptr)
{
if (THIS == NULL || THIS->mf_n == MF_SIZE) { /* full chunk */
printf(MF_F("full chunk, allocating new [%p]"), THIS);
THIS = mf_alloc(THIS);
printf(" -> [%p]\n", THIS);
}
mf_t s = THIS;
s->mf_vec[s->mf_n++] = ptr;
printf(MF_F("SAVED [%p]\n"), ptr);
return ptr;
}
void
mf_free(mf_t *safe_ref, void (*proc)(void *))
{
while(THIS) {
int ix;
for (ix = 0; ix < THIS->mf_n; ++ix) {
void *p = THIS->mf_vec[ix];
printf(MF_F("processing [%p]\n"), p);
proc(p);
}
mf_t temp = THIS;
THIS = THIS->mf_nxt;
printf(MF_F("freeing chunk @ [%p] -> [%p]\n"), temp, THIS);
free(temp);
}
}
这种方法的好消息是它只使用动态内存,而且保险箱只占用堆栈中指针的大小。另一个好的想法是它是 1992 年编写的,因此它不需要任何编译器新奇。
test_mf.c
这是一个测试例程,它分配 10 个指针(随机大小,但使用 space 将分配的大小存储在其中 --- 其余未使用)然后通过调用 [=23] 释放它们=].
#include <stdio.h>
#include <stdlib.h>
#include "mf.h"
/* this is a wrapper to malloc() to store the number of bytes in
* the allocated memory, so the processing() routine has the
* possibility of printing the amount of allocated memory */
static void *
malloc_wrapper(size_t n)
{
int *ret_val = malloc(n);
printf(MF_F("allocated %zd bytes @ %p\n"), n, ret_val);
*ret_val = n;
return ret_val;
}
/* this is a wrapper to free() to printf the number of allocated
* bytes that are being freed. */
void
free_wrapper(void *p)
{
int *q = p;
printf(MF_F("freeing %d bytes @ %p\n"), *q, p);
free(p);
}
/* main program, allocate 1000 random sized buckets of memory,
* then deallocate them. */
int
main()
{
int i;
mf_t safe = NULL; /* initialize to NULL always */
for (i = 0; i < 10; i++) { /* several allocations */
int size = rand() & 1000 + sizeof(int);
printf("Allocating %d bytes @ %p\n", size, mf_save(&safe, malloc_wrapper(size)));
}
/* all are freed at the end of the work */
mf_free(&safe, free_wrapper);
}
(注意:我已经为 malloc()
和 free()
编写了包装器以在内存量 allocated/deallocated 上插入跟踪,但您可以使用 malloc()
和 free()
在他们的位置。)
生成文件
这 Makefile
允许您构建测试程序。
targets = test_mf
test_mf_objs = test_mf.o mf.o
to_clean = test_mf $(test_mf_objs)
all: $(targets)
clean:
$(RM) $(toclean)
test_mf: $(test_mf_deps) $(test_mf_objs)
$(CC) $(CFLAGS) $(LDFLAGS) $($@_ldfl) -o $@ $($@_objs) $($@_libs)
此处的例程受版权保护,但您可以在 BSD 许可下自由使用它们。
假设我正在编写一个类似 strdup() 的函数,或者任何其他使用 malloc() 的函数。如果我只像这样在 printf() 内部调用此函数:
printf("%s", my_function(arg));
是否可以释放函数返回的值?如果是,如何?据我所知,free() 将一个空指针作为参数,但如果您从不将返回值存储在变量中,您如何获得该指针?
否 - 您需要将其命名为:
char *p;
p = my_function(arg);
printf("%s", p);
free(p);
编辑
如果你喜欢代码滥用,你可以这样做:
for(char *p = my_function(arg); p != NULL ; free(p), p = NULL)
printf("%s", p);
但这太可怕了...
Is it possible to free the returned value of a function (only) called inside of printf (in c)?
没有
备选方案:使用复合文字“分配”。
而不是在 my_function(char *arg)
中分配,确定所需的大小并将 复合文字 传递给 my_function(char *arg, char *buf)
,然后 returns buf
.
如果最大大小不是太大,则不在 my_function(char *arg)
中分配,而是将 复合文字 传递给 my_function(char *arg, char *buf)
,然后 [=44] =] buf
.
#define MY_FUNCTION_SIZE 42
printf("%s", my_function(arg, char [MY_FUNCTION_SIZE]{0}));
复合文字在代码块结束前有效。然后它是“未分配的”。 malloc()
、free()
也不需要明确命名的临时对象。
Example.
嗯....您可以执行以下操作(保存指针以供以后处理,例如 free()
ing 它)
char *p;
printf("%s", p = my_function(arg));
free(p);
或者,更易读
void *p = my_function(arg);
printf("%s", p);
free(p);
第二种方法是设计my_function()
在预先分配的(稍后解释)缓冲区上运行。
char *my_function(some_type arg, char *buffer, size_t buff_sz)
{
/* use buffer as a work buffer */
/* ... */
return buffer;
}
然后将它与一些缓冲区一起使用,分配在 auto
变量中:
if (something) {
char buffer[1000];
printf("%s", my_function(arg, buffer, sizeof buffer));
}
/* buffer is gone here */
这是一种非常灵活的工作方式,一旦你掌握了它。
一旦我编写了一个例程,将一系列分配的指针保存到 free()
(或者可能 post 处理指针),一旦工作完成,它们就会全部保存。为了允许像你提出的那样的表达式,函数采用一个指针(分配的指针)并将其保存在一个结构中,函数返回它的参数,所以上面的构造是可能的
它仅由一个头文件和一个包含两个函数的简单文件组成:
mf_save()
,保存一个指针供以后释放。mf_free()
,到 post-处理(并释放)一次性保存的所有指针。此例程还free()
分配了用于保存指针的内存,因此 post 处理仅完成一次,之后所有保存的指针都将丢失,因此您最好free()
它们在您传递给它的 post-processing 例程指针。一个常见的使用它来传递它只是free
.
mf.h
/* mf.h -- types and definitions for mf.c.
* Author: Luis Colorado <luiscoloradourcola@gmail.com>
* Date: Sun Sep 19 12:16:18 EEST 2021
* Copyright: (c) 1992-2021 Luis Colorado. All rights reserved.
* License: BSD.
*/
#ifndef _MF_H
#define _MF_H
#define MF_F(_fmt) "%s:%d:%s: "_fmt, __FILE__, __LINE__, __func__
typedef struct mf_s *mf_t;
void *mf_save(mf_t *safe_ref, void *ptr);
void mf_free(mf_t *safe_ref, void (*proc)(void *));
#endif /* _MF_H */
mf.c
这是模块的核心。
/* mf.c -- a module to save pointers for batch free()ing, after
* work is done.
* Author: Luis Colorado <luiscoloradourcola@gmail.com>
* Date: Sun Sep 19 11:54:37 EEST 2021
* Copyright: (c) 1992-2021 Luis Colorado. All rights reserved.
* License: BSD.
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include "mf.h"
#define MF_SIZE (3)
#define THIS (*safe_ref)
struct mf_s {
size_t mf_n; /* num of saved in this block */
mf_t mf_nxt; /* nxt chunk pointer */
mf_t mf_vec[MF_SIZE];/* saved pointers */
};
static mf_t
mf_alloc(mf_t prev)
{
/* call calloc, so the block is zeroed */
mf_t ret_val = calloc(1, sizeof * ret_val);
assert(ret_val != NULL);
ret_val->mf_nxt = prev;
return ret_val;
}
void *
mf_save(mf_t *safe_ref, void *ptr)
{
if (THIS == NULL || THIS->mf_n == MF_SIZE) { /* full chunk */
printf(MF_F("full chunk, allocating new [%p]"), THIS);
THIS = mf_alloc(THIS);
printf(" -> [%p]\n", THIS);
}
mf_t s = THIS;
s->mf_vec[s->mf_n++] = ptr;
printf(MF_F("SAVED [%p]\n"), ptr);
return ptr;
}
void
mf_free(mf_t *safe_ref, void (*proc)(void *))
{
while(THIS) {
int ix;
for (ix = 0; ix < THIS->mf_n; ++ix) {
void *p = THIS->mf_vec[ix];
printf(MF_F("processing [%p]\n"), p);
proc(p);
}
mf_t temp = THIS;
THIS = THIS->mf_nxt;
printf(MF_F("freeing chunk @ [%p] -> [%p]\n"), temp, THIS);
free(temp);
}
}
这种方法的好消息是它只使用动态内存,而且保险箱只占用堆栈中指针的大小。另一个好的想法是它是 1992 年编写的,因此它不需要任何编译器新奇。
test_mf.c
这是一个测试例程,它分配 10 个指针(随机大小,但使用 space 将分配的大小存储在其中 --- 其余未使用)然后通过调用 [=23] 释放它们=].
#include <stdio.h>
#include <stdlib.h>
#include "mf.h"
/* this is a wrapper to malloc() to store the number of bytes in
* the allocated memory, so the processing() routine has the
* possibility of printing the amount of allocated memory */
static void *
malloc_wrapper(size_t n)
{
int *ret_val = malloc(n);
printf(MF_F("allocated %zd bytes @ %p\n"), n, ret_val);
*ret_val = n;
return ret_val;
}
/* this is a wrapper to free() to printf the number of allocated
* bytes that are being freed. */
void
free_wrapper(void *p)
{
int *q = p;
printf(MF_F("freeing %d bytes @ %p\n"), *q, p);
free(p);
}
/* main program, allocate 1000 random sized buckets of memory,
* then deallocate them. */
int
main()
{
int i;
mf_t safe = NULL; /* initialize to NULL always */
for (i = 0; i < 10; i++) { /* several allocations */
int size = rand() & 1000 + sizeof(int);
printf("Allocating %d bytes @ %p\n", size, mf_save(&safe, malloc_wrapper(size)));
}
/* all are freed at the end of the work */
mf_free(&safe, free_wrapper);
}
(注意:我已经为 malloc()
和 free()
编写了包装器以在内存量 allocated/deallocated 上插入跟踪,但您可以使用 malloc()
和 free()
在他们的位置。)
生成文件
这 Makefile
允许您构建测试程序。
targets = test_mf
test_mf_objs = test_mf.o mf.o
to_clean = test_mf $(test_mf_objs)
all: $(targets)
clean:
$(RM) $(toclean)
test_mf: $(test_mf_deps) $(test_mf_objs)
$(CC) $(CFLAGS) $(LDFLAGS) $($@_ldfl) -o $@ $($@_objs) $($@_libs)
此处的例程受版权保护,但您可以在 BSD 许可下自由使用它们。