Object Oriented Programming in C, Avoid Memory Allocation

A

Andrew Au

Dear all,

I am trying to write a piece of software that use Object Oriented design
and implement it with C, I did the following

== In Object.h ==
typedef struct ObjectStructure* Object;

Object object_create();
int object_getIntegerAttribute(Object object);
void object_setIntegerAttribute(Object object, int integerAttribute);
void object_unload(Object object);

== In Object.c ==

#include <stdlib.h>

struct ObjectStructure {
int integerAttribute;
};

Object object_create() {return (Object)malloc(sizeof(struct
ObjectStructure));}
int object_getIntegerAttribute(Object object) {return
object->integerAttribute;}
void object_setIntegerAttribute(Object object, int integerAttribute)
{object->integerAttribute = integerAttribute;}
object_unload(Object object) {free object}

// I am afraid if the above code even compile, since I am simply writing the
code in the news client without a compiler.

While it is good to encapsulate the Object's structure, now, I must always
create the object in a dynamic memory allocation way (obviously, coz' the
outside world has no idea of the structure's size).

Now I am in dillema, I would like to have encapsulation for the object, so
that further changes to the Object does not affect the rest of the code, but
at the same time, I would like to avoid dynamic memory allocation as much as
possible, following the rule that ONLY unknown size of memory (p.s. I don't
have very large memory block) should be dynamically allocated, and any
pieces of dynamic memory should be reused as much as possible. (For
performance issue)

What should I do? At the same time, I would like to seek method refactor my
code so as to minimize memory allocation, are there any suggestion?
Memory Pool is great, and I am already using them.
 
M

Malcolm

Andrew Au said:
Now I am in dillema, I would like to have encapsulation for the object, so
that further changes to the Object does not affect the rest of the code, but
at the same time, I would like to avoid dynamic memory allocation as much as
possible, following the rule that ONLY unknown size of memory (p.s. I don't
have very large memory block) should be dynamically allocated, and any
pieces of dynamic memory should be reused as much as possible. (For
performance issue)

What should I do? At the same time, I would like to seek method refactor my
code so as to minimize memory allocation, are there any suggestion?
Memory Pool is great, and I am already using them.
Write a pair of functions, mymalloc() and myfree(), and use them to allocate
your objects from a big global pool.
When memory / performance constraints bite, tweak these functions. For
instance if you know that you always allocate 10 struct foos of 50 bytes,
then you can create a special pool of 50 byte blocks and allocate from this
efficiently and without any fragmentation.
 
A

Andrew Au

Dear all,

I am trying to write a piece of software that use Object Oriented design
and implement it with C, I did the following

== In Object.h ==
typedef struct ObjectStructure* Object;

Object object_create();
int object_getIntegerAttribute(Object object);
void object_setIntegerAttribute(Object object, int integerAttribute);
void object_unload(Object object);

== In Object.c ==

#include <stdlib.h>

struct ObjectStructure {
int integerAttribute;
};

Object object_create() {return (Object)malloc(sizeof(struct
ObjectStructure));}
int object_getIntegerAttribute(Object object) {return
object->integerAttribute;}
void object_setIntegerAttribute(Object object, int integerAttribute)
{object->integerAttribute = integerAttribute;}
object_unload(Object object) {free object}

// I am afraid if the above code even compile, since I am simply writing the
code in the news client without a compiler.

While it is good to encapsulate the Object's structure, now, I must always
create the object in a dynamic memory allocation way (obviously, coz' the
outside world has no idea of the structure's size).

Now I am in dillema, I would like to have encapsulation for the object, so
that further changes to the Object does not affect the rest of the code, but
at the same time, I would like to avoid dynamic memory allocation as much as
possible, following the rule that ONLY unknown size of memory (p.s. I don't
have very large memory block) should be dynamically allocated, and any
pieces of dynamic memory should be reused as much as possible. (For
performance issue)

What should I do? At the same time, I would like to seek method refactor my
code so as to minimize memory allocation, are there any suggestion?
Memory Pool is great, and I am already using them.

I am thinking of a way through macro expansion

== In Object.h ==
#define OBJECT (Object*)char[OBJECT_SIZE];
#define OBJECT_SIZE;

== In Object.c

// Somewhere
{
assert(OBJECT_SIZE == sizeof(struct ObjectStructure));
}

Then I could have static Object placed on the heap.
One difference from C++ is that the Object created must be freed, even
it is placed on the stack, it won't automatically destruct.
 
C

Christian Bau

Now I am in dillema, I would like to have encapsulation for the object, so
that further changes to the Object does not affect the rest of the code, but
at the same time, I would like to avoid dynamic memory allocation as much as
possible, following the rule that ONLY unknown size of memory (p.s. I don't
have very large memory block) should be dynamically allocated, and any
pieces of dynamic memory should be reused as much as possible. (For
performance issue)

Can you prove that memory allocation/deallocation affects performance in
any significant way, or is this just a guess? And "significant" means: I
will lose sales because of it, or customers will complain, or I will
have to buy faster and more expensive hardware.

Do whatever makes programming easiest.
 
D

Derrick Coetzee

Andrew said:
Now I am in dillema, I would like to have encapsulation for the object, so
that further changes to the Object does not affect the rest of the code, but
at the same time, I would like to avoid dynamic memory allocation as much as
possible [ . . . ]

This is a concern, since static allocation is more efficient (especially
the freeing part) and many calls to functions using such objects locally
could start to have an impact. Fragmentation on the other hand is not a
concern, since this could be fixed with pools or by using a better
memory allocator.

Here's a little trick I once came up with that lets you create both
public and private members in a C data structure. First put something
like this in your header file:

struct employeePrivate {
int age;
int salary;
};

typedef struct {
char* name;
char privateData[sizeof(struct employeePrivate)];
} Employee;

Employee objectCreate();

In other source files, they can access the public "name" element
directly, but in order to touch the private data they would have to
explicitly mess with the privateData array, which is unlikely to happen
accidentally (and easy to locate if someone does it). In the object's
implementation source file, you place this macro:

#define pri(obj, field) \
(((struct employeePrivate *)(&((obj).privateData)))->field)

Used like this:

Employee emp = ...;
pri(emp, salary) = pri(emp, age) * 1000;

These accesses will be just as efficient as normal accesses of struct
members, once the compiler has worked things out. All this code is
untested though. I hope this helps.
 
D

Derrick Coetzee

Derrick said:
typedef struct {
char* name;
char privateData[sizeof(struct employeePrivate)];
} Employee;

Employee objectCreate();

Err, I forgot to mention - the allocation policy here is, like in most
non-OOP C programs, the caller allocates space for the Employee wherever
they like, and instead of having the implementation create and destroy
the object, you have it "initialize" and "deinitialize" it:

Employee employeeInitialize(void);
void employeeDeinitialize(Employee);
 
D

Derrick Coetzee

Derrick said:
Employee employeeInitialize(void);
void employeeDeinitialize(Employee);

Argh, I meant:

void employeeInitialize(Employee*);
void employeeDeinitialize(Employee*);
 
D

Derrick Coetzee

Derrick said:
typedef struct {
char* name;
char privateData[sizeof(struct employeePrivate)];
} Employee;

To avoid alignment issues this might be better:

typedef struct {
char privateData[sizeof(struct employeePrivate)];
<public members>
} Employee;

I'm not sure if even that is allowed by the standard, though. But in
your case, all data is private, so it doesn't really matter.
 
C

Chris Torek

Derrick said:
typedef struct {
char* name;
char privateData[sizeof(struct employeePrivate)];
} Employee;

To avoid alignment issues this might be better:

typedef struct {
char privateData[sizeof(struct employeePrivate)];
<public members>
} Employee;

I'm not sure if even that is allowed by the standard, though.

The second one is guaranteed to work (because the offset of any
structure's first member is guaranteed to be zero, and sizeof()
takes into account any required padding). The first one is indeed
not guaranteed.

(My opinion, though, is that if you want to write C++ code, just write
C++ code. :) )
 
E

E. Robert Tisdale

Andrew said:
I am trying to write a piece of software
that uses Object Oriented design and implement it with C.
I did the following:

//== In Object.h ==

typedef struct ObjectStructure* Object;

You are confused.
An object is *not* a type.
It is an instance of some type.
Object object_create();
int object_getIntegerAttribute(Object object);
void object_setIntegerAttribute(Object object, int integerAttribute);
void object_unload(Object object);

//== In Object.c ==

#include <stdlib.h>

struct ObjectStructure {
int integerAttribute;
};

Object object_create(void) {
return (Object)malloc(sizeof(struct ObjectStructure)); }
int object_getIntegerAttribute(Object object) {
return object->integerAttribute; }
void object_setIntegerAttribute(Object object, int integerAttribute) {
object->integerAttribute = integerAttribute; }
object_unload(Object object) { free object }

// I am afraid if the above code even compile,
since I am simply writing the code in the news client without a compiler.

While it is good to encapsulate the Object's structure,
now, I must always create the object in a dynamic memory allocation way
(obviously, coz' the outside world has no idea of the structure's size).

Now I am in dillema, I would like to have encapsulation for the object
so that further changes to the Object does not affect the rest of the code
but, at the same time, I would like to avoid dynamic memory allocation
as much as possible, following the rule that ONLY unknown size of memory
(p.s. I don't have very large memory block) should be dynamically allocated
and any pieces of dynamic memory should be reused as much as possible.
(For performance issue)
What should I do?
At the same time, I would like to seek method refactor my code
so as to minimize memory allocation, are there any suggestion?
Memory Pool is great, and I am already using them.

I would do it this way:
> cat someType.h
#ifndef GUARD_SOMETYPE_H
#define GUARD_SOMETYPE_H 1

#include <stdlib.h>

typedef struct someType {
int Attribute;
} someType;

someType someType_create(int);
someType* someType_new(int);
int someType_attribute(const someType*);
void someType_destroy(const someType*);
void someType_delete(const someType*);

#endif//GUARD_SOMETYPE_H
> cat someType.c
#include "someType.h"

// private initializer
someType* someType_initialize(
someType* p, int attribute) {
p->Attribute = attribute;
return p;
}

someType someType_create(int attribute) {
someType value;
someType_initialize(&value, attribute);
return value;
}

someType* someType_new(int attribute) {
someType* p = (someType*)malloc(sizeof(someType));
return someType_initialize(p, attribute);
}

int someType_attribute(const someType* p) {
return p->Attribute;
}

void someType_destroy(const someType* p) { }

void someType_delete(const someType* p) {
someType_destroy(p);
free((void*)p);
}

Now you can write:

#include "someType.h"

int main(int argc, char* argv[]) {
someType anObject = someType_create(13);
// do stuff with anObject
someType_destroy(&anObject);
return EXIT_SUCCESS;
}

Memory is allocated from automatic storage for anObject.

Actually, for simple objects like this, I might write:
> cat someType.h
#ifndef GUARD_SOMETYPE_H
#define GUARD_SOMETYPE_H 1

#include <stdlib.h>

typedef struct someType {
int Attribute;
} someType;

inline static
someType someType_create(int attribute) {
someType value;
value.Attribute = attribute;
return value;
}

inline static
someType* someType_new(int attribute) {
someType* p = (someType*)malloc(sizeof(someType));
p->Attribute = attribute;
return p;
}

inline static
int someType_attribute(const someType* p) {
return p->Attribute;
}

inline static
void someType_destroy(const someType* p) { }

inline static
void someType_delete(const someType* p) {
someType_destroy(p);
free((void*)p);
}

#endif//GUARD_SOMETYPE_H
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,737
Latest member
Georgeengab

Latest Threads

Top