简体   繁体   English

C语言中的内存管理

[英]Memory management in C

Suppose I have a structure, and a pointer to a memory location p, how do I make sure that while creating an instance 'a' of the structure, it is placed into a memory chunk starting at p? 假设我有一个结构,以及一个指向存储位置p的指针,如何确保在创建该结构的实例“ a”时将其放置在以p开头的内存块中?

So I am passed a chunk of memory and I want to create a node at the beginning of it, so I need to make sure that the node is created at the beginning of it. 所以我传递了一块内存,我想在它的开头创建一个节点,所以我需要确保该节点是在它的开头创建的。 (Note: I cannot use malloc, calloc, free, memcpy, or similar functions because I am writing code for a memory management system). (注意:因为我正在为内存管理系统编写代码,所以无法使用malloc,calloc,free,memcpy或类似功能)。

You don't really 'create' instances of structures in C like that. 您并不是真的那样在C语言中“创建”结构实例。 Assuming that p points to a block of usable memory, you can just treat p as a pointer to your structure type: 假设p指向可用内存块,则可以将p视为指向您的结构类型的指针:

typedef struct {int x; long y;} a;

a *p2 = (a*)p;
int z = p2->x;

// or, if you don't want p2:
z = ((a*)p)->x;

Once p is cast (implicitly or explicitly as above), you can initialize the contents of your structure however you wish. 一旦强制转换了p (如上所述隐式或显式),就可以根据需要初始化结构的内容。

As an example, the following code will initialize a structure as you seem to request: 例如,以下代码将按照您的要求初始化结构:

typedef struct {int x; float y;} tA;
void initA (void *p) {
    tA *p2 = (tA*)p;
    p2->x = 0;
    p2->y = 3.14159;
}
int main (void) {
    char bigmem[100];
    initA (&(bigmem[0]));
    return 0;
}

Don't get hung up on the main function above, it's only to illustrate how you can pass an arbitrary memory address to the function. 不要挂在上面的main函数上,仅是为了说明如何将任意内存地址传递给该函数。 In your real-world case, you will have the memory already allocated somehow. 在实际情况下,您将已经以某种方式分配了内存。

If creation of the instance 'a' involves allocation of memory, then you can't make that allocation occur at memory pointed to by 'p'. 如果实例“ a”的创建涉及内存分配,那么您就无法在“ p”指向的内存中进行分配。

However, if by creation you mean initialisation of a structure in already allocated memory, then you should be able to pass 'p', typecast to a pointer to the structure, to the initialisation routine. 但是,如果通过创建是指在已经分配的内存中初始化结构,则应该能够将类型转换的p传递给p,并将其传递给初始化例程。 But you will have to be careful that the memory pointed to by 'p' is large enough for the structure, is not being used for something else, and has the right alignment for the structure you are initialising. 但是,您必须注意,“ p”所指向的内存对于该结构而言足够大,不会被用于其他事物,并且对于要初始化的结构具有正确的对齐方式。

If you are actually trying to do something else, you should post some code or go into a bit more detail. 如果您实际上正在尝试执行其他操作,则应发布一些代码或进行更多详细介绍。

just typecast the pointer to the type of your struct and you are done... 只要将指针类型转换为您的结构类型,就可以完成...

Hope it helps! 希望能帮助到你!

Basically, you take the address and cast it to a pointer of the appropriate type. 基本上,您获取地址并将其转换为适当类型的指针。 The major problem you can run into is alignment: if the address isn't properly aligned for an object of that type, attempting to dereference the pointer can (and will) cause undefined behavior -- a typical reaction will be your program being aborted. 您可能遇到的主要问题是对齐:如果该类型的对象的地址未正确对齐,则尝试取消对指针的引用可能(并且将)导致未定义的行为-典型的反应是程序被中止。 If memory serves, a typical Unix kernel will give you an error message about a "bus error". 如果有内存可用,那么典型的Unix内核将为您提供有关“总线错误”的错误消息。

