C: Memory usage and problems with Array - c

I have two arrays (representing rooms) with items that are traveling through the space. I found an interesting way to allocate the ram here in the forum. Here is what I am doing:
First I create an empty room with some default values.
After that I put some elements into it. There are two different items. An obstacle and an item that travels through the room. I have an iteration that runs for example 100 times and puts all items one coordinate further. The obstacles keep their position.
Every iteration has to do the following:
First it creates a new temporary room (new_room). It copies all obstacles because they stay at the same place(id = 3). Next, every item from the old room(room) gets his new coordinate in the new_room. After that I change the rooms, so room gets new_room. I have some big problems with the memory usage. I want to free the old new_room every time I create a new one with createRoomNew().In this implementation I get a segmentation fault. I think because of the function changeroom().
I am really confused right now because I am new to C.... I hope I pointed out what I mean. Thank you very much!
item_node ***room;
item_node ***room_new;
void createRoom(int x, int y, int z)
{
if (room == NULL) {
item_node *allElements = malloc(x * y * z * sizeof(item_node));
room = malloc(x * sizeof(item_node **));
for(int i = 0; i < x; i++)
{
room[i] = malloc(y * sizeof(item_node *));
for(int j = 0; j < y; j++)
{
room[i][j] = allElements + (i * y * z) + (j * z);
}
}
for (j = 0; j < x_format; j++) {
for (k = 0; k < y_format; k++) {
for (l = 0; l < z_format; l++) {
room[j][k][l].id = 3;
room[j][k][l].next = NULL;
}
}
}
}
}
void createRoomNew(int x, int y, int z)
{
if (room_new != NULL) {
for(int i = 0; i < x; i++)
{
free(room_new[i]);
}
free (room_new);
room_new = NULL;
}
if (room_new == NULL) {
item_node *allElements = malloc(x * y * z * sizeof(item_node));
room_new = malloc(x * sizeof(item_node **));
for(int i = 0; i < x; i++)
{
room_new[i] = malloc(y * sizeof(item_node *));
for(int j = 0; j < y; j++)
{
room_new[i][j] = allElements + (i * y * z) + (j * z);
}
}
}
for (j = 0; j < x_format; j++) {
for (k = 0; k < y_format; k++) {
for (l = 0; l < z_format; l++) {
if ((room[j][k][l].next) != NULL) {
if ((room[j][k][l].next->id) == 1) {
room_new[j][k][l] = room[j][k][l];
} else {
room_new[j][k][l].id = 3;
room_new[j][k][l].next = NULL;
}
}
else {
room_new[j][k][l].id = 3;
room_new[j][k][l].next = NULL;
}
}
}
}
}
void changeRoom(item_node *** newRoom)
{
room = newRoom;
}
Example call:
createRoom(200, 200, 200);
createRoomNew(200, 200, 200);
changeRoom(room_new);
createRoomNew(200, 200, 200);
changeRoom(room_new);

From the code it seems you think that when you do free, e.g. free(room_new) that room_new ends up being set to NULL. That is not the case
free() doesn't set a pointer to NULL (it can't), it is still pointing to wherever it was pointing just that the memory is no longer usable. You need to manually set the pointer to NULL after freeing.

Related

Runtime error on hackerrank problems for no reason?

