I am debugging some code and just wanted to make sure that the way I am setting a pointer to an array inside my struct is correct.
Here is an example of what I am trying to do:
typedef struct Foo
{
uint32_t *bar;
} Foo
int main(void)
{
Foo *foo;
uint32_t *bar[20];
foo = (Foo *)malloc(sizeof(Foo));
*bar = malloc(sizeof(uint32_t) * 20);
for(int i = 0; i < 20; i++)
{
bar[i] = (uint32_t*)malloc(sizeof(uint32_t));
}
foo->bar = *bar;
}
The code
uint32_t *bar[20];
declares bar as an array of 20 pointers to uint32_t which is probably not what you intended. Since you allocate the array dynamically with malloc, you should declare bar as a pointer rather than an array:
uint32_t **bar;
You may want to consider doing the memory allocation in a single malloc() rather than the piecewise approach you are using. For instance you might want to consider doing something like the following.
This allocates the memory needed in a single call to malloc() so that only a single call to free() is needed to release the memory. It is faster and tends to make the heap to be less fragmented and easier to manage.
typedef struct
{
uint32_t *bar[1]; // an array of size one that makes array syntax easy
} Foo;
Foo *FooCreateFoo (unsigned int nCount)
{
// create an array of pointers to uint32_t values along with the
// memory area for those uint32_t data values.
Foo *p = malloc (sizeof(uint32_t *) * nCount + sizeof(uint32_t) * nCount);
if (p) {
// we have memory allocated so now initialize the array of pointers
unsigned int iLoop;
uint32_t *pData = p->bar + nCount; // point to past the last array element
for (iLoop = 0; iLoop < nCount; iLoop++) {
// set the pointer value and initialize the data to zero.
*(p->bar[iLoop] = pData++) = 0;
}
}
return p;
}
int main(void)
{
Foo *foo = FooCreateFoo (20);
if (! foo) {
// memory allocation failed so exit out.
return 1;
}
// ... do things with foo by dereferencing the pointers in the array as in
*(foo->bar[1]) += 3; // increment the uint32_t pointed to by a value of 3
free (foo); // we be done with foo so release the memory
}
Related
Let's say I have a struct for implementing vectors in C like this:
struct cvector {
unsigned int size; // indicates number of element in the vector
unsigned int capacity; // indicates length of the array
int* data; // array to store the actual data
};
typedef struct cvector* cvector;
Then I create this vector like this:
cvector cvector_create() {
cvector retval = (cvector)malloc(sizeof(struct cvector));
retval->capacity = 8;
retval->size = 0;
retval->data = (int*)malloc(retval->capacity * sizeof(int));
return retval;
}
I use malloc for both allocating memory for the struct and for allocating memory for the internal int array.
For freeing up my cvector I use this:
void cvector_free(cvector vector) {
free(vector);
}
My question is, do I need to free the internal int array as well separately like this: free(vector->data) or is freeing up only the struct is enough?
Yes, you need to free also vector->data, the rule is: one call to free per each call to malloc
if you are under C99, you can use flexible array members:
struct cvector {
unsigned int size; // indicates number of element in the vector
unsigned int capacity; // indicates length of the array
int data[]; // array to store the actual data
};
Notice that int data[]; must be the last member of the struct.
Then, you reserve space in this way:
cvector cvector_create() {
cvector retval = malloc(sizeof(struct cvector) + (sizeof(int) * 8));
retval->capacity = 8;
retval->size = 0;
return retval;
}
Now, calling free(vector) is enough since vector and vector->data are on the same block.
I'm pretty bad at remembering C rules with structs. Basically, I have a struct like this:
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
Where the char* ptr will only be one character max.
In my program, I have to allocate and free memory to a fake disk (declared globally as char disk[100];) using my own functions:
char disk[100];
void disk_init() {
for(int i = 0; i < 100; ++i) {
disk[i] = memory[i] = 0;
}
}
struct Xalloc_struct* Xalloc(int size) {
// error checking
// ...
// run an algorithm to get a char* ptr back to a part of the global disk
// array, where index i is the index where content at disk[i] starts
char* ptr = &disk[i];
struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
ret->size = size;
ret->ptr = malloc(sizeof(char));
ret->ptr = ptr;
return ret;
}
int Xfree(void* ptr) {
struct Xalloc_struct* p = (struct Xalloc_struct*) ptr;
int size = p->size;
int index = *(p->ptr);
// .. more stuff here that uses the index of where p->ptr points to
free(p->ptr);
free(p);
return 0;
}
int main() {
disk_init();
struct Xalloc_struct* x = Xalloc(5);
Xfree(x);
return 0;
}
When this compiles I get quite a few errors:
error: invalid application of ‘sizeof’ to incomplete type ‘struct Xalloc_struct’
struct Xalloc_struct *ret = malloc(sizeof(struct Xalloc_struct));
^
error: dereferencing pointer to incomplete type
ret->size = size;
^
error: dereferencing pointer to incomplete type
free(x->ptr);
^
error: dereferencing pointer to incomplete type
int size = cast_ptr->size;
^
error: dereferencing pointer to incomplete type
int free_ptr = *(cast_ptr->ptr);
^
So, how should I be allocating and deallocating these structs? And how can I modify / edit what they contain?
First problem is Xalloc_struct is a type, not the name of a struct. You declared that type with this:
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
typedef is of the form typedef <type name or struct definition> <name of the type>. So you declared the type Xalloc_struct to be struct { char *ptr; int size; }.
That means you use it like any other type name: Xalloc_struct somevar = ...;.
Had you declared the struct with a name...
struct Xalloc_struct {
char* ptr;
int size;
};
Then it would be struct Xalloc_struct somevar = ...; as you have.
The rule of thumb when allocating memory for an array (and a char * is an array of characters) is you allocate sizeof(type) * number_of_items. Character arrays are terminated with a null byte, so for them you need one more character.
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = malloc(sizeof(char) * num_characters+1);
But if you're only storing one character, there's no need for an array of characters. Just store one character.
typedef struct {
char letter;
int size;
} Xalloc_struct;
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->letter = 'q'; /* or whatever */
But what I think you're really doing is storing a pointer to a spot in the disk array. In that case, you don't malloc at all. You just store the pointer like any other pointer.
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
Xalloc_struct *ret = malloc(sizeof(Xalloc_struct));
ret->ptr = &disk[i];
Then you can read that character with ret->ptr[0].
Since you didn't allocate ret->ptr do not free it! That will cause a crash because disk is in stack memory and cannot be free'd. If it were in heap memory (ie. malloc) it would probably also crash because it would try to free in the middle of an allocated block.
void Xalloc_destroy(Xalloc_struct *xa) {
free(xa);
}
Here's how I'd do it.
#include <stdio.h>
#include <stdlib.h>
char disk[100] = {0};
typedef struct {
char *ptr;
int idx;
} Disk_Handle_T;
static Disk_Handle_T* Disk_Handle_New(char *disk, int idx) {
Disk_Handle_T *dh = malloc(sizeof(Disk_Handle_T));
dh->idx = idx;
dh->ptr = &disk[idx];
return dh;
}
static void Disk_Handle_Destroy( Disk_Handle_T *dh ) {
free(dh);
}
int main() {
Disk_Handle_T *dh = Disk_Handle_New(disk, 1);
printf("%c\n", dh->ptr[0]); /* null */
disk[1] = 'c';
printf("%c\n", dh->ptr[0]); /* c */
Disk_Handle_Destroy(dh);
}
What you are attempting to accomplish is a bit bewildering, but from a syntax standpoint, your primary problems are treating a typedef as if it were a formal struct declaration, not providing index information to your Xalloc function, and allocating ret->ptr where you already have a pointer and storage in disk.
First, an aside, when you are specifying a pointer, the dereference operator '*' goes with the variable, not with the type. e.g.
Xalloc_struct *Xalloc (...)
not
Xalloc_struct* Xalloc (...)
Why? To avoid the improper appearance of declaring something with a pointer type, (where there is no pointer type just type) e.g.:
int* a, b, c;
b and c above are most certainly NOT pointer types, but by attaching the '*' to the type it appears as if you are trying to declare variables of int* (which is incorrect).
int *a, b, c;
makes it much more clear you intend to declare a pointer to type int in a and two integers b and c.
Next, in Xfree, you can, but generally do not want to, assign a pointer type as an int (storage size issues, etc.) (e.g. int index = *(p->ptr);) If you need a reference to a pointer, use a pointer. If you want the address of the pointer itself, make sure you are using a type large enough for the pointer size on your hardware.
Why are you allocating storage for ret->ptr = malloc(sizeof(char));? You already have storage in char disk[100]; You get no benefit from the allocation. Just assign the address of the element in disk to ptr (a pointer can hold a pointer without further allocation) You only need to allocate storage for ret->ptr if you intend to use the memory you allocate, such as copying a string or multiple character to the block of memory allocated to ret->ptr. ret->ptr can store the address of an element in data without further allocation. (it's unclear exactly what you intend here)
You are free to use a typedef, in fact it is good practice, but when you specify a typedef as you have, it is not equivalent to, and cannot be used, as a named struct. That is where your incomplete type issue arises.
All in all, it looks like you were trying to do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char* ptr;
int size;
} Xalloc_struct;
char disk[100] = "";
Xalloc_struct *Xalloc (int size, int i) {
char *ptr = &disk[i];
Xalloc_struct *ret = malloc (sizeof *ret);
ret->size = size;
// ret->ptr = malloc (sizeof *(ret->ptr)); /* you have a pointer */
ret->ptr = ptr;
return ret;
}
int Xfree (void *ptr) {
Xalloc_struct *p = (Xalloc_struct *) ptr;
// int size = p->size; /* unused */
// int index = *(p->ptr); /* what is this ?? */
// .. more stuff here that uses the index of where p->ptr points to
// free (p->ptr);
free (p);
return 0;
}
int main (void) {
int i = 0;
Xalloc_struct *x = Xalloc (5, i++);
Xfree(x);
return 0;
}
Look at the difference in how the typedef is used and let me know if you have any questions.
My code uses two structures, block and layout (which is a collection of an arbitrary number of blocks).
struct block{
char type;
unsigned short int loc;
unsigned short int size[2];
};
struct layout{
unsigned short int no;
struct block *blocks;
short int **moves;
};
I am using this function to quickly initialize (and partly fill) the structure layout, based a set of blocks:
struct layout init_layout(int block_no, struct block *blocks){
struct layout new_layout;
int i, j;
new_layout.no = (unsigned short int)block_no;
// the following two lines cause an memory corruption error
new_layout.blocks = (struct block *)malloc(block_no);
new_layout.moves = (short int **)malloc(block_no);
for(i = 0; i < block_no; i++){
new_layout.blocks[i] = blocks[i];
new_layout.moves[i] = (short int *)malloc(2);
for(j = 0; j < 2; j++)
new_layout.moves[i][j] = 0;
}
return new_layout;
}
So far, I do not see, that there is something wrong with it. However, when I call function like this
int main(int argc, char** argv){
// just some arbitrary values for 10 blocks
int size[2] = {2, 2};
struct block *blocks = (struct block *)malloc(10);
for(length = 0; length < 10; length++){
blocks[length] = init_block('R', 1, size);
}
struct layout puzzle;
puzzle = init_layout(10, blocks);
return 0;
}
I end up with an memory corruption error, as marked by the comment in init_layout().
What do I miss in my implementation?
When you are allocating memory for anything, you need to analyze, closely -- "What is it that I'm allocating memory for?"
Below, you incorrectly assume a cast of an arbitrary number block_no will adequately size the memory needed for both new_layout.blocks and new_layout.moves -- it won't:
new_layout.blocks = (struct block *)malloc(block_no);
new_layout.moves = (short int **)malloc(block_no);
What you are allocating for new_layout.blocks is actually space for struct block *blocks; (a pointer-to-struct-block), while you can malloc (block_no * sizeof (struct block)); to allocate space for block_no struct block, it is far better to allocate based upon what you are creating (i.e. space for an array new_layout.blocks (again a pointer-to-struct-block) which needs block_no * sizeof *new_layout.blocks bytes of memory to hold block_no of type struct block, e.g.:
new_layout.blocks = malloc(sizeof *new_layout.blocks * block_no);
new_layout.moves = malloc(sizeof *new_layout.moves * block_no);
(simply dereferencing the object you are allocating an array of, will accurate allow you to use sizeof to get the object (element) size for the array. (e.g. sizeof *new_layout.blocks) which you multiply by how many you need (e.g. sizeof *new_layout.blocks * block_no)
The same applies to:
new_layout.moves[i] = malloc(**new_layout.moves * 2);
(note: here you are allocating for 2 shorts, so you will need to dereference you pointer-to-pointer-to-short twice to be allocating for sizeof (short))
See Also: Do I cast the result of malloc? for thorough explanation.
For starters, this
new_layout.blocks = (struct block *)malloc(block_no);
should be
new_layout.blocks = malloc(block_no * sizeof *new_layout.blocks);
For the moves this is a bit more complicated.
Assuming short int **moves; should reference a certain number of int[2] the declaration is not optimal and better should be:
short int (*moves)[2]; /* Define a pointer to
an array with two elements of type short int. */
And allocation then should look like this:
new_layout.moves = malloc(block_no * sizeof *new_layout.moves);
Finally initialisation goes like this:
for(i = 0; i < block_no; i++){
new_layout.blocks[i] = blocks[i];
for(j = 0; j < sizeof new_layout.moves[0]/sizeof new_layout.moves[0][0]; j++)
new_layout.moves[i][j] = 0;
}
You might have noticed:
No memory allocation in the loop any more.
The magic number 2 only appears once.
:-)
I have a struct called menu_item that looks like:
struct menu_item
{
char name[ITEM_NAME_LEN+1];
};
And in main I declare an array of pointers to the struct (am I right about this part?):
struct menu_item * menu_items[NUM_MENU_ITEMS];
And also in main I'm trying to call:
init_menu(&menu_items[NUM_MENU_ITEMS]);
init_menu function looks like this:
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
However I'm getting a segmentation error, what am I doing wrong? Thanks in advance.
Take a closer look to your function.
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
You need to carry the size of the array in a second parameter in your function. However, NUM_MENU_ITEMS, seems to be a global #define, thus you don't need to carry a second parameter.
Then you are accessing an out of bound cell, menu_items[NUM_MENU_ITEMS]. I assume you know that the indexing starts from 0 and ends at NUM_MENU_ITEMS-1.
In your function, you need, inside a loop, to allocate memory. Moreover, you don't need to cast what malloc returns.
So, for example, you could do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ITEM_NAME_LEN 15
#define NUM_MENU_ITEMS 3
// Define the struct before main
struct menu_item {
char name[ITEM_NAME_LEN + 1];
};
// Give a synonym. Now struct menu_item is the same with menu_item_t.
// Notice the _t extension, which implies that this is a typedef.
typedef struct menu_item menu_item_t;
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), allocate memory for
* every cell of the array.
*/
void init_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// for every cell of our array, allocate memory
p[i] = malloc(sizeof(menu_item_t));
// check that allocation for the i-th cell is OK
if(!p[i]) {
printf("Error in allocating %d item!\n\n", i);
return;
}
}
}
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), de-allocate memory for
* every cell of the array.
*/
void delete_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// free the memory we had allocated for the i-th cell
free(p[i]);
// set the pointer to NULL
p[i] = NULL;
}
}
void fill(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
strcpy(p[i]->name, "myitem");
}
}
void print(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
printf("%s\n", p[i]->name);
}
}
int main(void) {
// Declare an array of pointers of menu_items_t.
// The size of the array is NUM_MENU_ITEMS
menu_item_t *menu_items[NUM_MENU_ITEMS];
init_menu(menu_items);
fill(menu_items);
print(menu_items);
delete_menu(menu_items);
return 0;
}
When I deal with structs, I always have this example on mind.
You are calling your function as
init_menu(&menu_items[NUM_MENU_ITEMS]);
This does not make sense. Expression &menu_items[NUM_MENU_ITEMS] creates a pointer to element with index NUM_MENU_ITEMS. Such element does not exist. Your array has elements numbered from 0 to NUM_MENU_ITEMS - 1. There's no element with index NUM_MENU_ITEMS.
Expression &menu_items[NUM_MENU_ITEMS] produces a pointer into the uncharted memory past the end of the array. You pass that pointer to the function. Later you are trying to use that pointer as if it were your array. You write into that uncharted memory, which causes a crash.
If you want to pass your array to the function, just pass it. Your function should be called as
init_menu(menu_items);
That's it. There's no need to create any pointers to any elements with strange indices.
Later, inside your function you are again trying to access element NUM_MENU_ITEMS of your array
menu_items[NUM_MENU_ITEMS] = ...
This does not make sense either for the very same reasons.
How to return 1000 variables from a function in C?
This is an interview question asked which I was unable to answer.
I guess with the help of pointers we can do that. I am new to pointers and C can anyone give me solution to solve this problem either using pointers or different approach?
Pack them all in a structure and return the structure.
struct YourStructure
{
int a1;
int b2;
int z1000;
};
YouStructure doSomething();
If it's 1000 times the same type (e.g. int's):
void myfunc(int** out){
int i = 0;
*out = malloc(1000*sizeof(int));
for(i = 0; i < 1000; i++){
(*out)[i] = i;
}
}
This function allocates memory for 1000 integers (an array of integers) and fills the array.
The function would be called that way:
int* outArr = 0;
myfunc(&outArr);
The memory held by outArr must be freed after use:
free(outArr);
See it running on ideone: http://ideone.com/u8NX5
Alternate solution: instead of having myfunc allocate the memory for the integer array, let the caller do the work and pass the array size into the function:
void myfunc2(int* out, int len){
int i = 0;
for(i = 0; i < len; i++){
out[i] = i;
}
}
Then, it's called that way:
int* outArr = malloc(1000*sizeof(int));
myfunc2(outArr, 1000);
Again, the memory of outArr must be freed by the caller.
Third approach: static memory. Call myfunc2 with static memory:
int outArr[1000];
myfunc2(outArr, 1000);
In that case, no memory has to be allocated or freed.
Array Pointer approach:
int * output(int input)
{
int *temp=malloc(sizeof(int)*1000);
// do your work with 1000 integers
//...
//...
//...
//ok. finished work with these integers
return temp;
}
Struct pointer approach:
struct my_struct
{
int a;
int b;
double x;
...
//1000 different things here
struct another_struct;
}parameter;
my_struct * output(my_struct what_ever_input_is)
{
my_struct *temp=malloc(sizeof(my_struct));
//...
//...
return temp;
}
This is how you do it in C.
void func (Type* ptr);
/*
Function documentation.
Bla bla bla...
Parameters
ptr Points to a variable of 'Type' allocated by the caller.
It will contain the result of...
*/
If your intention wasn't to return anything through "ptr", you would have written
void func (const Type* ptr);
instead.