Passing pointers for memory allocation inside a function? - c

I need to allocate arrays of structures in a bunch of different places in my program, thus putting the work inside a function (VS 2010). Compiler gives warning about uninitialized variable used. So how do I pass it, and how to declare it in the function. I've tried many variations of "&" and "*", to no avail.
(I apologize in advance if my code causes any form of nausea...I'm an English major.)
struct s_stream {
int blah;
};
void xxyz(void)
{
struct s_stream **StreamBuild;
char *memBlock_1;
xalloc(StreamBuild, memBlock_1, 20);
}
void xalloc(struct s_stream **StreamStruct, char *memBlock, int structCount)
{
int i = sizeof(struct s_stream *);
if ((StreamStruct=(struct s_stream **) malloc(structCount * i)) == NULL)
fatal("failed struct pointer alloc");
int blockSize = structCount * sizeof(struct s_stream);
if ((memBlock = (char *) malloc(blockSize)) == NULL)
fatal("failed struct memBlock alloc");
// initialize all structure elements to 0 (including booleans)
memset(memBlock, 0, blockSize);
for (int i = 0; i < structCount; ++i)
StreamStruct[i]=(struct s_stream *) &memBlock[i*sizeof(struct s_stream) ];
}

I'm not exactly sure I understand your question, but it seems like you want a function that will create a dynamically allocated array of struct s_stream objects and return them to the caller. If that's the case, it's pretty easy:
void easiest(void)
{
struct s_stream *array = malloc(20 * sizeof(struct s_stream));
}
You could move the malloc() off into its own function and return the pointer:
void caller(void)
{
struct s_stream *array = create_array(20);
}
struct s_stream *create_array(int count)
{
return malloc(count * sizeof(struct s_stream));
}
Or if you insist on passing the array as a parameter:
void caller(void)
{
struct s_stream *array;
create_array(&array, 20);
}
void create_array(struct s_stream **array, int count)
{
*array = malloc(count * sizeof(struct s_stream));
}

You are passing a copy of the pointer memBlock_1 to xalloc, so the address returned by malloc is written to the copy and never reaches the calling function. Since you presumably want the address to be available to xxyz in memBlock_1, you have to pass a pointer-to-pointer-to-char as the second argument,
void xalloc(..., char **memBlock, ...)
and call it with xalloc(..., &memBlock_1, ...);. In the body of xalloc, replace all occurrences of memBlock with *memblock, e.g. (*memblock = malloc(blockSize)) == NULL (no need to cast).
Analogously, the StreamStruct parameter of xalloc never changes the StreamBuild pointer-to-pointer-to-struct s_stream in xxyz. If I interpret your intentions correctly, you would also have to add a pointer layer to that parameter, void xalloc(struct s_stream ***StreamStruct, ..., ...), pass the address of StreamBuild in the call, xalloc(&StreamBuild, ..., ...) and dereference the pointer in the function body, e.g. (*StreamStruct = malloc(structCount * i)) == NULL.

Is there any reason you're not using a regular array? For example;
struct s_stream* streamArray = malloc(sizeof(s_stream*structCount));
Then you have an array of s_stream you can just access with streamArray[0] to streamArray[structCount-1] without dereferencing any extra pointers.

Related

Malloc within function not changing pointer value

So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}

How to pass structure to function to allocate memory

