I have to implement game of life, it is almost complete, the last thing I want to do is to allocate my field dynamical. I'm working under Windows, got no Valgrind and I don't no what's the error in my code. Eclipse shows only that the process is not functional anymore.
Can anyone tell me, what's the problem in my code? Or maybe I don't need a 2 dim. array for game of life field?
struct game_field {
int length;
int **field;
};
static struct game_field *new_game_field(unsigned int l) {
struct game_field *pstField;
pstField = calloc(1, sizeof(struct game_field));
pstField->length = l;
pstField->field = malloc(l * sizeof(int*));
for( int i = 0; i < l; i++ ) {
pstField->field[i] = malloc(l * sizeof(int));
if(NULL == pstField->field[i]) {
printf("No memory for line %d\n",i);
}
}
return pstField;
}
You should think a little bit about the structures and what you are storing.
For the game of life you need to know the state of the cell on the board which is indicated by and integer so your struct should become:
struct game_field {
int length;
int *field;
};
And once you know the dimensions of the field you should allocate it once:
struct game_field *gf = calloc(1, sizeof(struct game_field));
gf->length = <blah>;
gf->field = malloc(gf->length*gf->length*sizeof(int));
This way you have an array of integers that you can use as your board.
The first malloc should be:
pstField->field = malloc(l * sizeof(int*));
Your array is int**, so the first level of allocation is an int*.
Edit: Well, I've tested your code and it does not crash for me. The problem might be somewhere else.
Here's a modification of your code that allocates the field in one block, but still lets you use array brackets for both dimensions:
struct game_field {
int length;
int **field;
};
static struct game_field *new_game_field(unsigned int len)
{
struct game_field *pstField;
pstField = malloc(sizeof(struct game_field));
pstField->length = len;
/* allocate enough space for all the row pointers + the row contents */
pstField->field = malloc((len * sizeof(int *)) + (len * len * sizeof(int)));
/* point the row pointers (at the start of the block) at the row contents
* (further into the block). */
for (int i = 0; i < len; i++)
pstField->field[i] = (int *)(&field[len]) + (i * len);
return pstField;
}
This way you can free the field in one shot:
void free_game_field(struct game_field *gf)
{
free(gf->field);
free(gf);
}
And you can keep the bracket notation to access the elements:
int row7col3 = gf->field[7][3];
Note that what you have (here as well as in your original code) is not exactly a two-dimensional array, but an array of pointers to arrays of integers
(there is a difference, but the arr[x][y] notation can work for either one).
Related
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 the following pointer to structure
struct ALIST
{
short sPeriod;
long lDate;
}*list_ptr;
list_ptr = malloc(sizeof(*list_ptr));
Now if I have a global variable sIndex which I initialize to zero, is it possible to do this?
(list_ptr + sIndex)->sPeriod = period_variable;
(list_ptr + sIndex)->lDate = date_variable;
sIndex++
Is there a more efficient method?
This looks like you want to allocate a dynamic array. Make a size variable and set it to your starting size for the array.
Something like:
size_t list_size = 10;
struct ALIST list_ptr = 0;
size_t i;
list_ptr = malloc(sizeof(*list_ptr) * list_size);
for(i=0; i<list_size; ++i) {
list_ptr[i].sPeriod = period;
list_ptr[i].lDate = date;
}
Now, if you don't know the size of the array then what you want ends up looking a lot like a C++ std::vector.
I'd build a C version that wraps the necessary information in a struct. Use realloc to resize it.
It might look like (NOTE THAT THIS IS COMPLETELY UNTESTED):
struct dynamic_ALIST {
struct ALIST *array;
size_t size;
size_t capacity;
};
void dynamic_ALIST_construct(struct dynamic_ALIST *x, size_t initial_size)
{
x->array = 0;
x->size = 0;
x->capacity = 0;
dynamic_ALIST_reserve(x, initial_size);
}
void dynamic_ALIST_reserve(struct dynamic_ALIST *x, size_t size)
{
struct ALIST *tmp = realloc(x->array, sizeof(*tmp) * size);
if(!tmp) abort();
x->array = tmp;
x->capacity = size;
}
struct ALIST* dynamic_ALIST_get(struct dynamic_ALIST *x, size_t offset)
{
if(offset < x->size) {
return x->array + offset;
}
if(offset < x->capacity) {
x->size = offset + 1;
return x->array + offset;
}
dynamic_ALIST_reserve(x, offset+1);
return dynamic_ALIST_get(x, offset);
}
Then you could use it like:
void f()
{
size_t item_index = 0;
struct dynamic_ALIST list;
FILE *fp = fopen("filename");
dynamic_ALIST_construct(list, 0);
while( read_item(fp, dynamic_ALIST_get(list,item_index)) ) {
item_index++;
}
fclose(fp);
}
You can make all kinds of changes to that. The get function might return an error instead of automatically creating new entries. You might make another function that increases the size. You might want to have a function that sets all the values to zero before returning new memory.
If you have a lot of different structs to wrap up you can put ALL of the above dynamic_ALIST struct, and construct, reserve, get functions into a macro. If you do it right then you just say:
NEW_DYNAMIC_STRUCT(ALIST);
And the preprocessor spits out a whole new copy with all the names changed.
I'll answer point by point:
Do those pointer manipulations only if you know what you are doing.
Assuming sIndex to be an int, with sIndex=0;, it is no problem but if you increment sIndex, you don't have that space allocated to use becuase you have malloc'd just one block.
You need to first do your allocation appropriately if you need to access multiple such blocks then:
list_ptr = malloc(sizeof(struct ALIST)*N); //replace N with the number of blocks you want
I have a structure called container that has two fields: labels and linked_to_containers; The field labels is designed to be a 2-dimensional array of int, and the field linked_to_containers is designed to be a 2-dimensional array of int pointers. On top of this, I also have an array of struct container that are dynamically created in the initiation program. I have the following code written down, but one thing I'm unsure about is the first malloc I used inside of the function container_init(). As the struct container still does not have its size initialized, is this the right way to do malloc for creating an array of struct container?
Please see my question in my comments in the code, and I will appreciate your feedback.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct container {
int *labels[2]; /* two-dimensional array of int */
int **linked_to_container[2]; /* two-dimensional array of pointers to label */
} container;
int get_next_container_index(int current_container_index, int max_index)
{
if (max_index - current_container_index >= 1)
{
return current_container_index + 1;
}
else
return 0; /* elements at two ends are linked */
}
container *allcontainers; /* an array for all containers */
void container_init(int num_containers, int column_num)
{
/* is this right to malloc memory on the array of container when the struct size is still unknown?*/
allcontainers = (container *) malloc(num_containers * sizeof(container));
int i;
for (i = 0; i < num_containers; i++)
{
container *current_container = &allcontainers[i];
current_container->labels[0] = malloc(column_num * sizeof(int));
current_container->labels[1] = malloc(column_num * sizeof(int));
current_container->linked_to_container[0] = malloc(column_num * sizeof(int *));
current_container->linked_to_container[1] = malloc(column_num * sizeof(int *));
int j;
for (j = 0; j < column_num; j++)
{
current_container->labels[0][j] = 0; /* initialize all labels to 0 */
current_container->labels[1][j] = 0;
int next_container = get_next_container_index(i, num_containers - 1); /* max index in all_containers[] is num_containers-1 */
current_container->linked_to_container[0][j] = &(allcontainers[next_container]->labels[0]);
}
}
The line in question seems perfectly fine to me, the size of struct container is well-known, because of its definition. The only size not known is the size of the arrays that the pointers in the struct will eventually point to, but that doesn't affect the size of the pointers themselves and thus also not the struct's size.
The only issue I see is here:
current_container->linked_to_container[0][j] = &(allcontainers[next_container]->labels[0]);
linked_to_container[0][j] is of type int*, but labels[0] is of type int* and therefore &(labels[0]) is of type int**. I am not sure what you try to accomplish here, but you probably need another index to labels[0][...] or & shouldn't be there.
I'm used to PHP, but I'm starting to learn C. I'm trying to create a program that reads a file line by line and stores each line to an array.
So far I have a program that reads the file line by line, and even prints each line as it goes, but now I just need to add each line to an array.
My buddy last night was telling me a bit about it. He said I'd have to use a multidimensional array in C, so basically array[x][y]. The [y] part itself is easy, because I know the maximum amount of bytes that each line will be. However, I don't know how many lines the file will be.
I figure I can make it loop through the file and just increment an integer each time and use that, but I feel that there might be a more simple way of doing it.
Any ideas or even a hint in the right direction? I appreciate any help.
To dynamically allocate a 2D array:
char **p;
int i, dim1, dim2;
/* Allocate the first dimension, which is actually a pointer to pointer to char */
p = malloc (sizeof (char *) * dim1);
/* Then allocate each of the pointers allocated in previous step arrays of pointer to chars
* within each of these arrays are chars
*/
for (i = 0; i < dim1; i++)
{
*(p + i) = malloc (sizeof (char) * dim2);
/* or p[i] = malloc (sizeof (char) * dim2); */
}
/* Do work */
/* Deallocate the allocated array. Start deallocation from the lowest level.
* that is in the reverse order of which we did the allocation
*/
for (i = 0; i < dim1; i++)
{
free (p[i]);
}
free (p);
Modify the above method. When you need another line to be added do *(p + i) = malloc (sizeof (char) * dim2); and update i. In this case you need to predict the max numbers of lines in the file which is indicated by the dim1 variable, for which we allocate the p array first time. This will only allocate the (sizeof (int *) * dim1) bytes, thus much better option than char p[dim1][dim2] (in c99).
There is another way i think. Allocate arrays in blocks and chain them when there is an overflow.
struct _lines {
char **line;
int n;
struct _lines *next;
} *file;
file = malloc (sizeof (struct _lines));
file->line = malloc (sizeof (char *) * LINE_MAX);
file->n = 0;
head = file;
After this the first block is ready to use. When you need to insert a line just do:
/* get line into buffer */
file.line[n] = malloc (sizeof (char) * (strlen (buffer) + 1));
n++;
When n is LINE_MAX allocate another block and link it to this one.
struct _lines *temp;
temp = malloc (sizeof (struct _lines));
temp->line = malloc (sizeof (char *) * LINE_MAX);
temp->n = 0;
file->next = temp;
file = file->next;
Something like this.
When one block's n becomes 0, deallocate it, and update the current block pointer file to the previous one. You can either traverse from beginning single linked list and traverse from the start or use double links.
There's no standard resizable array type in C. You have to implement it yourself, or use a third-party library. Here's a simple bare-bones example:
typedef struct int_array
{
int *array;
size_t length;
size_t capacity;
} int_array;
void int_array_init(int_array *array)
{
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_free(int_array *array)
{
free(array->array);
array->array = NULL;
array->length = 0;
array->capacity = 0;
}
void int_array_push_back(int_array *array, int value)
{
if(array->length == array->capacity)
{
// Not enough space, reallocate. Also, watch out for overflow.
int new_capacity = array->capacity * 2;
if(new_capacity > array->capacity && new_capacity < SIZE_T_MAX / sizeof(int))
{
int *new_array = realloc(array->array, new_capacity * sizeof(int));
if(new_array != NULL)
{
array->array = new_array;
array->capacity = new_capacity;
}
else
; // Handle out-of-memory
}
else
; // Handle overflow error
}
// Now that we have space, add the value to the array
array->array[array->length] = value;
array->length++;
}
Use it like this:
int_array a;
int_array_init(&a);
int i;
for(i = 0; i < 10; i++)
int_array_push_back(&a, i);
for(i = 0; i < a.length; i++)
printf("a[%d] = %d\n", i, a.array[i]);
int_array_free(&a);
Of course, this is only for an array of ints. Since C doesn't have templates, you'd have to either put all of this code in a macro for each different type of array (or use a different preprocessor such as GNU m4). Or, you could use a generic array container that either used void* pointers (requiring all array elements to be malloc'ed) or opaque memory blobs, which would require a cast with every element access and a memcpy for every element get/set.
In any case, it's not pretty. Two-dimensional arrays are even uglier.
Instead of an array here, you could also use a linked list, The code is simpler, but the allocation is more frequent and may suffer from fragmentation.
As long as you don't plan to do much random access (Which is O(n) here), iteration is about as simple as a regular array.
typedef struct Line Line;
struct Line{
char text[LINE_MAX];
Line *next;
};
Line *mkline()
{
Line *l = malloc(sizeof(Line));
if(!l)
error();
return l;
}
main()
{
Line *lines = mkline();
Line *lp = lines;
while(fgets(lp->text, sizeof lp->text, stdin)!=NULL){
lp->next = mkline();
lp = lp->next;
}
lp->next = NULL;
}
If you are using C you will need to implement the resizing of the array yourself. C++ and the SDL has this done for you. It is called a vector. http://www.cplusplus.com/reference/stl/vector/
While a multidimensional array can solve this problem, a rectangular 2D array would not really be the natural C solution.
Here is a program that initially reads the file into a linked list, and then allocates a vector of pointers of the right size. Each individual character does then appear as array[line][col] but in fact each row is only as long as it needs to be. It's C99 except for <err.h>.
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct strnode {
char *s;
struct strnode *next;
} strnode;
strnode *list_head;
strnode *list_last;
strnode *read1line(void) {
char space[1024];
if(fgets(space, sizeof space, stdin) == NULL)
return NULL;
strnode *node = malloc(sizeof(strnode));
if(node && (node->s = malloc(strlen(space) + 1))) {
strcpy(node->s, space);
node->next = NULL;
if (list_head == NULL)
list_head = node;
else
list_last->next = node;
list_last = node;
return node;
}
err(1, NULL);
}
int main(int ac, char **av) {
int n;
strnode *s;
for(n = 0; (s = read1line()) != NULL; ++n)
continue;
if(n > 0) {
int i;
strnode *b;
char **a = malloc(n * sizeof(char *));
printf("There were %d lines\n", n);
for(b = list_head, i = 0; b; b = b->next, ++i)
a[i] = b->s;
printf("Near the middle is: %s", a[n / 2]);
}
return 0;
}
You can use the malloc and realloc functions to dynamically allocate and resize an array of pointers to char, and each element of the array will point to a string read from the file (where that string's storage is also allocated dynamically). For simplicity's sake we'll assume that the maximum length of each line is less than M characters (counting the newline), so we don't have to do any dynamic resizing of individual lines.
You'll need to keep track of the array size manually each time you extend it. A common technique is to double the array size each time you extend, rather than extending by a fixed size; this minimizes the number of calls to realloc, which is potentially expensive. Of course that means you'll have to keep track of two quantities; the total size of the array and the number of elements currently read.
Example:
#define INITIAL_SIZE ... // some size large enough to cover most cases
char **loadFile(FILE *stream, size_t *linesRead)
{
size_t arraySize = 0;
char **lines = NULL;
char *nextLine = NULL;
*linesRead = 0;
lines = malloc(INITIAL_SIZE * sizeof *lines);
if (!lines)
{
fprintf(stderr, "Could not allocate array\n");
return NULL;
}
arraySize = INITIAL_SIZE;
/**
* Read the next input line from the stream. We're abstracting this
* out to keep the code simple.
*/
while ((nextLine = getNextLine(stream)))
{
if (arraySize <= *linesRead)
{
char **tmp = realloc(lines, arraysSize * 2 * sizeof *tmp);
if (tmp)
{
lines = tmp;
arraySize *= 2;
}
}
lines[(*linesRead)++] = nextLine;
)
return lines;
}
How does one malloc an array of structs correctly if each struct contains an array of strings which vary in size?
So each struct might have a different size and would make it impossible to
realloc(numberOfStructs * sizeof(structName))
after
malloc(initialSize * sizeof(structName)
How does one allocate memory for this and keep track of what is going on?
If your structure has a char *, it takes up the size of one pointer. If it has a char[200], it takes up two hundred bytes.
I am making some guesses here, based on the information you have provided. The only reason I can see for wanting to realloc an array of structs is if you want to add more structs to that array. That's cool. There are plenty of reasons to want that kind of dynamic storage. The best way to handle it, especially if the structures are themselves dynamic, is to keep an array of pointers to these structures. Example:
1. Data structure:
typedef struct {
int numberOfStrings;
char ** strings;
}
stringHolder;
typedef struct {
int numberOfStructs;
stringHolder ** structs;
}
structList;
2. Managing dynamic arrays of strings:
void createNewStringHolder(stringHolder ** holder) {
(*holder) = malloc(sizeof(stringHolder));
(*holder)->numberOfStrings = 0;
(*holder)->strings = NULL;
}
void destroyStringHolder(stringHolder ** holder) {
// first, free each individual string
int stringIndex;
for (stringIndex = 0; stringIndex < (*holder)->numberOfStrings; stringIndex++)
{ free((*holder)->strings[stringIndex]); }
// next, free the strings[] array
free((*holder)->strings);
// finally, free the holder itself
free((*holder));
}
void addStringToHolder(stringHolder * holder, const char * string) {
int newStringCount = holder->numberOfStrings + 1;
char ** newStrings = realloc(holder->strings, newStringCount * sizeof(char *));
if (newStrings != NULL) {
holder->numberOfStrings = newStringCount;
holder->strings = newStrings;
newStrings[newStringCount - 1] = malloc((strlen(string) + 1) * sizeof(char));
strcpy(newStrings[newStringCount - 1], string);
}
}
3. Managing a dynamic array of structures:
void createNewStructList(structList ** list, int initialSize) {
// create a new list
(*list) = malloc(sizeof(structList));
// create a new list of struct pointers
(*list)->numberOfStructs = initialSize;
(*list)->structs = malloc(initialSize * sizeof(stringHolder *));
// initialize new structs
int structIndex;
for (structIndex = 0; structIndex < initialSize; structIndex++)
{ createNewStringHolder(&((*list)->structs[structIndex])); }
}
void destroyStructList(structList ** list) {
// destroy each struct in the list
int structIndex;
for (structIndex = 0; structIndex < (*list)->numberOfStructs; structIndex++)
{ destroyStringHolder(&((*list)->structs[structIndex])); }
// destroy the list itself
free((*list));
}
stringHolder * addNewStructToList(structList * list) {
int newStructCount = list->numberOfStructs + 1;
size_t newSize = newStructCount * sizeof(stringHolder *);
stringHolder ** newList = realloc(list->structs, newSize);
if (newList != NULL) {
list->numberOfStructs = newStructCount;
list->structs = newList;
createNewStringHolder(&(newList[newStructCount - 1]));
return newList[newStructCount - 1];
}
return NULL;
}
4. Main program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char * argv[]) {
structList * allHolders;
createNewStructList(&allHolders, 10);
addStringToHolder(allHolders->structs[4], "The wind took it");
addStringToHolder(allHolders->structs[4], "Am I not merciful?");
addStringToHolder(allHolders->structs[7], "Aziz, Light!");
printf("%s\n", allHolders->structs[4]->strings[0]); // The wind took it
printf("%s\n", allHolders->structs[4]->strings[1]); // Am I not merciful?
printf("%s\n", allHolders->structs[7]->strings[0]); // Aziz, Light!
stringHolder * newHolder = addNewStructToList(allHolders);
addStringToHolder(newHolder, "You shall not pass!");
printf("%s\n", newHolder->strings[0]); // You shall not pass!
printf("%s\n", allHolders->structs[10]->strings[0]); // You shall not pass!
destroyStructList(&allHolders);
return 0;
}
You don't, generally. There are two reasons you might want to do this:
So that a single free() will release the entire block of memory.
To avoid internal memory fragmentation.
But unless you have an exceptional situation, neither are very compelling, because there is crippling drawback to this approach:
If you do this, then block[i] is meaningless. You have not allocated an array. There is no way to tell where your next struct starts without either examining the struct or having outside information about the size/position of your structs in the block.
It is not so clear how your struct type is declared. C99 has a special construct for such things, called flexible array member of a struct:
As a special case, the last element of
a structure with more than one named
member may have an incomplete array
type; this is called a flexible array
member.
You could do something like
typedef struct myString myString;
struct myString { size_t len; char c[]; };
You may then allocate such a beast with
size_t x = 35;
myString* s = malloc(sizeof(myString) + x);
s->len = x;
and reallocate it with
size_t y = 350;
{
myString* tmp = realloc(s, sizeof(myString) + y);
if (!tmp) abort(); // or whatever
tmp->len = y;
}
s = tmp;
To use this more comfortably you'd probably better wrap this into macros or inline functions.