I need help with a school assignment, specifically with resizing the amount of memory allocated for a pointer WITHOUT realloc.
I have the following declarations in my program.
struct GraphicElement
{
enum{ SIZE = 256 };
unsigned int numLines;
Line* pLines;
char name[SIZE];
};
typedef struct
{
unsigned int numGraphicElements;
GraphicElement* pElements;
}VectorGraphic;
VectorGraphic Image;
As the program runs I'll be adding more GraphicElements to pElements.
For example, after 5 iterations the memory for pElements should be something like this:
[GraphicElement 0][GraphicElement 1] ... [GraphicElement 4]
For the function AddGraphicElement(VectorGraphic* vg) I have this code (with some lines removed for easier reading):
vg->pElements = (GraphicElement*)realloc(vg->pElements, sizeof(GraphicElement)*(vg->numGraphicElements+1));
//Then I assign inputs from user into the members of the struct at vg->pElements[vg->numGraphicElements]
vg->numGraphicElements++;
This works, BUT according to the instructions given by my professor, I'm only allowed to use malloc and free- no realloc. Sadly the only way I've made this work is with realloc.
Can anyone point me in the right direction to implement this using only malloc?
Thanks!
If you are not allowed to use realloc, but malloc and free are allowed, you can replace the call with the following, less efficient, sequence:
void *newData = malloc(newSize);
memcpy(newData, oldData, oldSize);
free(oldData);
Internally, realloc does the same thing, but it does so more efficiently. Unlike user program, realloc knows the actual size of the dynamic memory chunk, so it checks if newSize <= actualSize to avoid reallocation. When actualSize is insufficient, realloc does the same thing as above. realloc has additional logic to deal with situations when the size need to shrink, but in your situation this does not apply.
Related
Strait to the point.
I have a struct with a string, char and int.
The struct is created dynamically because i will need it in different parts of my program.
struct A
{
char staticString[20];
char* dynamicString;
char character;
int integer;
};
I know if i want to create a struct i call:
A example = (A)malloc(sizeof(A));
In order to populate the dynamicString and int i used:
example->dynamicString = (char*)malloc(sizeof(char*));
example->integer = (int)malloc(sizeof(int));
Unfourtanetly when i tried to populate staticString and char it didn't worked.
Don't even ask what was my code for those, i tried a lot of combinations from everywhere.
In addition to that can somebody show me examples how to write/read those values?
Thanks in advance.
First things first:
You're using C, and by the way you've defined the structure, you need to declare the pointer like so:
struct A *example;
Next, malloc returns a pointer, so you need to cast to a pointer (and not to a structure):
(struct A *)malloc(sizeof(struct A));
Secondly, I'm not sure why but hey:
- you're trying to dynamically allocate an int in the structure. As I said previously, malloc returns a pointer, so in your structure you need an int pointer like so "int *integer;"
- you're trying to allocate a dynamic string, however you're not doing it properly, here is what I think you want
example->dynamicString = (char *)malloc(sizeof(char) * 10);
Where 10 is the size of your dynamic string.
Edit:
you may also populate the integer in your struct statically or dynamically, but I think you intended the static approach:
example->integer = 123;
The dynamic approach would be (assuming you have int *integer in your struct):
example->integer = (int *)malloc(sizeof(int));
*(example->integer) = 123;
Every time you create a new struct the memory in the heap is set to size of :
sizeof(char)*20 + sizeof(char pointer) +sizeof(char)+ sizeof(int).
If you want to save a string that will be pointed to by your char pointer- then you ask for allocation in heap for the size of that string- and malloc returns the pointer to that memory allocation on heap.
So, you already have a space for your char array, char pointer, char and int that was allocated when you asked to make a new struct and do not need to allocate it again.
also, keep in mind malloc returns a pointer to the allocated place on the heap- so if you malloc(sizeof(int)) you get a pointer to a memory allocation for an int on the heap- which is pointed to by a int pointer Not an int.
good luck!
This question already has answers here:
Getting a stack overflow exception when declaring a large array
(8 answers)
Closed 5 years ago.
Hi all I am really new to C (just started this week), and want to make sure that I am not looking down the wrong rabbit home and hoping to perhaps get pointed to the right rabbit hole.
I create a struct:
#define MAX 64
#define ARRAY_SIZE 2048
struct object {
int q, c, p;
char name[MAX]; //Stores string up to 63 characters
char arr[ARRAY_SIZE][MAX]; // Creates an array of 2048 cells with string of length 63 max
};
int main(){
...
...
int variable = 30;
struct object l[variable]; //This is where the crash happens. But only when either variable is too large (for instance works on 15 just fine, but anything over 20 it crashes), or when Array_SIZE is too larger, for instance works fine with 1024 but 2048 crashes.
...
...
}
The error I get on crash is the following: Process returned -1073741571 (0xC00000FD) in the cmd window. And the following in the debugger in the IDE:
Program received signal SIGSEGV, Segmentation fault.
[Inferior 1 (process 12120) exited with code 030000000375]
Am I doing something obviously wrong with how I declare an array of structs? Why would large numbers not work but lower numebrs work?
Does the above error indicate I am accessing something out of bounds somewhere? Ive been up and down the code and cant seem to find any reason why larger numbers dont work and lower ones do. My memory footprint doesnt seem to be the issue, just a few megs of memory.
I need help with what to look for (I cant find any instances of accessing anything out of bounds, so I get the feeling Im not chasing the right rabbit and need to look for something else)? Or maybe Im doing something illegal for C without knowing it?
I think your program crashes because you statically allocate too much memory on the stack.
Try using the malloc or calloc function. It dynamically allocates memory on the heap instead e.g. :
struct object *l = malloc(variable*sizeof(struct object));
Don't forget to free it afterwards using the free function.
free(l);
You have a memory size problem, try to increase the memory size for your program.
And if you want to use big array size and so allocate a lot of memory, you shouldn't allocate statically but dynamically.
So you should use malloc
typedef struct object {
int q, c, p;
char name[MAX]; //Stores string up to 63 characters
char arr[ARRAY_SIZE][MAX];
} myObject ;
int variable = 30;
myObject *l = malloc(sizeof(myObject) * variable);
I do not advice you to declare an array of 2048 statically, so you should initiate your struct with a function.
typedef struct object {
int q, c, p;
char name[MAX]; //Stores string up to 63 characters
char *arr[MAX];
} myObject ;
myObject *createNewObject() {
myObject *toReturn = malloc(sizeof(myObject) * variable);
if (toReturn == NULL)
return NULL;
toReturn->arr = malloc(sizeof(char) * ARRAY_SIZE);
return (toReturn);
}
void freeMyObject(myObject *objectToFree)
{
if (objectToFree && objectToFree->arr =! NULL)
free(objectToFree->arr)
if (objectToFree)
free(objectToFree)
}
void main()
{
myObject *myNewObj = createNewObject()
// You can do some stuff with myNewObj but always verify the pointers
freeMyObject(myNewObj);
}
You should also debug with valgrind when you works with malloc, so you don't have memory loss or problems.
Hope I helped
Well the problem you had is - you have used automatic memory allocation. Due to constraint of size of automatic storage your program crashed - you asked for more than you should.
So what is the solution?
Static memory allocation:
Solution being
static struct object l[variable];
Dynamic memory allocation
struct object *ptr = malloc( sizeof *ptr * variable);
The storage of these allocation is different from automatic variables - so free from the size constraint . In this case you have to free the dynamically allocated memory. That's why you will get around the problem you have.
Statically allocate is not a confusion free term. All these types of variable will have different scope - lifetime. Standard never mentions about stack or heap . It is the implementation that follow these to store automatically allocated memory and dynamically allocated memory.
If I want to reduce malloc()s (espacially if the data is small and allocated often) I would like to allocate the pointer and pointee at once.
If you assume something like the following:
struct entry {
size_t buf_len;
char *buf;
int something;
};
I would like to allocate memory in the following way (don't care about error checking here):
size_t buf_len = 4; // size of the buffer
struct entry *e = NULL;
e = malloc( sizeof(*e) + buf_len ); // allocate struct and buffer
e->buf_len = buf_len; // set buffer size
e->buf = e + 1; // the buffer lies behind the struct
This could even be extende, so that a whole array is allocated at once.
How would you assess such a technuique with regard to:
Portability
Maintainability / Extendability
Performance
Readability
Is this reasonable? If it is ok to use, are there any ideas on how to design a possible interface for that?
You could use a flexible array member instead of a pointer:
struct entry {
size_t buf_len;
int something;
char buf[];
};
// ...
struct entry *e = malloc(sizeof *e + buf_len);
e->buf_len = buf_len;
Portability and performance are fine. Readability: not perfect but good enough.
Extendability: you can't use this for more than one member at a time, you'd have to fall back to your explicit pointer version. Also, the explicit pointer version means that you have to muck around to ensure correct alignment if you use it with a type that doesn't have an alignment of 1.
If you are seriously thinking about this I'd consider revisiting your entire data structure's design to see if there is another way of doing it. (Maybe this way is actually the best way, but have a good think about it first).
As to portability, I am unaware of any issues, as long as the sizes are found via suitable calls to sizeof(), as in your code.
Regarding maintainability, extendability and readability, you should certainly wrap allocation and de-allocation in a well-commented function. Calls to...
entry *allocate_entry_with_buffer();
void deallocate_entry_with_buffer(entry **entry_with_buffer);
...do not need to know implementation details of how the memory actually gets handled. People use stranger things like custom allocators and memory pools quite frequently.
As for speed, this is certainly faster than making lots of small allocations. I used to allocate whole 2D matrices with a similar strategy...
It should work, but in fact you are using a pointer for a useless indirection. Windows API (for example) uses another method for variable size structs : the variable size buffer is last in struct and is declared to be char buf[1].
Your struct would become :
struct entry {
size_t buf_len;
int something;
char buf[1];
};
The allocation is (still no error checking) :
size_t buf_len = 4; // size of the buffer
struct entry *e;
e = malloc( sizeof(*e) + buf_len - 1); // struct already has room for 1 char
e->buf_len = buf_len; // set buffer size
That's all e.buf is guaranteed to be a char array of size buf_len.
That way ensures that even if the variable part was not a character array but a int, long, or anything array, the alignement would be given by the last element being a array of proper type and size 1.
For starters, the line:
e->buf = e + sizeof(*e); // the buffer lies behind the struct
Should be:
e->buf = e + 1; // the buffer lies behind the struct
This is because e + 1 will be equal to the address at the end of the structure. As you have it, it will only be the number of bytes into the structure equal to the number of bytes in a pointer.
And, yes, it's reasonable. However, I prefer this approach:
struct entry {
size_t buf_len;
int something;
char buf[1];
};
This way, you don't mess with the pointers. Just append as many bytes as needed, and they will grow the size of your buf array.
Note: I wrote a text editor using an approach similar to this but used a Microsoft c++ extension that allowed me to declare the last member as char buf[]. So it was an empty array that was exactly as long as the number of extra bytes I allocated.
seems fine to me - put comments in though
Or you could do this - which is quite common
struct entry {
size_t buf_len;
int something;
char buf;
};
ie make the struct itself variable length. and do
size_t buf_len = 4; // size of the buffer
struct entry *e = NULL;
// check that it packs right
e = malloc(sizeof(size_t) + sizeof(int) + buf_len ); // allocate struct and buffer
e->buf_len = buf_len; // set buffer size
...... later
printf(&e.buf);
In the following function, I am parsing string form a linked list and giving values to struct array. Is there any way that let me not use mallocs inside while loop.I can not handle glibc errors, so looking for other way.I tried to use char arrays instead of char* for the struct fields. But I am getting seg error. Actually the function is working, but I ahve to call the function 15000 times later, so I want to make sure it won't cause any memory trouble that time.
struct CoordNode
{
int resNum;
double coordX;
double coordY;
double coordZ;
char atomName[4];
};
void parseCrdList()
{
int resNum=1;
int tAtomNum,i;
char *tcoordX, *tcoordY, *tcoordZ, *tatomName, tresNum[5];
ccur_node=headCoord_node->next;
struct CoordNode *t;
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
while (ccur_node!=NULL)
{
tresNum=malloc(5*sizeof(char));
memcpy(tresNum,ccur_node->crdRow+26,4);
resNum=atoi(tresNum);
t[i].resNum=resNum;
tcoordX=malloc(8*sizeof(char));
memcpy(tcoordX,ccur_node->crdRow+35,7);
tcoordY=malloc(8*sizeof(char));
memcpy(tcoordY,ccur_node->crdRow+43,7);
tcoordZ=malloc(8*sizeof(char));
memcpy(tcoordZ,ccur_node->crdRow+51,7);
t[i].coordX=strtod(tcoordX,NULL);
t[i].coordY=strtod(tcoordY,NULL);
t[i].coordZ=strtod(tcoordZ,NULL);
tatomName=malloc(4*sizeof(char));
memcpy(tatomName,ccur_node->crdRow+17,3);
strcpy(t[i].atomName,tatomName);
old_ccur_node=ccur_node;
ccur_node=ccur_node->next;
//free(old_ccur_node);
i++;
}
numofRes=i;
addCoordData(t);
//free(t);
t=NULL;
}
A couple of thoughts and guesses.
First, as I mentioned before, sizeof(char) is always 1 byte in C, it's actually standard byte definition in C. So remove those as completely unnecessary and hard to read.
Back to the main problem.
You never use array of chars bigger than 8, so just make it statically 8 bytes long. If you have to call you function 15k times, that will save you tons of time(malloc takes time to allocate memory for you).
Given information from the question I guess your segfault was the cause of not initialising memory you allocated with malloc or reserved for auto char [8] with its declaration
1. You allocate (or 2nd version - declare 8-byte array) 8 bytes. It works fine. But you get 8 bytes full of trash here.
2. You copy 7 bytes from your list. And that's fine, too. But you forget to NULL terminate, so if you try to print it out back, you get segfault.EDIT If it works then probably you got lucky, because it shouldn't.
Solution
Replace char * witch char [8], remove all mallocs and frees corresponding to those char *, null terminate all your char[8] after strcpy, strncpy, or memcpy (whatever your choice is, depending on how confident you are that your data in list is correct) data to them.
Check your code with valgrind before further use, too.
It's surprising you saying this function worked for you. From what I see from your code I had a lot of memory leaks to begin with because non of those 8-byte mallocs was ever fried.
The second thing is that it looks like you're allocating array of CoordNode before knowing the actual number of data records to parse. I added proper numofRes calculation before allocation.
Since you don't modify input data you don't actually need all those mallocs and memcpy's, you can use crdRow in strtod() immediatly, assuming it has char * type.
The last thing: it's generally a bad practice to do allocation in one place and freeing data in another. So it's better you free your headCoord_node structure in a place where it was allocated, after parsing it. The decision of freeing t depends on how addCoordData(t) treats its parameter.
void parseCrdList()
{
struct CoordNode *t;
int i;
// count number of records to parse
numofRes = 0;
ccur_node = headCoord_node->next;
while (ccur_node != NULL)
{
numofRes++;
ccur_node=ccur_node->next;
}
t=malloc(numofRes*sizeof(struct CoordNode));
i=0;
ccur_node = headCoord_node->next;
while (ccur_node!=NULL)
{
t[i].resNum=atoi(ccur_node->crdRow+26);
t[i].coordX=strtod(ccur_node->crdRow+35,NULL);
t[i].coordY=strtod(ccur_node->crdRow+43,NULL);
t[i].coordZ=strtod(ccur_node->crdRow+51,NULL);
strncpy(t[i].atomName,ccur_node->crdRow+17,4);
ccur_node=ccur_node->next;
i++;
}
numofRes=i;
addCoordData(t);
//free(t); // <<< it depends on how addCoordData treats t
}
I need to identify a global struct (array), consisted of 4 integers.
The problem is, size of that struct array is not known in advance.
I'm trying to make sth. like this:
typedef struct
{
int value;
int MAXleft;
int MAXright;
int MAX;
} strnum;
int main ()
{
int size;
scanf("%d", &size);
strnum numbers[size];
return 0;
}
I heard that, it is possible to do this by pointers but I don't know how to do.
You can allocate the space for several structures dynamically like this:
strnum *numbers = malloc( size * sizeof(strnum) );
Then you can use it like any regular array (mostly).
It might be more convenient to use calloc instead of malloc. It allocates a number of blocks and fills them with zeros. Please note, that malloc doesn't clear allocated memory.
strnum *numbers = calloc( size, sizeof(strnum) );
When you are done with the memory don't forget to call free( numbers ), which will return the allocated memory back to a memory manager.
If you don't free it when it's no longer required and allocate some more and more, a memory footprint of the program will grow for no good reason as the program continues to work. This is called a memory leak and should be avoided. It might eventually result in the lack of memory for a program and unpredictable results.
And don't forget to include a stdlib.h header with prototypes of memory allocation functions.
You can start with malloc() and then do realloc() when the size keeps increasing.
I would suggest you to allocate a pool of 10 structures at once so that the number of calls to realloc() are reduced.
It is called Dynamic Memory Allocation
The thing you are trying to do can be done as follows:
strnum* number;
int size = 0;
scanf("%d",&size);
number = malloc(size * sizeof(strnum));
Also, don't forget to free the memory once you have done using the array.
free(number);