You can't control where the allocator will allocate memory from, but you can make a temporary instance (on the stack) and copy it into where p points with memcpy . 您无法控制分配器将从何处分配内存,但是您可以创建一个临时实例(在堆栈上),然后使用memcpy将其复制到p指向的位置。

(Assuming p points to validly allocated memory, large enough for your structure and aligned appropriately.) (假设p指向有效分配的内存,该内存对于您的结构足够大并适当对齐。)

Code example for what Alex says: Alex所说的代码示例:

struct foo {
    int a;
    char *b;
    float c;
};

struct enough_space_for_a_foo {
    char a[sizeof(struct foo))];
};

int main() {
    // region of memory, which in the real code someone else is giving us
    struct enough_space_for_a_foo memory_region;

    // temporary object
    struct foo tmp = {10, "ten", 10.0};

    // copied to the specified region
    memcpy(&memory_region, &tmp, sizeof(struct foo));
}

So, an arbitrary memory region now contains the same values as if it had been initialized as a struct foo , using the initializer expression {10, "ten", 10.0} . 因此,任意内存区域现在​​都包含与使用初始化程序表达式{10, "ten", 10.0}初始化为struct foo相同的值。

If your struct doesn't need initializing with particular values, then you don't need to do anything. 如果您的结构不需要使用特定的值进行初始化,则无需执行任何操作。 A region of memory in C basically is an instance of a struct if you choose to think of it as one (and it's big enough, and correctly aligned). 如果您选择将其视为一个结构(并且它足够大且正确对齐),则C中的内存区域基本上就是该结构的一个实例。 There are no constructors, so just cast the pointer and get on with filling in the fields. 没有构造函数,因此只需转换指针并继续填写字段即可。

typedef struct {int x; long y;} A;

// Populate the members individually
A *aPtr = malloc(sizeof(A));
aPtr->x = 1;
aPtr->y = 2;

or 要么

A *aPtr = malloc(sizeof(A));
A a;

a.x = 1;
a.y = 2;

// Use C's inherent "assignment == copy by value" capability
*aPtr = a;

or 要么

A *aPtr = malloc(sizeof(A));
A a;

a.x = 1;
a.y = 2;

// Copy the memory yourself
memcpy(aPtr, &a, sizeof(A));

Feel free to replace my malloc with your own malloc. 随时用自己的malloc替换我的malloc。

Sounds like you are trying to do something similar to C++ placement new . 听起来您正在尝试做类似于C ++ new的放置

I think you confusing C with higher level languages. 我认为您将C与高级语言混淆了。 You never instantiate structs. 您永远不会实例化结构。 You just allocate a bunch of memory and then cast those to aa struct pointer. 您只需分配一堆内存,然后将其转换为struct指针即可。 Alternatively you allocate it on a stack which just means that compiler reserves so many bytes for you to use. 或者,您将其分配在堆栈上,这仅意味着编译器保留了太多字节供您使用。

You asked just the right person. 您只问了合适的人。 Not specifically, of course. 当然不具体。

The answer depends on your OS. 答案取决于您的操作系统。 If you truly can't use anyone else's memory stuff, then you have your work cut out for you. 如果您确实无法使用其他人的内存,那么您的工作就变得很容易。 You will have to make some kind of heap structure(s), perhaps some free list allocators for fixed size, and figure out what the OS has to offer. 您将必须建立某种堆结构,也许要为固定大小建立一些自由列表分配器,并弄清操作系统必须提供的功能。 You have VirtualAlloc in windows and you have brk or similar in unix. Windows中有VirtualAlloc,Unix中有brk或类似的东西。

If this is really homework, this is way too much work if this is a single semester assignment. 如果这确实是家庭作业,那么如果这是一个学期的作业,那么这将是太多的工作。

Of course if all you want to know is how to prepend allocation size to what you return, just do whatever your code normally is, then put your value at the front, then advance the pointer by one and return that. 当然,如果您只想知道如何将分配大小放在返回的值之前,则只需执行通常的代码,然后将值放在最前面,然后将指针前进一个并返回即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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