One memory allocation function - multiple data types? 
Author Message
 One memory allocation function - multiple data types?

I am in the process of writing a program that dynamically allocates memory
for several 1D and 2D arrays.  Unfortunately, the arrays that require this
dynamic memory allocation have several different data types, including int,
float, and unsigned char.  As a result I have a memory allocation function
for each type.  One such function is as follows:

void MEMORY_FLOAT_1D (int length, float **vector) {

        if ((*vector = (float *) malloc(sizeof(float) * length))==NULL) {
           perror("Trouble mallocing memory for vector!");
           exit (-1);
        }

Quote:
}

Does anyone know of a method that would allow me to pass the data type
required for an array to the function so that I could use just a single
function?  Something along the lines of:

void MEMORY_FLOAT_1D (char *datatype, int length, float **vector) {

where datatype indicates either int, float or unsigned char.  My apologies
If this seems to be a basic question, but much of my C programming ability
is self taught, and passing data types and dynamic memory allocation are
stretching that ability a bit thin!  By the way, I am using the gcc compiler
on Sun stations running Solaris if it should happen to make a difference.
Many thanks for any help!

-Brian

-------------------------------------------------------------------------------
  Brian R. Jones                                Aerospace Engineering


-------------------------------------------------------------------------------



Fri, 21 Feb 1997 12:45:20 GMT  
 One memory allocation function - multiple data types?

|> I am in the process of writing a program that dynamically allocates memory
|> for several 1D and 2D arrays.  Unfortunately, the arrays that require this
|> dynamic memory allocation have several different data types, including int,
|> float, and unsigned char.  As a result I have a memory allocation function
|> for each type.  One such function is as follows:
|>
|> void MEMORY_FLOAT_1D (int length, float **vector) {
|>
|>         if ((*vector = (float *) malloc(sizeof(float) * length))==NULL) {
|>            perror("Trouble mallocing memory for vector!");
|>            exit (-1);
|>         }
|> }
|>

You don't really need the data type, just it's size.
How about something like:

 void MEMORY_1D(int size, int length, void **vector) {
        if ((*vector = malloc(size * length))==NULL) {
           perror("Trouble mallocing memory for vector!");
           exit(-1);
        }
 }

and call it with:

  MEMORY_1D(sizeof(float), 100, (void**) &floatVector);

Ron



Sat, 22 Feb 1997 21:53:16 GMT  
 One memory allocation function - multiple data types?

Quote:
> Does anyone know of a method that would allow me to pass the data type
> required for an array to the function so that I could use just a single
> function?  Something along the lines of:

> void MEMORY_FLOAT_1D (char *datatype, int length, float **vector) {

> where datatype indicates either int, float or unsigned char.  My apologies
> If this seems to be a basic question, but much of my C programming ability
> is self taught, and passing data types and dynamic memory allocation are
> stretching that ability a bit thin!  By the way, I am using the gcc compiler
> on Sun stations running Solaris if it should happen to make a difference.
> Many thanks for any help!

> -Brian

Brian,

you don't need the type at all, only the size.

void* MEMORY_1D (int length, int elemsize) {
    void* tmp;
        if ((tmp = malloc(elemsize * length))==NULL) {
           perror("Trouble mallocing memory for vector!");
           exit (-1);
        }
    return tmp;

Quote:
}

... vector = (float*) MEMORY_1D(length,sizeof(float)) ...

Since you are using C, type safety is not of big importance ;-)
(If you were using C++, "vector" and "matrix" template classes
would be thing to do.)

There is no need to keep the "sizeof" near the malloc. The malloc
function does not know about the types that are to be stuffed into the
allocated area, so it returns a "suitably aligned" piece of memory.

Hope that helps,
        Markus

(comp.std.c eliminated from the newsgroup list)



Sat, 22 Feb 1997 23:06:01 GMT  
 One memory allocation function - multiple data types?

: function?  Something along the lines of:

: void MEMORY_FLOAT_1D (char *datatype, int length, float **vector) {

: where datatype indicates either int, float or unsigned char.  My apologies

I don't really understand what you want with 'float **vector', especially
when datatype is "int"...

The 2 other solutions I saw, use the C compiler, you could use the C pre-processor
as well:

#define DTYPE_INT       (sizeof(int))
#define DTYPE_FLOAT     (sizeof(float))
#define DTYPE_UCHAR     (sizeof(unsigned char))

#define MEMORY_CLAIM_1D(type,size)      certainmalloc((size_t)(type)*(size_t)(size))

And define the following function:

void *certainmalloc(size_t total) {
        void *p;

        p = malloc(total);
        if(p == NULL) {
                fprintf(stderr,"Malloc failed\n"); exit(1);
        }
        return p;

Quote:
}

Call the function with:

float *floatvec;
int *intvec;

floatvec = MEMORY_CLAIM_1D(DTYPE_FLOAT,100);
intvec = MEMORY_CLAIM_1D(DTYPE_INT,31);

: stretching that ability a bit thin!  By the way, I am using the gcc compiler
: on Sun stations running Solaris if it should happen to make a difference.

Make sure you use ANSI-C, the use of "void *" as generic pointer is only valid in ANSI-C.

Albert
--
exit 0 # Just in case



Sun, 23 Feb 1997 16:28:47 GMT  
 One memory allocation function - multiple data types?

Quote:
>The 2 other solutions I saw, use the C compiler, you could use the C
>pre-processor as well:
>#define DTYPE_INT   (sizeof(int))
>#define DTYPE_FLOAT (sizeof(float))
>#define DTYPE_UCHAR (sizeof(unsigned char))

You can do without those too....

Quote:
>#define MEMORY_CLAIM_1D(type,size) certainmalloc((size_t)(type)*(size_t)(size))

#define MEMORY_1D(type, size)       certainmalloc(sizeof(type) * size)

Quote:
>void *certainmalloc(size_t total) {
>    void *p; p = malloc(total);
>    if(p == NULL) { fprintf(stderr,"Malloc failed\n"); exit(1); }
>    return p;
>}

No change to that one....

Quote:
>float *floatvec;
>int *intvec;
>floatvec = MEMORY_CLAIM_1D(DTYPE_FLOAT,100);
>intvec = MEMORY_CLAIM_1D(DTYPE_INT,31);

floatvec = MEMORY_1D(float, 100);
intvec = MEMORY_1D(int, 31);

Or ...

#define GET_MEMORY_1D(ptr, size)     ptr = certainmalloc(sizeof(*ptr) * size)

GET_MEMORY_1D(floatvec, 100);
GET_MEMORY_1D(intvec, 31);

None of this depends on the standard though.
--
 <<  If this were the company's opinion, I would not be allowed to post it.  >>
segmentation fault (california dumped)



Mon, 24 Feb 1997 10:50:34 GMT  
 One memory allocation function - multiple data types?
How about something like this...

#define FLOAT_ID 0
#define INT_ID   1

void MEMORY_FLOAT_1D (int datatype, int length, void **vector) {

 switch(datatype) {
  case FLOAT_ID:
        if ((*vector = (void *) malloc(sizeof(float) * length))==NULL) {
           perror("Trouble mallocing memory for vector!");
           exit (-1);
        }
        break;
  case INT_ID:
        if ((*vector = (void *) malloc(sizeof(int) * length))==NULL) {
           perror("Trouble mallocing memory for vector!");
           exit (-1);
        }
        break;
  }

Quote:
}

Alternatively, you can keep the functions you have already written and create
an array of pointers to functions. Then make function calls like:

MEMORY[FLOAT_ID](length,vector);

This would require a change to all the current calls (as would the other method)
but would only require the functions themselves to have the vectors changed to
(void *) or (void **) instead of the current types. In fact some compilers won't
complain about even that. The array idea gives faster execution at a small
cost in memory overhead. Code size and program size would be machine dependent.

Hank



Mon, 24 Feb 1997 00:14:26 GMT  
 One memory allocation function - multiple data types?

Quote:

>I am in the process of writing a program that dynamically allocates memory
>for several 1D and 2D arrays.  Unfortunately, the arrays that require this
>dynamic memory allocation have several different data types, including int,
>float, and unsigned char.  As a result I have a memory allocation function
>for each type.  One such function is as follows:

>void MEMORY_FLOAT_1D (int length, float **vector) {

>        if ((*vector = (float *) malloc(sizeof(float) * length))==NULL) {
>           perror("Trouble mallocing memory for vector!");
>           exit (-1);
>        }
>}

I flirted with this problem in programs using linked lists and various
data structures with an eye to changing the lists that were seldom
altered to dynamic arrays.  What I eventually used was:

void *allocarray(size_t size, int nelem)
{
   void *ptr;

   ptr = calloc(size, nelem);
  return(ptr);

Quote:
}

and then call with (eg)

float *f;

if((f = (float *)allocarray(sizeof(*f), 10)) == NULL)
  /* error code here */

If your compiler doesn't support void *, then use char * instead.  Using this
permits you to explicitly cast the returned pointer, much as you would
do with malloc() or calloc().  To release it, you use the normal free() call,
and it works with anything, including arrays of structures, pointers, and
any other valid data type.

To make it work with 2-d arrays, you write a function that calls this function
twice, once for the array of pointers, and then in a loop for each subscripted
element.  Extend that by one for 3-d arrays, and so forth.  You may have
to keep an eye out for machine-dependencies that limit how *small* an
memory block you can allocate (ie/ MD-DOS has a minimum, I think, of
16 bytes before it begins behaving funny).

You can also alter this, or write a similar function, so that you can pass
in an allocated array and have the function enlarge it or shrink it.  The only
problem is when shrinking, do you care what data you lose?

It is not difficult to extend this idea slightly to come up with generic routines
that will write and read your arrays to disk, as well.  Give it a try.

Dave



Mon, 24 Feb 1997 05:03:52 GMT  
 One memory allocation function - multiple data types?

Quote:
> I am in the process of writing a program that dynamically allocates memory
> for several 1D and 2D arrays.  Unfortunately, the arrays that require this
> dynamic memory allocation have several different data types, including int,
> float, and unsigned char.  As a result I have a memory allocation function
> for each type.  One such function is as follows:

> void MEMORY_FLOAT_1D (int length, float **vector) {

>         if ((*vector = (float *) malloc(sizeof(float) * length))==NULL) {
>            perror("Trouble mallocing memory for vector!");
>            exit (-1);
>         }
> }

> Does anyone know of a method that would allow me to pass the data type
> required for an array to the function so that I could use just a single
> function?  Something along the lines of:

> void MEMORY_FLOAT_1D (char *datatype, int length, float **vector) {

What you are looking for is polymorphism and this is not supported directly in the C
language (though overloading in C++ would suit your requirements - but then so would
the new operator). WHat there is is a text pre-processor. Now this was inhereted from
the assemblers that preceeded it, used to create macros. It is inherantly dirty, I
note from Stroustrups book `The design and Evolution of C++' that one of his aims was
to make it redundant. Why? because it does not have the same scope, can produce
code with unexpected effects capable of `quiet' changes and provides no type checking
or error reporting.

OK so how to use it:-

#define talloc(type,arraySize)     ((type *) myalloc(sizeof(type) * arraySize))

This does the trick, all you need is a function myalloc that returns a void* and
performs your error checking. Now why bother casting the void * ? Well there
are two points of view on this, there are those that believe that the cast will hide
any lack of function prototype and that will cause  myalloc to return an int
with possible unforseen consequences. The other poinnt of view is that by
combining the type casting, with the inevitable type checking between the variable to
hold the type and the type requested, you ensure that the corect size object has been
asked for. And as this can cause one of the hardest problems in C to debug anything
to help prevent it is a good thing.

So if you are going to use the cast then:-

  1) Use full prototypes for all functions
  2) Use a compiler that warns if no prototype available
  3) Always compile with warnings enabled

