[英]Understanding use of memcpy on memory allocation
Looking at the source code for e2fsprogs
and wanting to understand the use of internal memory routines.查看
e2fsprogs
的源代码,想了解内部存储器例程的使用。 Allocating and freeing.分配和释放。
More to the point why use memcpy
instead of direct handling?更重要的是为什么使用
memcpy
而不是直接处理?
For example ext2fs_get_mem is:例如ext2fs_get_mem是:
/*
* Allocate memory. The 'ptr' arg must point to a pointer.
*/
_INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
{
void *pp;
pp = malloc(size);
if (!pp)
return EXT2_ET_NO_MEMORY;
memcpy(ptr, &pp, sizeof (pp));
return 0;
}
I guess the use of a local variable is as not to invalidate the passed ptr
in case of malloc
error.我想使用局部变量是为了在
malloc
错误的情况下不会使传递的ptr
无效。
memcpy
instead of setting ptr
to pp
on success?memcpy
而不是将ptr
设置为pp
?The memory is copied to a local variable, then freed, then memcpy
on the passed pointer to pointer.内存被复制到一个局部变量,然后释放,然后在传递的指针上进行
memcpy
。 As the allocation uses memcpy
I guess it has to do some juggling on free as well.由于分配使用
memcpy
我想它也必须在免费上做一些杂耍。
memcpy
do?memcpy
做了什么? Isn't sizeof(p)
size of int here?sizeof(p)
大小吗?/*
* Free memory. The 'ptr' arg must point to a pointer.
*/
_INLINE_ errcode_t ext2fs_free_mem(void *ptr)
{
void *p;
memcpy(&p, ptr, sizeof(p));
free(p);
p = 0;
memcpy(ptr, &p, sizeof(p));
return 0;
}
ext2_file_t
is defined as: ext2_file_t
定义为:
typedef struct ext2_file *ext2_file_t;
where ext2_file has , amongst other members, char *buf
.其中ext2_file在其他成员中具有
char *buf
。
In dump.c : dump_file()
在
dump.c : dump_file()
Here we have:我们这里有:
ext2_file_t e2_file;
retval = ext2fs_file_open(current_fs, ino, 0, &e2_file);
It calls ext2fs_file_open()
which do:它调用
ext2fs_file_open()
执行以下操作:
ext2_file_t file;
retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
And the free routine is for example:而免费例程是例如:
if (file->buf)
ext2fs_free_mem(&file->buf);
ext2fs_free_mem(&file);
You cannot assign directly to the ptr
parameter, as this is a local variable.您不能直接分配给
ptr
参数,因为这是一个局部变量。 memcpy
ing to ptr
actually writes to where the pointer points to. memcpy
ing to ptr
实际上写入指针指向的位置。 Compare the following usage code:比较以下使用代码:
struct SomeData* data;
//ext2fs_get_mem(256, data); // wrong!!!
ext2fs_get_mem(256, &data);
// ^ (!)
You would achieve exactly the same with a double pointer indirection:您可以使用双指针间接实现完全相同的效果:
_INLINE_ errcode_t ext2fs_get_mem_demo(unsigned long size, void** ptr)
{
*ptr = malloc(size);
return *ptr ? 0 : EXT2_ET_NO_MEMORY;
}
but this variant requires the pointer being passed to to be of type void*
, which is avoided by the original variant:但此变体要求传递给的指针为
void*
类型,原始变体避免了这种情况:
void* p;
ext2fs_get_mem_demo(256, &p);
struct SomeData* data = p;
Note: One additional variable and one additional line of code (or at very least one would need a cast)...注意:一个额外的变量和一个额外的代码行(或者至少有一个需要强制转换)...
Note, too, that in the usage example ext_file_t
should be a typedef
to a pointer type to make this work correctly (or uintptr_t
) or at least have a pointer as its first member (address of struct and address of its first member are guaranteed to be the same in C).还要注意,在使用示例中
ext_file_t
应该是指针类型的typedef
以使其正常工作(或uintptr_t
)或至少有一个指针作为其第一个成员(结构的地址和其第一个成员的地址保证在 C 中相同)。
/* The 'ptr' arg must point to a pointer.
/* 'ptr' arg 必须指向一个指针。 */
*/
can be read as "The ptr can point to pointer to ANYTHING".可以读作“ptr 可以指向任何东西的指针”。
It is a very simple malloc-wrapper in a library;它是一个非常简单的库中的 malloc 包装器; to be useful it has to work for any type.
要有用,它必须适用于任何类型。 So
void *
is the argument.所以
void *
是参数。
With a real type the function looks like this, with direct pointer assignment:对于真实类型,函数看起来像这样,直接分配指针:
int g(unsigned long size, int **ptr)
{
void *pp;
pp = malloc(size);
if (!pp)
return 1;
*ptr = pp;
return 0;
}
The same *ptr = pp
gives a invalid-void error with void *ptr
as argument decalration.同样的
*ptr = pp
给出了一个invalid-void 错误,其中void *ptr
作为参数声明。 Somehow disappointing, but then again it is called void *
, not any *
.不知何故令人失望,但又被称为
void *
,而不是any *
。
With void **ptr
there is a type warning like:使用
void **ptr
有一个类型警告,如:
expected 'void **' but argument is of type 'int **'
So memcpy to the rescue.所以 memcpy 来救援。 It looks like even without optimization, the call is replaced by a quadword MOV.
看起来即使没有优化,调用也会被四字 MOV 替换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.