This is the question:
https://www.hackerrank.com/challenges/lisa-workbook/problem.
My code passes all the test cases except one. The message I get is just Run Time Error. Even if I return 0 at the beginning of the function that I am supposed to implement, I still get this error, while in all other test cases I get Wrong Answer.
This is not the only question on hacker rank where this happened. In the last couple of days I encountered 3 or 4 more questions with that one odd case that was always giving a runtime error. In the end, I had to implement a Python 3 solution (with the same logic), which passed all the test cases, to solve these problems.
I wonder if this is a bug on the website or if I am understanding something wrongly. Here is my function implementation for this problem:
int workbook(int n, int k, int arr_count, int* arr)
{
int tmp = 1, specprob = 0;
int *chstart = malloc(n * sizeof(int));
int *chend = malloc(n * sizeof(int));
for (int i = 0; i < n; i++) {
chstart[i] = tmp;
tmp += arr[i] / k - 1;
if (arr[i] % k != 0) {
tmp++;
}
chend[i] = tmp;
tmp++;
if (!(arr[i] < chstart[i])) {
int qno = 0, chpage = 1, iqno = 0;
for (int j = chstart[i]; j < chend[i] + 1; j++) {
if (chpage * k <= arr[i]) {
qno += k;
} else {
qno += (k - (chpage * k - arr[i]));
}
if (j > iqno && j < qno + 1) {
specprob++;
}
iqno = qno;
chpage++;
}
}
}
return specprob;
}
It looks like a bug, since when you run the empty function with just a return 0; it gives the same runtime error.
For the moment though, if you don't mind too much about the different language, you could make a few minor changes to the code to make it compile for C++ (don't forget to change the language selection too):
int workbook(int n, int k, vector<int> arr)
{
int tmp = 1, specprob = 0;
int *chstart = (int*)malloc(n * sizeof(int));
int *chend = (int*)malloc(n * sizeof(int));
for (int i = 0; i < n; i++)
{
chstart[i] = tmp;
tmp += arr[i] / k - 1;
if (arr[i] % k != 0)
{
tmp++;
}
chend[i] = tmp;
tmp++;
if (!(arr[i] < chstart[i]))
{
int qno = 0, chpage = 1, iqno = 0;
for (int j = chstart[i]; j < chend[i] + 1; j++)
{
if (chpage * k <= arr[i])
{
qno += k;
}
else
{
qno += (k - (chpage * k - arr[i]));
}
if (j > iqno && j < qno + 1)
{
specprob++;
}
iqno = qno;
chpage++;
}
}
}
return specprob;
}

Dynamic 2 array in C

I am learning C and I am trying to have a virtual grid in it, where the user can put new grid elements to "activate" into the console. So for example if I am starting with nothing and the user adds (40,50), then the size is at least 40x50 with element (40,50) initialised. If (20,30) follows, it just activates the element at 20,30. But if the user then enters (500,300), it will allocate some more memory and increases the size of the array. I would like to access them easily. I would like to work (I might have to anyway), because they are new for me.
My code (at the moment) is the following:
int width = 4, height = 5;
bool **arr = (bool **) malloc(height * sizeof(bool *));
for (int x = 0; x < height; x++) {
arr[x] = (bool *) malloc(width * sizeof(bool));
}
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
*(*(arr + x) + y) = false;
}
}
*(*(arr + 3) + 2) = true;
// user puts a value bigger than (4,5) inside
int newX=10, newY = 10;
//allocate more memory
So I am using a 2D pointer with booleans and I do "malloc" the height first and afterwards make an array of them for the width.
In the last line is just an example of entering the first element at (2,3). The scan method for the user doesn't matter here.
So is there a way of increasing the size of my array afterwards or do I need a totally different concept for it?
=====
The current code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main() {
int width = 4, height = 5;
bool **arr = (bool **) malloc(height * sizeof(bool *));
for (int x = 0; x < height; x++) {
arr[x] = (bool *) malloc(width * sizeof(bool));
}
for (int x = 0; x < height; x++) {
for (int y = 0; y < width; y++) {
*(*(arr + x) + y) = false;
}
}
*(*(arr + 3) + 2) = true;
int newWidth = 10, newHeight = 10;
bool **narr = realloc(arr, newHeight * sizeof(bool*));
if(narr) {
arr = narr;
for(size_t i = 0; i < newHeight; i++){
bool* p = realloc(arr[i] , newWidth * sizeof(bool));
if( !p ){
perror("realloc");
}
arr[i] = p;
}
// here resize the number of elements if needed
}
else {
perror("realloc failed");
exit(EXIT_FAILURE);
}
return 0;
}
Yes there is a mathod called realloc. And you can use that. You can resize the jagged array completely.
bool **narr = realloc(arr , newsize * sizeof(bool*));
if( narr ) {
arr = narr;
for(size_t i = 0; i < newsize; i++){
bool* p = realloc(arr[i] , newsize1 * sizeof(bool));
if( !p ){
perror("realloc");
}
arr[i] = p;
}
// here resize the number of elements if needed
}
else {
perror("realloc failed");
exit(EXIT_FAILURE);
}
Also simplify things write a[1][2] instead of *(*(a+1)+2). The check is needed as realloc may fail - in that case instead of letting your code go awry, take appropriate step as needed.
Also note that you need to set all the newly allocated bool* to NULL. So do this:-
for(size_t i = 0; i < newHeight; i++){
if( i >= height)
arr[i] = NULL;
bool* p = realloc(arr[i] , newWidth * sizeof(bool));
if( !p ){
perror("realloc");
}
arr[i] = p;
}
This is needed because realloc expects address of memory previously allocated with *alloc functions or NULL.
You can use realloc to increase the size of the array
in your situation you'd do
arr = (bool **)realloc(arr, sizeof(bool*) * new_height)
for(int i = 0; i < new_height; i++){
arr[i] = (bool *)realloc(arr, sizeof(bool) * new_width);
}
Note that you have to check whether the array needs to even get bigger, realloc can also "shrink" your array so tread carefully.
Initializing the newly created memory to false:
for(int i = old_height; i < new_height; i++){
for(int j = old_width; j < new_width; j++){
arr[i][j] = false;
}
}
arr[new_height - 1][new_width - 1] = true;

