I have been struggling with the ideas behind malloc and realloc for quite some time now and at the moment I have a problem with dynamically creating an array of structs. I have a struct triangle which itself is composed of an array of struct coordinates. I would like to be able to have an array of triangles which is as large as necessary, but every time I attempt to increase the length of my array, nothing seems to happen. Realloc doesn't fail and neither does malloc. However the new triangles are not inserted in my array. Here is my code for reference.
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = (struct triangle*) realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
free(ts);
exit(EXIT_FAILURE);
}
*triangles = ts;
triangles[size] = t;
size++;
}
int main() {
struct triangle* triangles = (struct triangle *) malloc(sizeof(struct triangle));
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct coordinate *a = malloc(sizeof(struct coordinate));
a->x = 1 * i;
a->y = 2 * i;
struct coordinate *b = malloc(sizeof(struct coordinate));
b->x = 3 * i;
b->y = 4 * i;
struct coordinate *c = malloc(sizeof(struct coordinate));
c->x = 5 * i;
c->y = 6 * i;
struct triangle *t = malloc(sizeof(struct triangle));
t->point[0] = *a;
t->point[1] = *b;
t->point[2] = *c;
addTriangle(triangles, t);
}
}
I have tried every variation of this I have found, but I would rather not just blindly throw in & and * until something happens.
As-is, your program invokes undefined behavior when it passes an uninitialized *triangles to realloc: https://taas.trust-in-soft.com/tsnippet/t/9ff94de4 . You probably meant to pass &triangles when you called it in main.
Changing the call in main to addTriangle(&triangles, t);, the next issue is an out-of-bounds access inside addTriangle: https://taas.trust-in-soft.com/tsnippet/t/658228a1 . Again this may be because you have the wrong level of indirection and meant something like (*triangles)[size]
instead of triangles[size].
If I change the line triangles[size] = t; to (*triangles)[size] = *t; then there is no undefined behavior. You should check whether this program still does what you want, since it was modified: https://taas.trust-in-soft.com/tsnippet/t/8915bd2d
The final version:
#include <string.h>
#include <stdlib.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = (struct triangle*) realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
free(ts);
exit(EXIT_FAILURE);
}
*triangles = ts;
(*triangles)[size] = *t; // a struct assignment
size++;
}
int main() {
struct triangle* triangles = (struct triangle *) malloc(sizeof(struct triangle));
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct coordinate *a = malloc(sizeof(struct coordinate));
a->x = 1 * i;
a->y = 2 * i;
struct coordinate *b = malloc(sizeof(struct coordinate));
b->x = 3 * i;
b->y = 4 * i;
struct coordinate *c = malloc(sizeof(struct coordinate));
c->x = 5 * i;
c->y = 6 * i;
struct triangle *t = malloc(sizeof(struct triangle));
t->point[0] = *a;
t->point[1] = *b;
t->point[2] = *c;
addTriangle(&triangles, t); /* pass the address of triangles
so that addTriangle can modify this variable's contents */
}
}
Side remarks not directly related to the problem you asked about
As long as you program in C, please do not cast the result of malloc. Simply write struct triangle* triangles = malloc(....
As noted by #aschepler in the comments, this program still leaks the memory blocks allocated from main. These can be freed at the end of each iteration without adding any undefined behavior: https://taas.trust-in-soft.com/tsnippet/t/a0705262 . Doing this, you may realize that t->point[0] = *a;, ... are in fact struct assignments and that it was unnecessary to allocate a separate struct coordinate in the first place: you could just fill in each struct coordinate member of the struct triangle. In addition, it was unnecessary to allocate the struct triangle in main, too: you could just use a local variable for that, since anyway the contents of the struct will be copied by the function addTriangle to the array that main's local variable triangles points to.
Also you don't need to call free(triangles) if triangles is a null pointer in main:
struct triangle* triangles = (struct triangle *) malloc(...
if(triangles == NULL) {
free(triangles);
exit(EXIT_FAILURE);
}
It is allowed to pass a null pointer to free, and this does what you would expect (it does nothing), but since you know that triangles is NULL in the then branch, simply call exit.
Handling the failure of realloc on the other hand is a subtle subject. Your program is doing it wrong, but it does not really matter because it calls exit immediately.
Storing information about the allocated array pointed by main's local variable triangles in a static file-scope variable size is not consistent. The two are so closely related that they should be in the same scope. Since you need addTriangle to be able to change size, you cannot simply move size to be a local variable of main, but you can move the local variable triangles of main to file scope, next to size. If you prefer to make size a local variable of main after all, you will need to pass its address to the function addTriangle so that the latter can update the former.
Change the function call as
addTriangle(&triangles, t);
You can replace the whole body of your for loop with
struct triangle t = {{{i, 2*i},{3*i,4*i},{5*i,6*i}}};
addTriangle(&triangles, &t);
Please note the & before the parameters, because you want to pass the address of both.
I already noticed as a comment that triangles[size] = t; should be (*triangles)[size] = *t;
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
struct coordinate {
int x;
int y;
};
struct triangle {
struct coordinate point[3];
};
static size_t size = 0;
static void addTriangle(struct triangle **triangles, struct triangle *t) {
struct triangle *ts = realloc(*triangles, (size+1) * sizeof(struct triangle));
if(ts == NULL) {
exit(EXIT_FAILURE);
}
*triangles = ts;
(*triangles)[size] = *t;
size++;
}
int main() {
struct triangle* triangles = malloc(sizeof(struct triangle));
if(triangles == NULL) {
exit(EXIT_FAILURE);
}
for(int i = 0; i < 2; i++) {
struct triangle t = {{{i, 2*i},{3*i,4*i},{5*i,6*i}}};
addTriangle(&triangles, &t);
}
for(int i = 0; i < size; i++) {
printf("%d %d, %d %d, %d %d\n", triangles[i].point[0].x,
triangles[i].point[0].y,
triangles[i].point[1].x,
triangles[i].point[1].y,
triangles[i].point[2].x,
triangles[i].point[2].y);
}
}
Related
When allocating memory for a pointer to a record I also need space for an integer pointer located just before the allocated record. This pointer cannot be part of the record itself and it cannot be placed after the record. My current approach is the following:
#include <stdlib.h>
static int n;
struct { int f; } *p;
p = malloc(sizeof (int *) + sizeof *p);
if (p != NULL) {
p = (void *) ((int **) p + 1);
*((int **) p - 1) = &n;
}
Are the casts well defined? If not, what should I do instead?
Edit:
What I'm trying to achieve is to implement extensible records (OOP) and the integer pointer represent a type ID. An extended record should be compatible with its base type. However, I only need type ID:s for pointer to records. Here is a complete example:
#include <assert.h>
#include <stdlib.h>
struct T0 {
int f;
};
int T0ID;
struct T1 {
struct T0 base;
int g;
};
int T1ID;
int main(void)
{
struct T0 *x;
struct T1 *y;
y = malloc(sizeof (int *) + sizeof *y);
if (y != NULL) {
*((int **) y) = &T1ID;
y = (void *) ((int **) y + 1);
((struct T0 *) y)->f = 1;
y->g = 2;
}
x = (struct T0 *) y;
assert(x->f == 1);
return 0;
}
I'm not sure your approach is good. Especially I'm worried about changing the value of p. You'll need that value later when you need to free the memory.
I would wrap the int* and the struct together in another struct. Something like:
static int n;
struct someData { int f; };
struct wrapper {int* pn; struct someData data;};
struct someData* pd; // Pointer to the data struct
struct wrapper* pw = malloc(sizeof *pw);
if (pw != NULL) {
pw->pn = &n;
pd = &pw->data;
}
Your code, in which you cast (arbitrary) memory addresses to particular object types, is might yield undefined behaviour due to incorrect alignment (cf.
C standard draft):
6.3.2.3 Pointers
(7) A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type, the behavior is undefined.
You are having a pointer declared to be of type struct{int}* pointing to a (larger memory block), and then casting the pointer and doing arithmetic operations on the (casted) pointer. As it is not guaranteed that int * and struct{int}* are aligned the same way, it is not guaranteed that the behaviour is defined.
To avoid this, encapsulate your structure and the preceeding integer in another structure, e.g. as follows:
static int n;
struct data_struct {
int f;
};
struct enclosing_struct {
int *nPtr;
struct data_struct data;
};
int main() {
struct enclosing_struct *e = malloc (sizeof(struct enclosing_struct));
e->nPtr = &n;
struct data_struct *dataPtr = &e->data;
return 0;
}
So I have what I think is a noob question. Sorry for that in advance, and for the grammar as english is not my primary language.
So I have to make a game of checkers. I have some struct, defined by
struct game {
int **board;
int xsize, ysize;
struct move *moves;
int cur_player;
};
struct coord {
int x, y;
};
struct move_seq {
struct move_seq *next;
struct coord c_old;
struct coord c_new;
int piece_value;
struct coord piece_taken;
int old_orig;
};
struct move {
struct move *next;
struct move_seq *seq;
};
And I have to initialize a struct game wih the fonction
struct game *new_game(int xsize, int ysize)
So, here's my problem. I call, for now, new_game always with 10 and 10 values for xsize an ysize. Then I initialize the board game, which I want to assign later.
int black = 1;
int white = 5;
int **board;
int i;
int j;
int k;
for(i=0;i<xsize;i++)
{
for(j=0;j<ysize;j++)
{
if(i<(xsize/2) && j<(ysize/2) && (i+j)%2!=0)
{
board[i][j] = black;
}
else if(i>(xsize/2) && j>(ysize/2) && (i+j)%2!=0)
{
board[i][j] = white;
}
else board[i][j] = 0;
}
}
struct game *new = malloc (sizeof(struct game *));
if (new == NULL) return NULL;
So, my problem is after that. I just have Segmentation Fault whatever I do with my struct new.
I tried to do assign new->xsize = xsize and the same with ysize. I do a malloc for the board and the struct move, like I learned to do, but I kept getting this error of Segmentation Fault.
So here's my real question: How to assign and initialize correctly a struct ? Do I Have to make a malloc for each of the member of struct game ? (I tried that too but without any success...)
I don't necessarily want just the answer, I'd prefer to really understand what I have to do in this case and in general, to make less mistakes in the future.
Thanks in advance for your help.
Have a good day.
It happens because you only allocated space for a pointer to your struct. What you need to do, is allocate it for the entire size of it:
struct game *new = malloc (sizeof(struct game));
Edit: Don't be mislead by the return value of malloc, as it returns a pointer to the allocated space, that's why it should be struct game *new as it is.
In addition to Michael's bug fix, I also wonder about board: it is not allocated, yet you write to it. I think it should be like:
struct game *new_game(int xsize, int ysize)
{
int black = 1;
int white = 5;
int i;
int j;
struct game *new = malloc (sizeof(struct game));
if (new == NULL) return NULL;
game->xsize= xsize;
game->ysize= ysize;
game->board= malloc(xsize*ysize*sizeof(int));
for(i=0;i<xsize;i++)
{
for(j=0;j<ysize;j++)
{
if(i<(xsize/2) && j<(ysize/2) && (i+j)%2!=0)
{
game->board[i*xsize+j] = black;
}
else if(i>(xsize/2) && j>(ysize/2) && (i+j)%2!=0)
{
game->board[i*xsize+j] = white;
}
else game->board[i*xsize+j] = 0;
}
}
return (game);
}
Note also the array indexing: the compiler doesn't know the dynamic rowsize so you have to do that yourself.
I am trying to take input from console and add it to hash table.
But I'm getting Segmentation fault 11.
So, I debugged the program using gdb-apple.
It is showing that I'm trying access memory I cannot, using the pointer variable.
I think it is something obvious, but I'm missing it
This is what the gdb is displaying
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000986 in CreateHashTable (size=200) at hashing.c:29
29 h->Table[i]->next = NULL;
Here is the code
Header File:
#define LOAD_FACTOR 20
#define INITIAL_SIZE 200
struct HashTable *CreateHashTable(int size);
int HashSearch(struct HashTable *h,int data);
int HashInsert(struct HashTable *h,int data);
int HashDelete(struct HashTable *h, int data);
void Rehash(struct HashTable *h);
int Hash(int data, int size);
struct ListNode
{
int key;
int data;
struct ListNode *next;
};
struct HashTableNode
{
int bcount;
struct ListNode *next;
};
struct HashTable
{
int tsize;
int count;
struct HashTableNode **Table;
};
Implementation file:
#include "hashing.h"
#include<stdio.h>
#include<stdlib.h>
struct HashTable *CreateHashTable(int size)
{
struct HashTable *h;
h = (struct HashTable *) malloc ( sizeof(struct HashTable) );
if(h == NULL)
{
printf("Memory Error");
return NULL;
}
h->tsize = (int) size/LOAD_FACTOR;
printf("h->tsize = %d",h->tsize);
h->count = 0;
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
if( h->Table == NULL )
{
printf("Memory Error");
return NULL;
}
int i;
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
return h;
}
I would paste the rest of file, or Driver file, but I don't see it relevant.
Please tell me why I'm getting the segmentation fault 11
You allocated memory for array of pointers but you didn't allocate memory for members of this array.
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i] = malloc(...); //put correct arguments here and check allocation
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
Your problem is here:
struct HashTableNode **Table;
You want an array of nodes (not a 2d array), change to:
struct HashTableNode *Table;
also change
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
to
h->Table = malloc(sizeof(struct HashTableNode) * h->tsize);
I think I want an array of pointers to nodes, don't I?
As pointed out by #WhozCraig, there is no reason for the additional level of indirection.
Example A (Pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a; /* pointer */
int i, n = 10;
a = malloc(n * sizeof(int)); /* space for 10 ints */
for (i = 0; i < n; i++) {
a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", a[i]);
}
free(a);
return 0;
}
Example B (Pointer to pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **a; /* pointer to pointer*/
int i, n = 10;
a = malloc(n * sizeof(int *)); /* space for 10 pointer to ints */
for (i = 0; i < n; i++) {
a[i] = malloc(sizeof(int)); /* space for 1 int */
*a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", *a[i]);
free(a[i]);
}
free(a);
return 0;
}
As you can see both do the same thing, but the first one requires less memory and the code is cleaner.
One way to make it easy to remember is:
int * can hold an array
int ** can hold a table (NROWS * NCOLS)
int *** can hold an array of tables
I wrote a piece of code to handle dynamic arrays. Idea was to use array of struct pointers, where the last member of array is NULL. Slight variation of code I wrote is below (using integers and not structures).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int **list, int* value) {
for(int i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
}
void list_init(int **list) {
int* x;
for(int i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(list, x);
}
}
int main() {
int** l = malloc(sizeof(int*));
l[0] = NULL;
list_init(l);
}
While debugging, I discovered that only first 3 integers are added to the list. I can't seem to figure out why is this happening. Any ideas?
The problem is that the call to realloc() in list_add() potentially frees the memory block *list and allocates another. list_add updates its list pointer, but it does not return the updated pointer to the caller, list_init(); list_init()'s list pointer is potentially a pointer to the recently-freed memory block.
To fix this code, list_add() and list_init() need to be able to "return" the updated list pointer:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int ***p_list, int *value) {
int **list = *p_list;
int i;
for(i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
*p_list = list;
}
void list_init(int ***p_list) {
int **list = *p_list;
int *x;
int i;
for(i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(&list, x);
}
*p_list = list;
}
int main() {
int **list = malloc(sizeof(int*));
list[0] = NULL;
list_init(&list);
int **l = list;
for (; *l != NULL; ++l) {
printf("%d\n", **l);
}
}
http://codepad.org/iGcSaJOR
EDIT
In this case of dynamic arrays the way you have told will not make anything better, the code will complicate only. For each addition of integer you have used realloc trying aggressively to save memory, but this will take more time while execution. Why not allocate a block of memory reserved for the array and to reflect the dynamic character put the array inside a struct with the last index, and when you add something add it on the last location and increment the counter. When this block is filled, you can chain another block to point to another one.
typedef struct _dyna_arr
{
my_type data_arr[MAX_LEN];
int n;
struct _dyna_arr *next block;
};
Therefore you maintain a linked list of multiple arrays. The size of MAX_LEN can be fixed which is appropriate for an application which will help decrease internal fragmentation.
*old answer removed *
A struct like the following works fine, I can use t after calling malloc(sizeof(mystruct)):
struct mystruct {
MyDef *t[5];
};
I want to be able to dynamically set the length of the array of MyDef, like the following:
struct mystruct {
MyDef **t;
int size;
};
What do I need to do additionally to malloc(sizeof(mystruct)) to get this to work, so I can do TestStruct->t[3] = something? Just getting a segmentation fault!
Thanks!
EDIT with code that causes seg fault, unless I'm blind this seems to be what the answers are so far:
#include <stdio.h>
typedef struct mydef {
int t;
int y;
int k;
} MyDef;
typedef struct mystruct {
MyDef **t;
int size;
} MyStruct;
int main(){
MyStruct *m;
if (m = (MyStruct *)malloc(sizeof(MyStruct)) == NULL)
return 0;
m->size = 11; //seg fault
if (m->t = malloc(m->size * sizeof(*m->t)) == NULL)
return 0;
return 0;
}
struct mystruct *s = malloc(sizeof(*s));
s->size = 5;
s->t = malloc(sizeof(*s->t) * s->size);
m = (MyStruct*)malloc(sizeof(MyStruct)) == NULL
What that does. Calls malloc, compares return of malloc to NULL. Then assigns the result of that comparison(a boolean value) to m.
The reason it does that is because '==' has a higher precedence than '='.
What you want:
if ( (m = (MyStruct *)malloc(sizeof(MyStruct))) == NULL)
...
if ( (m->t = malloc(m->size * sizeof(*m->t))) == NULL)
That happens because you do not allocate memory for array itself, only for pointer to this array.
So, first you have to allocate mystruct:
struct_instance = malloc(sizeof(mystruct));
and then you have to allocate memory for array of pointers to MyDef and initialize pointer in your struct
struct_instance->size = 123;
struct_instance->t = malloc(sizeof(MyDef*) * struct_instance->size);