I'm making the game atoms in C where people take turns putting atoms into grid spaces. I'm trying to implement a move tracking system wherein every time they make a move, the moves array is increased by one. Not very efficient I know (and I know I don't check malloc return value), but just trying to get it at least working for now. Here's how I'm doing it:
int move_count_temp = (game->move_count)+1;
move_t* moves;
//Check if it's first move
if (game->moves == NULL) moves = (move_t*)malloc(sizeof(move_t*));
else moves = (move_t*)malloc(move_count_temp*sizeof(move_t*));
// Copy old moves over
for (int i=0; i<game->move_count;i++) {
moves[i].x = game->moves[i].x;
moves[i].y = game->moves[i].y;
}
//Copy current move
moves[move_count_temp-1].x = y_coordinate;
moves[move_count_temp-1].y = x_coordinate;
// Free old moves pointer and assign new one
free(game->moves);
game->moves = moves;
game->move_count = move_count_temp;
The problem is on the 4th move it crashes on the 4th line in that sample, when mallocing moves. I've been trying to fix it for a while and just don't know why it's happening. Any insight would help, thanks.
P.S. The game struct has a pointer to a moves struct, and this is the move_t struct;
struct move_t {
int x;
int y;
};
These allocations are wrong:
if (game->moves == NULL) moves = (move_t*)malloc(sizeof(move_t*));
else moves = (move_t*)malloc(move_count_temp*sizeof(move_t*));
You need to allocate space for move_t structures, not pointers to move_t structures. The canonical way to do this helps avoid such mistakes:
if (game->moves == NULL) {
moves = malloc(sizeof *moves);
} else {
moves = malloc(sizeof *moves * move_count_temp);
}
That is, there is no reason to cast the result of calls to malloc() in C, this only serves to clutter the code. And, using an identifier instead of an explicit type in the sizeof operand helps avoid the error in the posted code, as well as making the code easier to maintain.
That said, it seems like the posted code should use realloc() instead of malloc() and free() to reallocate game->moves.
Related
I have a problem with this code, I tried to understand what's going on, but I cannot understand why it just crushes. the functions works like I expect for the node->left.
But when the last call of the function ends in the case node->left; the function just crushes, I think because of the reallocated array, I don't know if I'm trying to access a forbidden memory.
I'll explain a little more where I think the problem comes from:we are in the last call of helper(node->left,table,len) before printing the array : consider len = N and node->left!=NULL ==> reallocating table len = N+1, assigning node->data to table[len] and everything is fine, node->left == NULL ==> printing the table and we are done with the helper(node->left,table,N) case; now we are in the helper(node->right,table,N) case; in this case the program just crushes ; it's supposed to reallocate table; and assign node->data to table[N]; and so one ...
By the way : this function tries to print all the Root-leaf paths in a binary tree.
struct node {
int data;
struct node* left;
struct node* right;
};
void helper(struct node* node,int *table,int len)
{
if(node == NULL){
return;
}
else{
table = realloc(table,(len+1)*sizeof(int));
table[len]=node->data;
len = len +1;
if(node->left == NULL && node->right == NULL)
{
int cmt=0;
for(cmt = 0; cmt < len ; cmt++ ){
printf("%d ->",table[cmt]);
}
}
else{
helper(node->left,table,len);
helper(node->right,table,len);
}
}
}
void print_rtl(struct node* node) {
if(NULL == node) return;
else{
int *t=malloc(sizeof(int));
t[0]=node->data;
int lenght = 1;
helper(node->left,t,1);
helper(node->right,t,1);
}
}
Here is the thing about realloc: it has the freedom to change not just the size of the allocated memory block, but also its location. In general, realloc can break any pointers you have that are pointing to objects in the block of memory that was realloced. When you try to use those pointers later, you will get undefined behavior.
You should either allocate enough memory at the beginning of your program that you won't need to call realloc, or you should redesign your program so you don't need to allocate that memory block in the first place, or you should make your table pointer be a global variable so that when you change its value, it gets updated for every function that is using the table.
Right now the problem with your code is that when you call helper, it might call realloc and change the location of your table, but it doesn't communicate that change to the caller in any way, so the caller doesn't know where the table is located.
There might be other problems with your code. If you continue to have trouble, I strongly urge you to produce an MCVE and post that in your next question. Doing that makes it much easier for someone else to reproduce your problem and find a solution to it that actually works.
It's hard to tell exactly what going on because it quite a big mess, but generally... The first thing helper() does (after validating node!=NULL) is reallocate table. That means when you get to the recursion point, helper(node->left.. will reallocate, and then immediately after helper(node->right.. will also try to do so, but on an invalid pointer. From there on, it's a wild ride to exceptions...
I have seen other answers to questions like this, but none seemed to work for me. Say I have a dynamic array:
int* myarray;
myarray = malloc(myarray, 4*sizeof(int));
myarray[0] = 1;
myarray[1] = 2;
myarray[2] = 3;
myarray[3] = 4;
What I want to do is to remove (and free, because the array will keep on getting larger and larger) the first element of the array. I am well aware of realloc which removes the last element of the array if shrunk. Any ideas on this? Is this possible?
Thanks in advance!
One method I can think of is doing
memmove(myarray, myarray+1, 3*sizeof(int))
and then use realloc to shrink the array. I'm not sure there are more efficient ways to do this in C.
You have to shunt all the other elements along one. Conceptually, it's like this:
for( int i = 0; i < 3; i++ ) p[i] = p[i+1];
As others have mentioned, memmove is optimized for shifting memory segments that overlap, rather than using the above loop.
Moving data around is still inefficient as your array grows larger. Reallocating an array every time you add an item is even worse. General advice is don't do it. Just keep track of how large your array is and how many items are currently stored in it. When you grow it, grow it by a significant amount (typically you would double the size).
It sounds like you might want a circular queue, where you preallocate the array, and a head and tail pointer chase each other round and round as you push and pop items on.
Typically a "Delete" operation is not possible on an array. Perhaps you want to create and use a linked list?
C++ has its std::vector which supports this. What it would do is to shift elements that come later, forward by 1 element. You could implement this, and call realloc later.
Storing them in reverse is an obvious workaround if only first element needs to be deleted.
I don't think that you'll find a proper/clean way to do that in C. C++ as some lybraries who do that, and almost all the OO oriented languages can do that, but not C. All I can think of is moving memory and, yes, calling realloc, or setting the position you want to free to a known value wich you'll consider empty in a memory re-use policy.
Another way to turn the problem is by a dynamic implementation of the array. DOn't know if you want to go there, but if you do, here's some brief example.
Since you're only saving integers, a struct like this:
typedef struct DynamicArray_st{
int x;
struct DynamicArray_st *next;
}DynamicArray;
Makes it possible to alloc and free elements as the program needs to. It also allows insertion in the middle, begin or end and the same for frees.
The way you'll do it is by saving a pointer to the begin of this dynamic type and then iterate over it.
The problem is that you can't access data by the [] notation. Iterations are necessary wich makes it heavier on processing time.
Besides that, your code would become something like this:
DynamicArray *array = malloc(sizeof(DynamicArray)); /*Just a first element that will stay empty so your Dynamic array persists*/
array->next = NULL;
DynamicArray *aux = array;
DynamicArray *new;
for(i = 0; i<4; i++){
new = malloc(sizeof(DynamicArray));
new->next = NULL;
new->x = i+1;
aux->next = new;
aux = new;
}
Here you have a sequence of structs in a way that each struct points to the next one and has a integer inside.
If now you'd do something like:
aux = array->next; /*array points to that empty one, must be the next*/
while(aux != NULL){
printf("%d\n",aux->x);
aux = aux->next;
}
You'll get the output:
1
2
3
4
And freeing the first element is as easy as:
aux = array->next;
array->next = aux->next;
free(aux);
If you try to draw it(structs are boxes and next/aux/next are arrows) you'll see one boxe's arrow outline an box - the one you want to free.
Hope this helps.
I'm having some trouble with the following:
void BuildList(cs460hwp hw)
{
FILE* fp;
fp = fopen("HW2input.dat", "r");
if(fp == NULL)
{
printf("Couldn't open the file.");
return;
}
int numStudents;
int i;
bool success;
char* dueDate = malloc(9*sizeof(char));
char* course = malloc(7*sizeof(char));
char* wsuid = malloc(9*sizeof(char));
char* subDate = malloc(9*sizeof(char));
double points1 = 0;
double points2 = 0;
cs460hwp stuInsert = NULL;
fscanf(fp, "%d", &numStudents);
fscanf(fp, "%s", dueDate);
for(i = 0; i < numStudents; i++)
{
stuInsert = malloc(sizeof(cs460hwp));
fscanf(fp, "%s %s %s %lf", course, wsuid, subDate, &points1);
strcpy(stuInsert->course, course);
strcpy(stuInsert->wsuid, wsuid);
strcpy(stuInsert->subdate, subDate);
stuInsert->points1 = points1;
stuInsert->points2 = CalculatePoints(dueDate, subDate, points1);
stuInsert->nextPtr = NULL;
if(hw == NULL)
{
hw = stuInsert;
}
else
{
stuInsert->nextPtr = hw;
hw = stuInsert;
}
}
free(course);
free(wsuid);
free(subDate);
free(dueDate);
PrintGrades(hw);
fclose(fp);
}
struct hwpoints
{
char course[7];
char wsuid[9];
char subdate[9];
double points1;
double points2;
struct hwpoints *nextPtr;
};
typedef struct hwpoints *cs460hwp;
My goal here is to insert every entry to the top of the list. However, whenever I try to assign anything to nextPtr (such as in the else clause), it gets filled with garbage values. They're mostly truncated versions of old data, which leads me to believe they're being taken from the heap. I've been reading (a lot), but I'm having trouble finding advice on this particular problem.
nextPtr always becomes junk, and nextPtr->nextPtr causes a segfault. For every iteration of the loop. hw remains fine, but its pointer value never gets updated properly.
Even when I've attempted to move the memory allocation for the struct into a function, I've had the same (or similar) issues.
Can anyone point me in the right direction?
Two problems.
1) As pb2q mentioned, you are passing a pointer to a struct and trying to assign what the arg points to. That's allowed by the compiler, but it doesn't do anything for you outside the function. It might be OK in your case if:
void main()
{
cs460hwp hw = NULL;
BuildList(hw);
return;
}
Is the whole of your function. I don't know the assignment so you need to figure out if that's acceptable to you or not.
2) The much bigger problem:
stuInsert = malloc(sizeof(cs460hwp));
Did you check what sizeof(cs460hwp) comes out to be? it's 4. You're allocating enough memory for the size of a pointer, not the size of your structure. I'm pretty sure this is not what you want to do and this is what is killing you. Just for kicks, replace it with malloc(100) and see if your problem goes away. If so you just need to figure out what size you really want. ;)
A problem with your BuildList function is that you're passing a pointer to a struct hwpoints, and you're trying to re-assign what the argument points to. Since function arguments in C are pass-by-value you're only changing the copy of the pointer that your function receives, and those changes won't be reflected in the caller.
You can use this pointer to modify the contents of the list: you can change e.g. hw->course or hw->nextPtr, you can move elements around in your list. But you can't change what the head, hw points to, so you can't insert elements at the beginning of the list.
If you want to change your head pointer, as in these statements:
hw = stuInsert;
// ...
hw = stuInsert;
Then you'll need to pass a pointer to the pointer:
void BuildList(cs460hwp *hw)
And de-reference it as necessary in the body of the function.
I can't be sure that this is the cause of the output that you're observing, which may be due to other problems. But if, after some number of calls to BuildList, beginning with a head pointer equal to NULL, you're trying to print your list assuming that it has valid nodes, you could see garbage data.
Thanks to #Mike's answer, we see also that you're not allocating enough space for your list nodes:
stuInsert = malloc(sizeof(cs460hwp));
Will only allocate enough space for a pointer, since cs460hwp is typedef'd to be a pointer to struct hwpoints. You need to allocate enough space for the structure, not a pointer to it:
stuInsert = malloc(sizeof(struct hwpoints));
I have a dynamic array of structures, so I thought I could store the information about the array in the first structure.
So one attribute will represent the amount of memory allocated for the array and another one representing number of the structures actually stored in the array.
The trouble is, that when I put it inside a function that fills it with these structures and tries to allocate more memory if needed, the original array gets somehow distorted.
Can someone explain why is this and how to get past it?
Here is my code
#define INIT 3
typedef struct point{
int x;
int y;
int c;
int d;
}Point;
Point empty(){
Point p;
p.x=1;
p.y=10;
p.c=100;
p.d=1000; //if you put different values it will act differently - weird
return p;
}
void printArray(Point * r){
int i;
int total = r[0].y+1;
for(i=0;i<total;i++){
printf("%2d | P [%2d,%2d][%4d,%4d]\n",i,r[i].x,r[i].y,r[i].c,r[i].d);
}
}
void reallocFunction(Point * r){
r=(Point *) realloc(r,r[0].x*2*sizeof(Point));
r[0].x*=2;
}
void enter(Point* r,int c){
int i;
for(i=1;i<c;i++){
r[r[0].y+1]=empty();
r[0].y++;
if( (r[0].y+2) >= r[0].x ){ /*when the amount of Points is near
*the end of allocated memory.
reallocate the array*/
reallocFunction(r);
}
}
}
int main(int argc, char** argv) {
Point * r=(Point *) malloc ( sizeof ( Point ) * INIT );
r[0]=empty();
r[0].x=INIT; /*so here I store for how many "Points" is there memory
//in r[0].y theres how many Points there are.*/
enter(r,5);
printArray(r);
return (0);
}
Your code does not look clean to me for other reasons, but...
void reallocFunction(Point * r){
r=(Point *) realloc(r,r[0].x*2*sizeof(Point));
r[0].x*=2;
r[0].y++;
}
The problem here is that r in this function is the parameter, hence any modifications to it are lost when the function returns. You need some way to change the caller's version of r. I suggest:
Point * // Note new return type...
reallocFunction(Point * r){
r=(Point *) realloc(r,r[0].x*2*sizeof(Point));
r[0].x*=2;
r[0].y++;
return r; // Note: now we return r back to the caller..
}
Then later:
r = reallocFunction(r);
Now... Another thing to consider is that realloc can fail. A common pattern for realloc that accounts for this is:
Point *reallocFunction(Point * r){
void *new_buffer = realloc(r, r[0].x*2*sizeof(Point));
if (!new_buffer)
{
// realloc failed, pass the error up to the caller..
return NULL;
}
r = new_buffer;
r[0].x*=2;
r[0].y++;
return r;
}
This ensures that you don't leak r when the memory allocation fails, and the caller then has to decide what happens when your function returns NULL...
But, some other things I'd point out about this code (I don't mean to sound like I'm nitpicking about things and trying to tear them apart; this is meant as constructive design feedback):
The names of variables and members don't make it very clear what you're doing.
You've got a lot of magic constants. There's no explanation for what they mean or why they exist.
reallocFunction doesn't seem to really make sense. Perhaps the name and interface can be clearer. When do you need to realloc? Why do you double the X member? Why do you increment Y? Can the caller make these decisions instead? I would make that clearer.
Similarly it's not clear what enter() is supposed to be doing. Maybe the names could be clearer.
It's a good thing to do your allocations and manipulation of member variables in a consistent place, so it's easy to spot (and later, potentially change) how you're supposed to create, destroy and manipulate one of these objects. Here it seems in particular like main() has a lot of knowledge of your structure's internals. That seems bad.
Use of the multiplication operator in parameters to realloc in the way that you do is sometimes a red flag... It's a corner case, but the multiplication can overflow and you can end up shrinking the buffer instead of growing it. This would make you crash and in writing production code it would be important to avoid this for security reasons.
You also do not seem to initialize r[0].y. As far as I understood, you should have a r[0].y=0 somewhere.
Anyway, you using the first element of the array to do something different is definitely a bad idea. It makes your code horribly complex to understand. Just create a new structure, holding the array size, the capacity, and the pointer.
I am implementing the standard bubble sort algorithm, and I had a question on pointers.
float *SortValues(float *p, size_t n)
{
float temp;
float didSwap;
float *current;
float *last = &p[n - 1];
float *start = p;
do
{
for (didSwap = 0, current = p; current < last; current++) {
if (current[0] > current[1]) {
temp = current[0];
current[0] = current[1];
current[1] = temp;
didSwap = 1;
}
}
--last;
}
while (didSwap);
return start;
}
I get confused a lot of times using other pointers to point to the start and/or end of the pointer passed in. In something like the code above, I set current to point to p, and start to point to p. The current changes throughout the loop. Since current and p point to the same thing, how does p, and therefore start end up changing to pointing to the same thing as current?
Where start is pointing doesn't change. What start is pointing at does.
Imagine you have five cups and you put a ball in the green one. Then you tell me to replace the ball in the green cup with a dollar bill. Next time you look in the green cup, it will contain a dollar, not the ball you put there.
The last time through the while loop, when last == start, only the initialization of the for loop is executed so that current == p when the while loop exits.
Subscripts vs. Pointers
Right now the code is written with a hybrid approach that uses some subscripting and some pointer addressing.
It's possible that if you rewrote this loop to work entirely with subscripts instead of the current hybrid addressing, then it would be easier to understand.
For that matter, it could be written to use entirely pointers with no subscripts.
I'm not complaining about the current organization which looks just fine, I'm just saying that it might shed some light on the implementation to see it done both ways in pure form.
But to answer your question, keep in mind that the list is always in the same location, it's just that elements have their values swapped. So the beginning of the list is always in the same place, but it doesn't always have the same contents. It's kind of nice that you have such an object-oriented picture embedded in your mind but in this case it is perhaps not serving you so perfectly well. Ultimately, data structures are just arrays of bits at specific addresses...