Segmentation fault in function implementing Ford-Fulkerson

I'm working on a class assignment and I've run into an issue I haven't been able to figure out. I'm implementing the Ford-Fulkerson algorithm using BFS to find max flow. But while trying to set my Residual Capacity matrix to the given capacity, I hit a segmentation fault. In the test code we received, I can see that the original capacity matrix was passed by value by its address, but I have a feeling that in my code I'm not interacting with it the way I think I am? Which leads me to believe that I may have the same issue recurring elsewhere. I worked with gdb and saw that I hit a segmentation fault on this line here in my nested for loop :
resCap[i][j] = *(capacity + i*n + j);
However, nothing I have tried has worked for me though so I am pretty stumped.
void maximum_flow(int n, int s, int t, int *capacity, int *flow)
{
int i, j, resCap[n][n], path[n]; // residual capacity and BFS augmenting path
int min_path = INT_MAX; // min of the augmenting path
// Assign residual capacity equal to the given capacity
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
resCap[i][j] = *(capacity + i*n + j);
*(flow + i*n + j) = 0; // no initial flow
}
// Augment path with BFS from source to sink
while (bfs(n, s, t, &(resCap[0][0]), path))
{
// find min of the augmenting path
for (j = t; j != s; j = path[j])
{
i = path[j];
min_path = min(min_path, resCap[i][j]);
}
// update residual capacities and flows on both directions
for (j = t; j != s; j = path[j])
{
i = path[j];
if(*(capacity + i*n + j) > 0)
*(flow + i*n + j) += min_flow_path;
else
*(flow + j*n + i) -= min_flow_path;
resCap[i][j] -= min_flow_path;
resCap[j][i] += min_flow_path;
}
}
}
And here is the test code provided to us in case it is needed:
int main(void)
{ int cap[1000][1000], flow[1000][1000];
int i,j, flowsum;
for(i=0; i< 1000; i++)
for( j =0; j< 1000; j++ )
cap[i][j] = 0;
for(i=0; i<499; i++)
for( j=i+1; j<500; j++)
cap[i][j] = 2;
for(i=1; i<500; i++)
cap[i][500 + (i/2)] =4;
for(i=500; i < 750; i++ )
{ cap[i][i-250]=3;
cap[i][750] = 1;
cap[i][751] = 1;
cap[i][752] = 5;
}
cap[751][753] = 5;
cap[752][753] = 5;
cap[753][750] = 20;
for( i=754; i< 999; i++)
{ cap[753][i]=1;
cap[i][500]=3;
cap[i][498]=5;
cap[i][1] = 100;
}
cap[900][999] = 1;
cap[910][999] = 1;
cap[920][999] = 1;
cap[930][999] = 1;
cap[940][999] = 1;
cap[950][999] = 1;
cap[960][999] = 1;
cap[970][999] = 1;
cap[980][999] = 1;
cap[990][999] = 1;
printf("prepared capacity matrix, now executing maxflow code\n");
maximum_flow(1000,0,999,&(cap[0][0]),&(flow[0][0]));
for(i=0; i<=999; i++)
for(j=0; j<=999; j++)
{ if( flow[i][j] > cap[i][j] )
{ printf("Capacity violated\n"); exit(0);}
}
flowsum = 0;
for(i=0; i<=999; i++)
flowsum += flow[0][i];
printf("Outflow of 0 is %d, should be 10\n", flowsum);
flowsum = 0;
for(i=0; i<=999; i++)
flowsum += flow[i][999];
printf("Inflow of 999 is %d, should be 10\n", flowsum);
printf("End Test\n");
}
This line is likely going to segfault, it does using Clang.
int i, j, resCap[n][n], path[n];
You're declaring a very large array on the stack. Just how big can be seen when you try and allocated it using calloc. Try this instead and don't forget to free it using the same sort of loop.
int **resCap2 = calloc(1, n * sizeof(int *));
assert(resCap2);
for (i = 0; i < n; i++) {
resCap2[i] = calloc(1, n * sizeof(int));
assert(resCap2[i]);
}
This is a lot of space ie
(1000 * sizeof(int*) * (1000 * n * sizeof(int)))