As the title says i want to pass structure to function and allocate memory, maybe it's a stupid question but i can't find the answer..
structName *allocate_memory( int *numPlayers,structName )
{
structName *retVal = malloc( sizeof(struct structName) * (*numPlayers) );
return retVal;
}
The problem is in parameters structName what should go there?
if you need the full code i can post it but i think there is no need..
You can't pass in a type as a parameter. But you can pass in its size:
void *allocate_memory( int *numPlayers, size_t struct_size)
{
void *retVal = malloc( struct_size * (*numPlayers) );
if (!retVal) {
perror("malloc failed!");
exit(1);
}
return retVal;
}
Then call it like this:
struct mystruct *s = allocate_memory(&numPlayers, sizeof(struct mystruct));
Or you just do this instead, assuming you want the memory initialized to all 0:
struct mystruct *s = calloc(numPlayers, sizeof(struct mystruct));
You can use a void pointer there, void can take anything...hope it helps....
You have two options, the first returning a new pointer (see allocate_memory) and the second is to fill in an existing pointer (see allocate_memory2. In both cases I converted numPlayers to int because it isn't necessary to provide by reference
struct structName *allocate_memory(int numPlayers)
{
struct structName *retVal = malloc(sizeof(struct structName) * numPlayers);
return retVal;
}
void allocate_memory2(struct structName **target, int numPlayers)
{
*target = malloc(sizeof(struct structName) * numPlayers);
}
int main(int argc, char** argv)
{
struct structName *str;
struct structName *str2;
//After this line str is a valid pointer of size 20*sizeof(struct structName)
str = allocate_memory(20);
//After this line str2 is a valid pointer of size 20*sizeof(struct structName)
allocate_memory2(&str2, 20);
}
You cannot pass a type as a parameter to a function.
You basically have two options realizing your allocate_memory function:
Instead of passing the name of the type simply pass the size of the type:
void *allocate_memory( int *numPlayers, size_t size). But this is only a trivial wrapper for malloc.
You could write a macro #define allocate_memory(num, type) (malloc(num * sizeof(type))) to do the job.
Maybe you're looking for a combination of both if you want to track some statistics of the memory allocated or do additional checks:
#define allocate_memory(num, type) (my_malloc((num), sizeof((type))))
void *my_malloc(int num, size_t size)
{
void *pMem = malloc(num * size);
if (pMem == NULL)
{
/* do error handling */
}
return (pMem);
}
You can use the above macro as follows:
pInt = allocate_memory(5, int); // allocates 5 integers
pStruct = allocate_memory(10, some_struct); // allocates 10 some_structs

Creating function out of realloc() function

I would like to create a function that will reallocate 2D array of typedef struct
typedef struct hero_data{
char name[254];
char title[254];
int encoding;
int startstr;
double incstr;
int startdex;
double incdex;
int startintel;
double incintel;
int basemindmg,basemaxdmg;
double bat;
double basearmor;
struct hero_data *next;
struct hero_data *Class;
}hero;
typedef struct parameters{
int toughtotal;
int nimbletotal;
int smarttotal;
int skeptictotal;
int mystictotal;
int cursedtotal;
int brutetotal;
int shreddertotal;
int vanillatotal;
int typetotal;
int typenum;
hero **smart[];
hero **nimble[];
hero **tough[];
hero **type[][];
hero **skeptic[][];
hero **mystic[][];
hero **cursed[][];
hero **brute[][];
hero **shredder[][];
hero **vanilla[][];
}Parameters;
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p = realloc(p,sizeof(Parameters *) * typenum);
for ( i = 0; i < typenum; i++)
{
p[i] = realloc(p[i],sizeof(Parameters) * typetotal);
}
}
The function above shall be called like: void reallocation(p->type,p->typenum,p->typetotal);
So, by substituting the parameters of the function correctly, I expect the function to look like:
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p->type = realloc(p->type,sizeof(Parameters *) * p->typenum);
for ( i = 0; i < p->typenum; i++)
{
p->type[i] = realloc(p->type[i],sizeof(Parameters) * p->typetotal);
}
}
The typedef struct named Parameters contains int typenum, int typetotal, and the 2D arrays that shall be initialized through realloc().
When I try to compile, I am getting an error in Tiny C (Windows): *The file is in C.
Error: cannot cast 'struct parameters' to 'void *'
(This apeears in the 'p[i] = realloc(p[i],sizeof(Parameters) * typetotal')
Can anyone help me re-write this function so that I will be able to realloc the 2D arrays within the Parameter *p?
I tried changing void reallocation(Parameters *p, ...) into void reallocation(Parameters *p[], ...) and the Error # 2 becomes the same message as Error #1 and it appears in the = of p[i] = realloc (...);
A large problem with your code is that you are assigning inequal types to each other, and you are also not checking the result of realloc. If this call were to fail, you will leak the memory allocated initially.
Assuming that your struct looks like
typedef struct {
int typenum;
int typetotal;
} Parameters;
Parameters *p;
p = malloc(10 * sizeof(*p));
if (p == NULL)
printf("Allocatation of memory failed!\n");
To properly reallocate to say 20, you could do something like this
reallocate_p(&p, 20);
Where the function is defined as
void reallocate_p(Parameters **p, int new_size)
{
Parameters *temp;
temp = realloc(*p, sizeof(*temp) * new_size);
if (temp==NULL) {
printf("Reallocatation of memory failed!\n");
// Handle error
}
*p = temp;
return;
}
Also note that we don't cast the return value of malloc() and realloc().
As to why, see this reference
OP is coding in C, but using a using a C++ compiler.
Code in C++
// C
// p = realloc(p,sizeof(Parameters *) * typenum);
// C++
p = (Parameters *) realloc(p,sizeof(Parameters *) * typenum);
OR
VS2012: set properties for each C file to use C compiler
How to compile C in visual studio 2010?
OP code has a memory leak when scaling down the pointer array table. The pointers in the table that are about to be loss due to realloc() need to be freed first.
for (i=old_typenum; i<typenum; i++) free(p[i]);
p = realloc(p,sizeof(Parameters *) * typenum);

