在 C 中,您可以使用
strdup
来简洁地分配缓冲区并将字符串复制到其中。然而,据我所知,一般记忆没有类似的功能。例如,我不能说
struct myStruct *foo = malloc(sizeof(struct myStruct));
fill_myStruct(foo);
struct myStruct *bar = memdup(foo, sizeof(struct myStruct));
// bar is now a reference to a new, appropriately sized block of memory,
// the contents of which are the same as the contents of foo
那么,我的问题有三个:
malloc
和 memcpy
?strdup
但不包含 memdup
?你可以用一个简单的函数来实现它:
void* memdup(const void* mem, size_t size) {
void* out = malloc(size);
if(out != NULL)
memcpy(out, mem, size);
return out;
}
GNU Gnulib 的
void *xmemdup (void const *p, size_t s)
中有 xalloc.h
。
请注意,如果内存不足,它会调用
xalloc_die
。
您可能只想自己定义
memdup()
,然后按照已经建议的方式在代码中使用它。我的函数版本如下。
void *memdup(const void *src, size_t n)
{
void *dest;
dest = malloc(n);
if (dest == NULL)
return NULL;
return memcpy(dest, src, n);
}
至于讨论
memdup()
是否太琐碎甚至多余,我认为不是。它对于复制代码中的结构非常有用。 C 标准库的 ANSI/ISO 和 POSIX 标准都包含许多便利函数,但不幸的是没有这个。
示例:使用
strdup()
重新实现 memdup()
。
char *strdup(const char *src)
{
return memdup(src, strlen(src) + 1);
}
示例:使用
memdup()
复制对象。
int some_function(const struct some_struct *some_const_data)
{
struct some_struct *my_mutable_copy;
my_mutable_copy = memdup(some_const_data, sizeof *some_const_data);
if (my_mutable_copy == NULL)
return -1;
...
return 0;
}
为什么 C 包含
但不包含strdup
?memdup
在 C23 之前,
strdup
不是 C 标准库函数。但它是一个 POSIX 函数。您可以注意到在 动态内存 TR 之前的模式,除了存在分配内存的函数之外,没有任何东西返回指向动态分配的内存缓冲区的指针,您可以稍后调用 free
(getdelim、getline 、strdup、strndup - 这些都不是标准函数)。我不知道这个设计选择背后的原因,但我猜memdup
也因为同样的原因而没有实现。
是否有一些像这样的我不知道的标准库函数?
没有。
如果没有,是否有一种简洁且最好是标准的方法来执行此操作,而无需显式调用
和malloc
?memcpy
没有。
strdup 函数读取并复制以 null 结尾的字符串,直到 null。但是,普通数据没有任何此类分隔符,因此您需要为其指定要复制的数据的长度。
复制任意内存结构并不像复制字符串那么简单。例如,当结构包含指向其他结构(例如字符串)的指针时,您应该如何处理? “复制”这样的结构意味着什么?与字符串的情况不同,这个问题没有一个正确的答案。在这种情况下,最好让应用程序开发人员创建一种根据其用例制作结构副本的机制,而不是通过假装有规范的方法来处理它来混淆问题。