C: Problems Using Free() on Structs Elements, Strange Behivor

I'm having problems by freeing the elements on my struct.
long code warning
typedef struct bingo
{
char board[5][5];
int* luckNum;
int* boardNum;
} bingo;
void update(bingo *pBingo,int num); //Function that gets a struct, number and checks if he is in the board, if it does he change it to "X"
int main(void)
{
srand(time(NULL));
int i, j, m, k, temp[75], *parr;
bingo player;
//For rellocating them later
if (!(player.luckNum = (int*) malloc(sizeof(int))))
{
printf("ERROR");
}
if (!(player.boardNum = (int*) malloc(sizeof(int))))
{
printf("ERROR");
}
//giving temp values of 1-75
for ( i = 0; i < 75; i++)
{
temp[i] = i + 1;
}
//Giving the player board random values of 1-75 without repeating the same number twice
for ( i = 0; i < 5; i++) //Passing on the rows
{
for (j = 0; j < 5; j++) //Passing on the columns
{
//
do
{
k = rand() % 75; //from 0-74
}
while (temp[k] == NULL); //while temp[k] is marked
player.board[i][j] = temp[k];
temp[k] = NULL; //NULL as a "flag" that marks the cell as taken (for not taking the same number twice)
player.luckNum=(int*) malloc(sizeof(int)*(i*j+j));
player.luckNum[i*j + j] = player.board[i][j];
}
}
//sets luckNum
for ( i = 0; i < 25; i++)
{
printf("%d ", player.luckNum[i]);
update(&player, player.luckNum[i]);
}
printf("\n");
for ( i = 0; i < 25; i++)
{
printf("%d",player.luckNum);
}
free(player.boardNum);
free(player.luckNum);
getchar();
return 0;
}
void update(bingo *pBingo, int num)
{
int i, j, k;
static int counter = 0,luckCounter = 25;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 5; j++)
{
if (num == (int) (pBingo->board[i][j]))
{
pBingo->board[i][j] = 'X';
counter++;
pBingo->boardNum = (int*) realloc(pBingo->boardNum, sizeof(int)*counter);
pBingo->boardNum[counter] = num;
for (k = 0; k < luckCounter; k++)
{
if (pBingo->luckNum[k] == num)
{
num = pBingo->luckNum[k];
pBingo->luckNum[k] = pBingo->luckNum[luckCounter-1];
pBingo->luckNum[luckCounter-1] = num;
pBingo->luckNum = (int*) realloc(pBingo->luckNum, sizeof(int)*luckCounter);
luckCounter--;
}
}
}
}
}
}
Can anyone recognize what interrupts the free() function from freeing the memory?. I'm new to C and working on this code about good days so sorry for my ignorance about free() function, can anyone help me?
Ilan,
Don't be afraid to post your code with the necessary includes. First of all, are you heeding to the warnings of your compiler?
A few problem areas:
while (temp[k] == NULL)
You can research the difference between 0, NULL and '\0' but reserve the use of NULL for pointers. Also:
for ( i = 0; i < 25; i++)
{
printf("%d",player.luckNum);
}
Printf is expecting an integer and you're giving it a pointer. Finally, to address what I think is your problem, when you write "..interrupts the free() function from freeing the memory?" Do you mean your program simply not returning? If so then get rid of the final getchar(). You're still going to have at least one leak in this program. This address of this malloc:
if (!(player.luckNum = (int*) malloc(sizeof(int))))
will be lost as you assigned luck.Num a new address here without freeing the first:
player.luckNum=(int*) malloc(sizeof(int)*(i*j+j));