Generic stack in plain C does not copies structures correct

So I have implemented a generic stack in Plain C. It should copy different type of data, inclusive structures. And by structures I have the problem.
So here's the structure of the stack:
/*
* Definite genStack as a structure.
* Pointer elems points to the objects lying on the stack
* The variable elemSize spiecifies the size of an element
* The variable logLength specifies the number of actually
* lying on the stack objects
* The variable allocLenght specifies the allocated size
*/
typedef struct{
void* elems;
int elemSize;
int logLength;
int allocLength;
}genStack;
Push and pop functions:
void GenStackPush(genStack *s, const void *elemAddr)
{
/* if stack is full - allocates more memory */
if (GenStackFull(s))
{
GenStackAlloc(s, s->elemSize);
}
memcpy((char*) (s->elems)+(s->logLength), elemAddr, sizeof(*elemAddr));
s->logLength++;
}
void GenStackPop(genStack *s, void *elemAddr)
{
if(GenStackEmpty(s))
{
fprintf(stderr, "Can't pop element from stack: stack is empty.\n");
} else
{
s->logLength--;
memcpy((void*) elemAddr, (s->elems)+(s->logLength), sizeof(s->elems[s->logLength]));
}
}
Simple structures test:
gentest.h:
#ifndef GENTEST1_H
#define GENTEST1_H
typedef struct {
char* name;
int age;
char gender;
}person;
#endif
gentest.c:
#include <stdio.h>
#include <stdlib.h>
#include "gentest1.h"
#include "genstacklib.h"
int main(int argc, char* argv[])
{
genStack StructStack;
person testPerson[5];
person* newPerson;
person* test;
int i;
newPerson = (void*) malloc (sizeof(person));
testPerson[0].name = "Alex";
testPerson[0].age = 21;
testPerson[0].gender = 'm';
testPerson[1].name = "Vanja";
testPerson[1].age = 20;
testPerson[1].gender = 'm';
testPerson[2].name = "sjrgsde";
testPerson[2].age = 11;
testPerson[2].gender = 'w';
testPerson[3].name = "wergsggsd";
testPerson[3].age = 99;
testPerson[3].gender = 'y';
testPerson[4].name = "adaasxx";
testPerson[4].age = 13;
testPerson[4].gender = 'g';
GenStackNew(&StructStack, sizeof(person));
printf("sizeof(person) = %lu\n", sizeof(person));
for (i = 0; i < 5; i++) {
newPerson = &testPerson[i];
GenStackPush(&StructStack, newPerson);
printf("Pushed: %s, %d, %c\n", newPerson->name, newPerson->age, newPerson->gender);
}
test = (void*) malloc (sizeof(person));
test->name = "test";
test->age = 0;
test->gender = 't';
while(!GenStackEmpty(&StructStack))
{
GenStackPop(&StructStack, test);
printf("Popped: %s, %d, %c\n", test->name, test->age, test->gender);
}
GenStackDispose(&StructStack);
return 0;
}
And here's the output I get:
./gentest1
elemSize = 16 GenStackInitialAlocationSize = 4
sizeof(person) = 16
Pushed: Alex, 21, m
Pushed: Vanja, 20, m
Pushed: sjrgsde, 11, w
Pushed: wergsggsd, 99, y
New size of alloc = 8
Pushed: adaasxx, 13, g
Popped: adaasxx, 0, t
Popped: wergsggsd, 0, t
Popped: sjrgsde, 0, t
Popped: Vanja, 0, t
Popped: Alex, 0, t
As you can see, I can receive names, but no age or gender. I've tried a lot of options, but still getting Segmentation Fault or the output from above. For moment, the output above is the finest output I get, but still not what I want.
The question is - how can I get the output I need?
Thanks in advance.
To avoid some questions:
sizeof(person) = s->elemSize
It is defined by creating the stack:
genstacklib.c:
void GenStackNew(genStack *s, int elemSize)
{
void* newElems;
/* Allocate a new array to hold the contents. */
newElems = (void*) malloc(elemSize * GenStackInitialAlocationSize);
printf("elemSize = %d\tGenStackInitialAlocationSize = %d\n",
elemSize, GenStackInitialAlocationSize);
if (newElems == NULL)
{
fprintf(stderr, "Error with allocating the stack.\n");
exit(1); /* Exit, returning error code. */
}
s->elems = newElems;
s->elemSize = elemSize;
s->allocLength = GenStackInitialAlocationSize;
s->logLength = 0; /*is empty*/
}
gentest.c:
GenStackNew(&StructStack, sizeof(person));
printf("sizeof(person) = %lu\n", sizeof(person));
your push function is copying sizeof(*elemAddr) and that is a void *, so it has the size of a pointer not the inteded size of a person struct. So you are probably copying only the first 4 bytes
As stated above the push is copying the wrong size of data. It should be elemSize.
The memcpy is also overwriting its own data. Something like this should work.
memcpy((char*) (s->elems)+(s->logLength)*elemSize, elemAddr, elemSize);
s->logLength++;
You're not using elemSize in all the relevant places...
void GenStackPush(genStack *s, const void *elemAddr)
{
...
memcpy((char*) (s->elems)+(s->logLength), elemAddr, sizeof(*elemAddr));
^^^^^^^^^^^^^^^^^
This is very wrong; the type of the expression *elemAddr is void, which is a constraint violation (sizeof may not be called on an expression of incomplete type, and void is an incomplete type). You will want to turn up the warning level on your compiler. I wrote a test program to compute sizeof on expressions of type void * and void, and I get a warning with gcc -pedantic. If I drop the -pedantic I don't get a warning, but the result I get for sizeof (void) is 1, which I'm pretty certain is not the size of a person. Why aren't you using s->elemSize here?
Secondly, why are you casting s->elems to char *?
EDIT
If I may offer some advice, I've womped up a few generic containers in the past, and here are the lessons I've come away with:
First, delegate all type-aware operations (allocation, deallocation, copy, compare, display, etc.) to separate functions, which are called via function pointers passed as parameters to the generic container's functions; i.e., a push would be defined like
GenStackPush(genStack *stack, const void *data, void *(*copy)(const void *))
{
stack->elems[++stack->logLength] = copy(data);
}
...
void *myIntCopyFunc(const void *data)
{
const int *inputData = (const int *) data;
int *copy = malloc(sizeof *copy);
if (copy)
*copy = *inputData;
return copy;
}
...
GenStackPush(&myIntStack, &intVal, myIntCopyFunc);
One issue you have with your person type is that you're not doing a deep copy of the name member; you're just copying a pointer value to the stack. In this case it's not a big deal since you're working with string literals, but if you were using, say, a local char [], you'd have problems. By writing a separate copy function for each type, you can deal with those sorts of issues, instead of trying to do a one-size-fits-all allocation in the container function itself.
Secondly, don't call your generic container functions directly; put a type-aware interface between you and the container (basically, the poor man's version of function overloading):
void pushInt(GenStack *stack, int intVal)
{
GenStackPush(stack, &intVal, myIntCopyFunc);
}
...
genStack myIntStack;
...
pushInt(&myIntStack, 5);
This gives you two benefits; first, it allows you to pass literal values as parameters (which you can't do with parameters of type void *). Secondly, it gives you a way to enforce type safety on your container. You can't accidentally push a value of the wrong type this way.
Is this a lot of extra work? Oh my yes. There's a lot of magic that has to happen under the hood for generic container types to work properly. If you're trying to replicate the same kind of functionality that you get with the C++ std::stack container type, you're going to be writing a lot of code.

array of type void

plain C have nice feature - void type pointers, which can be used as pointer to any data type.
But, assume I have following struct:
struct token {
int type;
void *value;
};
where value field may point to char array, or to int, or something else.
So when allocating new instance of this struct, I need:
1) allocate memory for this struct;
2) allocate memory for value and assign it to value field.
My question is - is there ways to declare "array of type void", which can be casted to any another type like void pointer?
All I want is to use "flexible member array" (described in 6.7.2.1 of C99 standard) with ability to casting to any type.
Something like this:
struct token {
int type;
void value[];
};
struct token *p = malloc(sizeof(struct token) + value_size);
memcpy(p->value, val, value_size);
...
char *ptr = token->value;
I suppose declaring token->value as char or int array and casting to needed type later will do this work, but can be very confusing for someone who will read this code later.
Well, sort of, but it's probably not something you want:
struct token {
// your fields
size_t item_size;
size_t length
};
struct token *make_token(/* your arguments */, size_t item_size, size_t length)
{
struct token *t = malloc(sizeof *t + item_size * length);
if(t == NULL) return NULL;
t->item_size = item_size;
t->length = length;
// rest of initialization
}
The following macro can be used to index your data (assuming x is a struct token *):
#define idx(x, i, t) *(t *)(i < x->length ? sizeof(t) == x->item_size ?
(void *)(((char *)x[1]) + x->item_size * i)
: NULL : NULL)
And, if you like, the following macro can wrap your make_token function to make it a little more intuitive (or more hackish, if you think about it that way):
#define make_token(/* args */, t, l) (make_token)(/* args */, sizeof(t), l)
Usage:
struct token *p = make_token(/* args */, int, 5); // allocates space for 5 ints
...
idx(p, 2, int) = 10;
Expanding on AShelly's answer you can do this;
/** A buffer structure containing count entries of the given size. */
typedef struct {
size_t size;
int count;
void *buf;
} buffer_t;
/** Allocate a new buffer_t with "count" entries of "size" size. */
buffer_t *buffer_new(size_t size, int count)
{
buffer_t *p = malloc(offsetof(buffer_t, buf) + count*size);
if (p) {
p->size = size;
p->count = count;
}
return p;
}
Note the use of "offsetof()" instead of "sizeof()" when allocating the memory to avoid wasting the "void *buf;" field size. The type of "buf" doesn't matter much, but using "void *" means it will align the "buf" field in the struct optimally for a pointer, adding padding before it if required. This usually gives better memory alignment for the entries, particularly if they are at least as big as a pointer.
Accessing the entries in the buffer looks like this;
/** Get a pointer to the i'th entry. */
void *buffer_get(buffer_t *t, int i)
{
return &t->buf + i * t->size;
}
Note the extra address-of operator to get the address of the "buf" field as the starting point for the allocated entry memory.
I would probably do this:
struct token {
int type;
void *value;
};
struct token p;
p.value = malloc(value_size);
p.value[0] = something;
p.value[1] = something;
...
edit, actually you have to typecast those p.value[index] = somethings. And/or use a union to not have to typecast.
You can't have an array of 'void' items, but you should be able to do something like what you want, as long as you know value_size when you do the malloc. But it won't be pretty.
struct token {
int type;
void *value;
};
value_size = sizeof(type)*item_count;
struct token *p = malloc(sizeof(struct token) + value_size);
//can't do memcpy: memcpy(p->value, val, value_size);
//do this instead
type* p = (type*)&(p->value);
type* end = p+item_count;
while (p<end) { *p++ = someItem; }
Note that you need an extra address-of operator when you want to get the extra storage.
type *ptr = (type*)&(token->value);
This will 'waste' sizeof(void*) bytes, and the original type of value doesn't really matter, so you may as well use a smaller item. I'd probably typedef char placeholder; and make value that type.
following structure can help you.
struct clib_object_t {
void* raw_data;
size_t size;
};
struct clib_object_t*
new_clib_object(void *inObject, size_t obj_size) {
struct clib_object_t* tmp = (struct clib_object_t*)malloc(sizeof(struct clib_object_t));
if ( ! tmp )
return (struct clib_object_t*)0;
tmp->size = obj_size;
tmp->raw_data = (void*)malloc(obj_size);
if ( !tmp->raw_data ) {
free ( tmp );
return (struct clib_object_t*)0;
}
memcpy ( tmp->raw_data, inObject, obj_size);
return tmp;
}
clib_error
get_raw_clib_object ( struct clib_object_t *inObject, void**elem) {
*elem = (void*)malloc(inObject->size);
if ( ! *elem )
return CLIB_ELEMENT_RETURN_ERROR;
memcpy ( *elem, inObject->raw_data, inObject->size );
return CLIB_ERROR_SUCCESS;
}
More Details : clibutils
Array of type void is not supporting in c/c++.
Example like:
int main() {
void alexa[]; // error: declaration of ‘alexa’ as array of void
return 0;
}
Array of void pointer is supported in c/c++.
Example below:
int main(int argc, char argv*[])
{
void *alexa[100]; // Compiled successfully
return 0;
}

Resources