Of course once you are using the pre-processor you can get cleverer

#define talloc(type,arraySize) \
     ((type *) msgalloc(sizeof(type)*arraySize, __LINE__, __FILE__)

You then just pick up the values - oh gcc also has __FUNCTION__ but if you
use it you should use conditional compilation on the form..

Now:-

  typedef struct {int a; inb; char *c} Foo_t

  int main(void)
  {
     Foo_t **ptr;
     int i, rows = 20, columns = 40;

     ptr = talloc(Foo_t *,rows);
     for (i=0; i<rows; i++){
        ptr[i] = talloc(Foo_t, columns);
     }
     return EXIT_SUCCESS;
  }    

--
Douglas

---
=============================================================================

                                        Fax: +44 31-667 7209
============================= Mostly harmless ===============================



Tue, 25 Feb 1997 18:21:38 GMT  
 One memory allocation function - multiple data types?

    faticar> You don't really need the data type, just it's size.
    faticar> How about something like:

    faticar>  void MEMORY_1D(int size, int length, void **vector) {
    faticar>         if ((*vector = malloc(size * length))==NULL) {
    faticar>            perror("Trouble mallocing memory for vector!");
    faticar>            exit(-1);
    faticar>         }
    faticar>  }

    faticar> and call it with:

    faticar>   MEMORY_1D(sizeof(float), 100, (void**) &floatVector);

That'll work okay on his Sun (he did say Sun, didn't he?), but strictly
speaking, it is not correct.  When you convert that `pointer to a float*' to a
`pointer to a void*' you assume that sizeof(float*)==sizeof(void*), which
isn't necessarily true.  (That may sound excessively pedantic, but he *did*
post his question to `comp.std.c'. :-)

To be completely correct, he would have to do something like this:

        *(float**) vector = malloc...

but then he's stuck having to supply that extra type information again.

He could use a macro:

 #define MEMORY_1D(L, V) \
  do { if (((V) = malloc(sizeof(*(V)) * (L))) == 0) { yikes(); } } while (0)

 MEMORY_1D(100, floatVector);

Or write it in C++:

 template<class T> void MEMORY_1D(int length, T **floatVector)
 {
    *floatVector = new T[length];
    if (*floatVector == 0)
      yikes();
 }

 MEMORY_1D(100, &floatVector);

Michael.



Wed, 26 Feb 1997 01:46:15 GMT  
 One memory allocation function - multiple data types?

Quote:
>I am in the process of writing a program that dynamically allocates memory
>for several 1D and 2D arrays.  Unfortunately, the arrays that require this
>dynamic memory allocation have several different data types, including int,
>float, and unsigned char.  As a result I have a memory allocation function
>for each type.  One such function is as follows:

>void MEMORY_FLOAT_1D (int length, float **vector) {

>        if ((*vector = (float *) malloc(sizeof(float) * length))==NULL) {
>           perror("Trouble mallocing memory for vector!");
>           exit (-1);
>        }
>}

>Does anyone know of a method that would allow me to pass the data type
>required for an array to the function so that I could use just a single
>function?  Something along the lines of:

>void MEMORY_FLOAT_1D (char *datatype, int length, float **vector) {

>where datatype indicates either int, float or unsigned char.  My apologies
>If this seems to be a basic question, but much of my C programming ability
>is self taught, and passing data types and dynamic memory allocation are
>stretching that ability a bit thin!  By the way, I am using the gcc compiler
>on Sun stations running Solaris if it should happen to make a difference.
>Many thanks for any help!

>-Brian

    There're 2 ways

1. Change to C++ language and there you can write things like

     float* pf = new float[10];
     char* pc = new char[81];

   BTW, new provides basic error handling throu user defined new_handler
   function which is called every time there is not enough room
   And you don't need to free(pf),

     delete pf;
     delete pc;

   will do everything for you even if new fails and pf or pc equal NULL.

2. If you wish to keep in C try this:

   Use one function for for error handling and later translate to type
   you need, eg.

     void* Memory (size_t size, int count)
     { void* pv = malloc(size * count));
       if (pv == NULL)
       { perror("Trouble mallocing memory for vector!");
         exit (-1);
       }
       return pv;
     }

     float* pf = (float*)Memory(sizeof(float), 10);
     char* pc = (char*)Memory(sizeof(char), 81);

P.S. I believe there is C++ compiler even on Sun with Solaris, look for
     GNU gpp compiler.

---+-           Best wishes, Brand // also known as Igor Karp



Wed, 26 Feb 1997 00:23:54 GMT  
 One memory allocation function - multiple data types?
Ok, I'm the one that originally posted the question concerning a single function
capable of dynamically allocating memory to vectors of different data types (1
data type per vector, obviously).  Just so people don't think I am ignoring
their posts, I will post a quick follow-up.  First of all, I am running this
"software" (probably too grand a term for what it is I am actually doing) on
on assorted Sun workstations.  To make matters somewhat more confusing, the
operating system that I was accustomed to (Sun OS 4.1.x) has been updated to
Solaris 2.x and in the process, such things as compilers and libraries are also
getting changed or updated.  I am attempting to make my code meet the strictest
of the ANSI C requirements so that all modern compilers will compile it without
complaining.  I have been flip-flopping back and forth between the gcc compiler
and the new SunPro 2.0.1 cc compiler.  I will post a much more detailed summary
when the responses die down some, but for now, the general trend seems to define
a macro that sets up the memory allocation and data type size and remove the
error handling to another part of the program.  I have also had several replies
indicating that should I switch to C++, this particular issue could be easily
handled.  Unfortunately, I am an aerospace student first and a mostly self
taught C programmer second, so this is not going to happen in the immediate
future (though I would like to learn C++).  Many thanks to those who have
responded so far!  I appreciate your time, and judging by the number of replies,
many individuals have run accross this issue before.  I will post a more
complete summary in a few days.  Thanks again!

-Brian



Wed, 26 Feb 1997 14:33:27 GMT  
 One memory allocation function - multiple data types?
There is something people often do in C, and I have never understood why.
It is a standards related issue, and it came up in a recent posting to
comp.std.c.


Quote:
>void MEMORY_FLOAT_1D (int length, float **vector) {
>        if ((*vector = (float *) malloc(sizeof(float) * length))==NULL) {
>           perror("Trouble mallocing memory for vector!");
>           exit (-1);
>        }
>}
>By the way, I am using the gcc compiler
>on Sun stations running Solaris if it should happen to make a difference.

In no version of UNIX that I have used (V7, 4.1BSD, 4.2BSD, 4.3BSD,
SVr1, SVr2, SVr3, SVr4) has it ever made sense to call exit(-1).  The
manual pages for exit() and wait() make it perfectly clear:
"the low order 8 bits of the argument that the child process passed to
exit()" are returned to the parent.  The Bourne shell reports these
numbers as 0..255.  So a shell script that does
        foo bar ugh
        case $? in
            0)  echo foo worked ;;
           -1)  echo foo reported -1 ;;
           -2)  echo foo reported -2 ;;
            *)  echo foo reported $? which I do not understand ;;
        esac
will *never* execute the -1 case.  What you get is
        foo reported 255 which I do not understand
In fact, when I try "exit -1" in sh, it says "bad number"...

To me, it makes no sense to pass a specific number to exit() when you
_know_ that you won't be able to get the _same_ number on the other end.
For what it's worth, the exit status is also an 8-bit non-negative
number in DOS.  To quote p80 of "Microsoft MS-DOS Programmer's Reference"
(version 6.0) "By convention, a return value of zero indicates success;
_increasingly_ large nonzero values indicate increasingly severe errors"
(int 21h func 4ch => exit, int 21h func 4dh => wait, sort of) and the
.BAT "IF ERRORLEVEL n" command interprets return codes as non-negative.
As I recall it, IBM CMS also interprets exit() status as non-negative.

If someone is seriously trying to write code to the standard, there are
three standard values you can pass to exit():
        EXIT_FAILURE            (typical UNIX value: +1)
        EXIT_SUCCESS            (might NOT be 0 on some systems)
        0                       ("grandfathered"; avoid in new code)

If you stick to these, you don't have to worry about the valid range
of numbers for your particular system.
--
The party that took Australia into Vietnam wants to smash the inner-city
yacht school and put a Grand Prix in its place.  They don't change.



Sun, 02 Mar 1997 16:53:52 GMT  
 One memory allocation function - multiple data types?

Quote:


>>Does anyone know of a method that would allow me to pass the data type
>>required for an array to the function so that I could use just a single
>>function?  Something along the lines of:

>>void MEMORY_FLOAT_1D (char *datatype, int length, float **vector) {

>>where datatype indicates either int, float or unsigned char.  My apologies
>>If this seems to be a basic question, but much of my C programming ability
>>is self taught, and passing data types and dynamic memory allocation are
>>stretching that ability a bit thin!  By the way, I am using the gcc compiler
>>on Sun stations running Solaris if it should happen to make a difference.
>>Many thanks for any help!
>>-Brian

>    There're 2 ways

There is actually another way.  With some clever token pasting
macros, you can emulate the C++ template feature with C. I haven't tested
this code, but you should get the general idea. Can anyone think of why this
woulnd't work?

#define DECLARE_ALLOCATE(DATATYPE) \
DATATYPE * allocate_##DATATYPE (size_t length) \
{ \
   return (DATATYPE *)malloc(sizeof(DATATYPE) * length); \

Quote:
}

#define PROTOTYPE_ALLOCATE(DATATYPE) \
DATATYPE * allocate_##DATATYPE (size_t length); \

then, in your header file, use a PROTOTYPE_ALLOCATE for each type
you want to allocate:
PROTOTYPE_ALLOCATE(float)
PROTOTYPE_ALLOCATE(char)

Then, in one of your c files put
DECLARE_ALLOCATE(float)
DECLARE_ALLOCATE(char)

then you can allocate an array for each type with calls to:

float * foo;
char *bar;

foo = allocate_float(100);
bar = allocate_char(99);

2D stuff would be a little more work, but not much more.

#define DECLARE_2D_ALLOCATE (DATATYPE) \
DATATYPE ** allocate_2d##DATATYPE (dim1, dim2) \
{ \
  DATATYPE **tmp; \
  int i; \
\
  tmp = (DATATYPE **) malloc (sizeof(DATATYPE *) * dim1); \
\
  if (!tmp) \
     error_handler(); \
\
  for (i=0;i<dim2;i++) { \
     tmp[i] = (DATATYPE *) malloc (sizeof (DATATYPE) * dim2); \
     if (!tmp1[i]) \
        error_handler(); \
     } \
\
  return tmp; \

Quote:
}

Again, I didn't check this for correctness, and it isn't optimized for
speed, just clarity.

The biggest drawback to this approach is that it can be *really*
difficult to debug errors in the macros because you have no idea where
the error really lies (the de{*filter*} or compiler will always report an
error at the line where DECLARE_ALLOCATE for that particular datatype
occurs.  Welcome to OOP in C.

Hope that helped,
-Eric
--

               Snail Mail: 33021 Georgia Tech Station,  Atlanta, GA 30213 USA
             URL: http://www.*-*-*.com/
Georgia Institute of Technology  CoC, IMAGINE, GVU, GTRI, the list goes on...



Sun, 02 Mar 1997 23:21:59 GMT  
 One memory allocation function - multiple data types?

Quote:
> If someone is seriously trying to write code to the standard, there are
> three standard values you can pass to exit():
>    EXIT_FAILURE            (typical UNIX value: +1)
>    EXIT_SUCCESS            (might NOT be 0 on some systems)
>    0                       ("grandfathered"; avoid in new code)
> If you stick to these, you don't have to worry about the valid range
> of numbers for your particular system.

If only that were true in practice!  On some (old, busted, but still-in-use)
systems, EXIT_FAILURE is 0.  I would suggest:

        #if HAVE_STDLIB_H
        #       include <stdlib.h>
        #endif

        #if !EXIT_FAILURE
        #       undef EXIT_FAILURE
        #       define EXIT_FAILURE 1
        #endif

where HAVE_STDLIB_H is 1 on a standard-conforming system.
GNU autoconf will configure HAVE_STDLIB_H for you automatically.



Mon, 03 Mar 1997 03:49:52 GMT  
 One memory allocation function - multiple data types?

Quote:

>        #if !EXIT_FAILURE
>        #       undef EXIT_FAILURE
>        #       define EXIT_FAILURE 1
>        #endif

I would avoid {*filter*}ling over definitions like this unless you know
precisely why it is set to zero. There may have been a very good reason for
it.

--
-----------------------------------------


-----------------------------------------



Tue, 04 Mar 1997 20:07:00 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. one matrix op fcn lib, multiple data types

2. Tree memory allocation, pool memory allocation

3. passing more than one type of argument to one function

4. Which one is more efficient, memory allocation or buffer

5. SUMMARY: Memory allocation / data access

6. Memory allocation / data access

7. allocating memory in one function and freeing it with another function

8. Multiple extensions for one doc type

9. Combining Multiple Memory Models into one Library

10. multiple users of one data structure

11. Multiple Threads accessing one data structure??????

12. Varargs memory allocation function - is this strictly conforming?

 

 
Powered by phpBB® Forum Software