Expression cannot be evaluated. Malloc fail

I' having a problem allocating a structure in a function. Here is the code(I'm currently using visual studio 2008):
Mat3x3* ProdMat(Mat3x3 *m, Mat3x3 *n)
{
if(m == NULL || n == NULL)
{
cout << "\t[W] Cannot compute product of the two matrixes one or both are NULL." << endl;
return NULL;
}
Mat3x3 *p; // product
int i, j;
float sum = 0;
p = (Mat3x3*)malloc(sizeof(Mat3x3)); // <= Exp cannot be evaluated
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
sum = 0;
for(int k = 0; k < 3; k++)
{
float a = m->a[i][k];
float b = n->a[k][j];
sum += a * b;
}
p->a[i][j] = sum;
}
}
return p;
}
P contains a matrix with 9 entries. Here is the context in which the error is given:
Mat3x3* compute_final_trans(Trans **transes) // compute product of all transformation matrixes from right to left
{
int k_trans = 0, i, j;
Mat3x3 *final_trans;
if(transes == NULL)
{
printf("\t[E] Cannot compute sequence of NULL transformations.\n");
return NULL;
}
final_trans = (Mat3x3*)malloc(sizeof(final_trans));
for(i = 0; i < 3; i++) // generate eye matrix
for(j = 0; j < 3; j++)
{
if(i == j)
{
final_trans->a[i][j] = 1;
}
else
{
final_trans->a[i][j] = 0;
}
}
while(transes[k_trans++]);
for(i = k_trans - 2; i >= 0; i--)
{
final_trans = ProdMat(transes[i]->matrix, final_trans); // <= ERROR
}
return final_trans;
}
Final trans is initialised as the eye matrix and transes have been succesfully computed before this step(before calling compute_final_trans). The while is used to retreieve the number of transformations that transes contains. At line:
final_trans = ProdMat(transes[i]->matrix, final_trans);
ProdMat fails to allocate memory for p which is a pointer to a Mat3x3 structure.
perror suggests that there isn't enough memory to allocate to the structure. However I'm only using 1GB of RAM(4GB in all).
Any help/suggestion/reference will be very much appreciated.
Sebi
malloc(sizeof(final_trans))
This is bad. You are only allocating enough space for a pointer, not space for an array.

Resources