tags:

views:

265

answers:

9

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?

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).

A: 

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.

(Assuming p points to validly allocated memory, large enough for your structure and aligned appropriately.)

Alex
Actually, I am writing the code for memcpy, malloc, calloc, free, etc. So I am not allowed to use any of those. My problem is that I want to make sure that a node I am creating is where I want to create.
As long as p has been allocated by your program to have enough empty space to store the struct! (Just wanted to clarify that you can't just dump things in random memory locations.)
Bob Somers
You mean aligned appropriately?
Alex
@unknown: malloc doesn't "create an instance" of anything. It allocates a specified number of bytes. You don't have to do anything about the contents of the memory you return, just find some from somewhere (and, as Alex says, make sure it is correctly aligned for whatever type has the strictest alignment requirements of all the types which can fit in it).
Steve Jessop
+1  A: 

just typecast the pointer to the type of your struct and you are done...

Hope it helps!

Ass3mbler
Assuming the pointer is sufficiently well aligned, which it will be if it is provided by the system's malloc() et al.
Jonathan Leffler
+7  A: 

You don't really 'create' instances of structures in C like that. Assuming that p points to a block of usable memory, you can just treat p as a pointer to your structure type:

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.

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. In your real-world case, you will have the memory already allocated somehow.

paxdiablo
Huh? You haven't created an instance of `a` at all. He wants to create (allocate) an instance of his struct at address `p`.
Alex
And `a` should be the instance, not the type, according to him.
Alex
You misunderstand my answer, @Alex. If OP has the memory already allocated, it exists already - you just cast that memory to treat it as the correct type.
paxdiablo
Yes , this program will work if p is a valid memory address.
atv
You can use sbrk() system call to extend your program address space. sbrk returns the start address of the extended address space. you can do like this char * p= sbrk(size) now pass 'p' to above function
atv
+3  A: 

If creation of the instance 'a' involves allocation of memory, then you can't make that allocation occur at memory pointed to by '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. 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.

If you are actually trying to do something else, you should post some code or go into a bit more detail.

Tony van der Peet
+1  A: 

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".

Jerry Coffin
A: 

Code example for what Alex says:

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}.

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). There are no constructors, so just cast the pointer and get on with filling in the fields.

Steve Jessop
Lose the address-of operator on the first argument to memcpy. ;)
Alex
Steve Jessop
Btw, feel free to use this code if you like (or give your own example), and I'll delete my answer. I was going to just post it into a comment to yours, but it won't fit.
Steve Jessop
Alex
Err, `s/100/sizeof(struct foo)/`.
Alex
D.Shawley
Steve Jessop
Anyway, with D.Shawley's advice taken into account too, I think whatever I do will either look weird, or else will raise the whole issue of array decay that I was trying to avoid as irrelevant. I'll try something else.
Steve Jessop
A: 
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.

Will Hartung
A: 

Sounds like you are trying to do something similar to C++ placement new.

I think you confusing C with higher level languages. You never instantiate structs. You just allocate a bunch of memory and then cast those to a a struct pointer. Alternatively you allocate it on a stack which just means that compiler reserves so many bytes for you to use.

Igor Zevaka
A: 

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.

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.

Charles Eli Cheese