简体   繁体   English

了解在内存分配中使用 memcpy

[英]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而不是直接处理?

Allocate分配

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无效。

  1. Why memcpy instead of setting ptr to pp on success?为什么在成功时使用memcpy而不是将ptr设置为pp

Free自由

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它也必须在免费上做一些杂耍。

  1. It can not free directly?不能直接免费吗?
  2. And what does the last memcpy do?最后一个memcpy做了什么? Isn't sizeof(p) size of int here?这里不是 int 的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;
}

Example of use:使用示例:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM