I am VERY new to C, but I thought that I'd learn it while I'm learning basic data structures. Anyway, I'm having a problem wrapping my head about how/where errors are coming up in my code.
Basically, I'm getting two different kinds of errors:
Segmentation Faults (# binary heap length 2 and 3) when subtracting from heap.
Malloc/Realloc errors when I add to binary heap enough to make it to length 4 (and beyond), and then subtract to length 2 (I get a non-valid binary heap structure # length 3 when I do this as well).
Basically, I just want to see what exactly I'm doing wrong to get this behavior. Also, if there's anything in my code that is downright appaling, I'd like to know that too.
So, here's my code:
void printArray(int array[], int size) {
printf("[");
for (int i = 0; i < size; i++) {
if (i == (size - 1)) {
printf("%d", array[i]);
} else {
printf("%d, ", array[i]);
}
}
printf("]\n");
}
int getLeftChild(int h_array[], int p_index, int size) {
/* Summary: Obtains the `left child` of Parent at given parent index (p_index)
*
* Input: `h_array` - The binary heap
* `p_index` - The index of the parent that we are currently looking at
* `size` - The size of the binary heap.
*
* Return: `0` if the index given points out of bounds of the array. Returns the child of parent at p_index if not
*/
int child = 0;
if (p_index * 2 + 1 < size) {
child = h_array[p_index * 2 + 1];
}
return child;
}
int getRightChild(int h_array[], int p_index, int size) {
/* Summary: Obtains the `right child` of Parent at given parent index (p_index)
*
* Input: `h_array` - The binary heap
* `p_index` - The index of the parent that we are currently looking at
* `size` - The size of the binary heap.
*
* Return: `0` if the index given points out of bounds of the array. Returns the child of parent at p_index if not
*/
int child = 0;
if ((p_index * 2 + 2) < size) {
child = h_array[p_index * 2 + 2];
}
return child;
}
void heapSort(int h_array[], int size, int min_max) {
/* Summary: Performs a heap sort on a binary heap array; parents with 2 children maximum.
* This could be used to implement a priority queue, as the node with the highest (or lowest)
* priority will be at the root of the list.
* Input: `h_array` - the heap array to sort
* `size` - The size of the heap array
* `min_max` - an input that will tell whether or not we want to return a 'maxed', or a 'min'd' binary heap.
* maxed will have highest priority at the root, and min'd will have the lowest priority at the root
*
* Returns: Does not return. Performs all sorting operations on input array.
**/
int parent, leftChild, rightChild, p_holder, i = 0;
while (i < (size / 2)) {
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
if (min_max == 0 ) {
while (parent < leftChild || parent < rightChild) {
p_holder = parent;
if (parent < leftChild) {
h_array[i] = leftChild;
h_array[(i * 2) + 1] = p_holder;
} else if (parent < rightChild) {
h_array[i] = rightChild;
h_array[(i * 2) + 2] = p_holder;
}
i = 0;
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
}
i++;
} else {
while ((leftChild != 0 && parent > leftChild) || (rightChild != 0 &&parent > rightChild)) {
p_holder = parent;
if ((leftChild != 0) && parent > leftChild) {
h_array[i] = leftChild;
h_array[(i * 2) + 1] = p_holder;
} else if ((rightChild != 0) && parent > rightChild) {
h_array[i] = rightChild;
h_array[(i * 2) + 2] = p_holder;
}
i = 0;
parent = h_array[i];
leftChild = getLeftChild(h_array, i, size);
rightChild = getRightChild(h_array, i, size);
}
i++;
}
}
}
void heapAdd(int h_array[], int *a_size, int value, int *min_max_ptr) {
/* Summary: Adds a value to the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* `value` - The value that is to be inserted in the array
* Returns: Void function. Performs all operations on inputted array.
*/
*a_size += 1;
int * a_copy = h_array;
h_array = realloc(h_array, *a_size * sizeof(int));
memcpy(h_array, a_copy, (*a_size - 2) * sizeof(int));
h_array[*a_size - 1] = value;
heapSort(h_array, *a_size, *min_max_ptr);
}
void heapSub(int h_array[], int *a_size, int *min_max_ptr) {
/* Summary: Subtracts the root value from the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* Returns: Void function. Performs all operations on inputted array.
*/
h_array[0] = h_array[*a_size - 1];
int * a_copy = h_array;
h_array = realloc(h_array, *a_size - 1 * sizeof(int));
memcpy(h_array, a_copy, (*a_size - 1) * sizeof(int));
*a_size -= 1; // Put here in order to not do any stupid calculations in the calls.
heapSort(h_array, *a_size, *min_max_ptr);
}
int main(void) {
char * user_input;
int user_value;
int debug = 0;
// min_max = 0 to produce a max-heap, min_max = 1 to produce a min-heap
int min_max = 0;
int *min_max_ptr = &min_max;
int size = 0;
int *size_ptr = &size;
// Binary Heap array, initialized here
int * main_array = malloc(size * sizeof(int));
// Start building binary heap with the following loop.
while (strcmp(user_input, "q") != 0) {
printf("Current Heap:\n");
printArray(main_array, size);
// Debug
if (debug) {
printf("Current Heap Size: %i\n", size);
}
printf("What is your input?: ");
scanf("%s", user_input);
// Debug
if (debug) {
printf("Current user input is: %s\n", user_input);
}
if (strcmp(user_input, "add") == 0) {
printf("What # will you be adding to the heap?: ");
scanf("%i", &user_value);
heapAdd(main_array, size_ptr, user_value, min_max_ptr);
} else if (strcmp(user_input, "sub") == 0) {
printf("Subtracting %i from array\n", main_array[0]);
heapSub(main_array, size_ptr, min_max_ptr);
} else if (strcmp(user_input, "debug") == 0) {
printf("Do you want to toggle debug mode(y/n): ");
scanf("%s", user_input);
if (strcmp(user_input, "y") == 0) {
debug = (debug == 0) ? 1 : 0;
printf("Debug is: %i", debug);
} else {
continue;
}
} else {
printf("Incorrect Input, please read the instructions more\n\n");
}
printf("\n");
}
free(main_array);
return 0;
}
So that's the code, and here are the test cases:
Subtracting highest value from heap # length = 2 test case 1
Subtracting highest values from heap starting # length = 4 and going to length = 2 test case 2
After that it seems like every other test case works fine (past length = 4 I can add and subtract from binary heap just fine and the sorting process works great). Thank you for your help :)
I was able to reach a solution to my problems by making the following changes to my code:
void heapAdd(int h_array[], int *a_size, int value, int *min_max_ptr) {
/* Summary: Adds a value to the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* `value` - The value that is to be inserted in the array
* Returns: Void function. Performs all operations on inputted array.
*/
*a_size += 1;
h_array[*a_size - 1] = value;
heapSort(h_array, *a_size, *min_max_ptr);
}
void heapSub(int h_array[], int *a_size, int *min_max_ptr) {
/* Summary: Subtracts the root value from the binary heap
* Input: `h_array` - The binary heap array
* `a_size` - The size of the array. A pointer to `size` located in main().
* Returns: Void function. Performs all operations on inputted array.
*/
h_array[0] = h_array[*a_size - 1];
h_array[*a_size - 1] = 0;
*a_size -= 1; // Put here in order to not do any stupid calculations in the calls.
heapSort(h_array, *a_size, *min_max_ptr);
}
int main(void) {
char * user_input;
int user_value;
int debug = 0;
// min_max = 0 to produce a max-heap, min_max = 1 to produce a min-heap
int min_max = 0;
int *min_max_ptr = &min_max;
int size = 0;
int *size_ptr = &size;
int alloc_size = 1000;
int * main_array = malloc(alloc_size * sizeof(int));
do {
if (alloc_size - size < 2) {
printf("Reallocating the main_array size");
alloc_size += 1000;
main_array = realloc(main_array, alloc_size * sizeof(int));
if (main_array == NULL) {
printf("realloc addition failed, exiting");
exit(1);
}
} else if (alloc_size - size > 1002) {
alloc_size -= 1000;
main_array = realloc(main_array, alloc_size * sizeof(int));
if (main_array == NULL) {
printf("Realloc subtraction failed, exiting");
exit(1);
}
}
printf("Current Heap:\n");
printArray(main_array, size);
// Debug
if (debug) {
printf("Current Heap Size: %i\n", size);
}
printf("What is your input?: ");
scanf("%s", user_input);
// Debug
if (debug) {
printf("Current user input is: %s\n", user_input);
}
if (strcmp(user_input, "add") == 0) {
printf("What # will you be adding to the heap?: ");
scanf("%i", &user_value);
heapAdd(main_array, size_ptr, user_value, min_max_ptr);
} else if (strcmp(user_input, "sub") == 0) {
if (size == 0) {
printf("Can't subtract any more from the heap.\n");
continue;
} else {
printf("Subtracting %i from array\n", main_array[0]);
heapSub(main_array, size_ptr, min_max_ptr);
}
} else if (strcmp(user_input, "debug") == 0) {
printf("Do you want to toggle debug mode(y/n): ");
scanf("%s", user_input);
if (strcmp(user_input, "y") == 0) {
debug = (debug == 0) ? 1 : 0;
printf("Debug is: %i", debug);
} else {
continue;
}
} else {
printf("Incorrect Input, please read the instructions more fully\n\n");
}
printf("\n");
} while (strcmp(user_input, "q") != 0);
free(main_array);
return 0;
}
Related
there is a part where the program asks the user to enter Y or N and then loops beck when I choose N or else it will end the while loop and continue. when I choose the Y for the first time the program works fine but when I choose N and then Y after my program exits even if it does not encounter the return keyword from the main
and it exits with a garbage return value. It stops at system("cls");. Can anyone tell me what's wrong with this code. Note:
Statistician is an integer pointer type that I created with typedef. And, I've also declared the SIZE variable in the survey.h file
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include "survey.h"
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
SIZE = 10;
int c, count = 0, item = 0;
Statistician arr;
float mea, med;
arr = (int*)calloc(10, sizeof(int));
printf("Enter 10 answers\n");
while(count < SIZE) // this is the while loop that loops until Y is chosen by the user in the add function
{
while(item > 9 || item < 1)
{
scanf("%d", &item);
}
++count;
add(arr, &count, &SIZE, item);
item = 0;
}
system("cls");
mea = mean(arr, count);
med = median(arr, count);
printf("mean = %f\n", mea);
printf("median = %f\n", med);
return 0;
}
definition of add() function:
void add(Statistician answer, int *count, int *SIZE, int item)
{
int i, j, temp;
bool swapped;
char choice;
answer[*count - 1] = item;
for(i = 0; i < *count - 1; i++)
{
swapped = false;
for(j = 0; j < *count - i - 1; j++)
{
if(answer[j] > answer[j + 1])
{
temp = answer[j];
answer[j] = answer[j + 1];
answer[j + 1] = temp;
swapped = true;
}
}
if(swapped == false)
break;
}
if(*count == *SIZE)
{
printf("Array is full do you want to compute now?\n");
while(toupper(choice) != 'N' && toupper(choice) != 'Y') // The part where the program ask for Y or N.
{
choice = toupper(getch());
}
if(toupper(choice) == 'Y') // returns without changing the value of SIZE thus ending the while loop at main
{
return;
}
else if(toupper(choice) == 'N') // adds 10 to SIZE thus continuing the while loop in main and returns
{
printf("add another 10 answers\n");
*SIZE += 10;
realloc(answer, *SIZE);
}
}
return;
}
There are probably other issues (I'm not going to look too closely), but you certainly need to fix:
while(item > 9 || item < 1)
{
scanf("%d", &item);
}
If scanf matches zero items, then that is an infinite loop, with scanf repeatedly returning 0, reading the same data and not changing item. You must always check the value returned by scanf.
This is a serious bug:
realloc(answer, *SIZE);
You don't save the return value so you have lost the allocated memory. Further, you forgot the object size.
In principle you should do
Statistician tmp = realloc(answer, *SIZE * sizeof(int));
if (tmp == NULL)
{
// Error handling
// or just
exit(1);
}
answer = tmp;
However, that doesn't fully help. The problem is that it will only change the value of answer inside the function but not the value of arr in main. In order to change the value of arr you'll have to pass the address of arr to the function. Similar to what you have done with SIZE. BTW: Why do you pass counter as a pointer? You never change it in the function, so it unnecessary to pass a pointer.
Also your current code doesn't initialize choice.
Change
printf("Array is full do you want to compute now?\n");
while(toupper(choice) != 'N' && toupper(choice) != 'Y') // The part where the program ask for Y or N.
to
printf("Array is full do you want to compute now?\n");
choice = ' ';
while(toupper(choice) != 'N' && toupper(choice) != 'Y') // The part where the program ask for Y or N.
or better:
printf("Array is full do you want to compute now?\n");
do
{
choice = toupper(getch());
} while(toupper(choice) != 'N' && toupper(choice) != 'Y');
BTW:
Since you have choice = toupper(getch()); you don't need toupper(choice) != 'N'. Simply do choice != 'N'
All that said - why do you want to ask the question inside the function? Your code will be much simpler if you do it in main.
Something like:
int main(void) {
int SIZE = 10;
int c, count = 0, item = 0;
int* arr;
float mea, med;
arr = calloc(10, sizeof(int));
printf("Enter 10 answers\n");
while(count < SIZE)
{
while(item > 9 || item < 1)
{
if (scanf("%d", &item) != 1) exit(1);
}
++count;
add(arr, count, item);
item = 0;
if (count == SIZE)
{
printf("Array is full do you want to compute now?\n");
char choice;
do
{
choice = toupper(getch());
} while(choice != 'N' && choice != 'Y');
if(choice == 'N')
{
printf("add another 10 answers\n");
SIZE += 10;
int* tmp = realloc(arr, SIZE * sizeof *arr);
if (tmp == NULL) exit(1); // or error handling
arr = tmp;
}
}
}
system("cls");
mea = mean(arr, count);
med = median(arr, count);
printf("mean = %f\n", mea);
printf("median = %f\n", med);
return 0;
}
void add(int* answer, int count, int item)
{
int i, j, temp;
bool swapped;
answer[count - 1] = item;
for(i = 0; i < count - 1; i++)
{
swapped = false;
for(j = 0; j < count - i - 1; j++)
{
if(answer[j] > answer[j + 1])
{
temp = answer[j];
answer[j] = answer[j + 1];
answer[j + 1] = temp;
swapped = true;
}
}
if(swapped == false)
break;
}
return;
}
I currently have this program that I have working. It works when I input values from the keyboard, but now I am trying to make it work by reading data from the file and make it execute depending on the data from the file. Here is the data from the file...
1
65536
1027
16
1
65536
1024
4096
1
65536
1024
16
3
65535
14
2
65535
3
65534
512
2
1023
4
Here is where I scan the file and store the inputs.
//Declare and initialize variables.
int option = 0;
int mainMemSize = 65536;
int cacheSize = 1024;
int blockSize = 16;
int tags = mainMemSize / cacheSize;
int *mainMemPtr = NULL;
line *cachePtr = NULL;
FILE *filePtr;
//Initialize the memory.
mainMemPtr = initMainMemory(mainMemSize);
cachePtr = initCache(cacheSize);
filePtr = fopen("prog2_test_data.txt", "r");
printf("*** Starting to read data from file: prog2_data_test.txt");
fscanf(filePtr, "%d", &option);
do
{
showMenu();
switch (option)
{
case 1:
freeCache(&cachePtr, tags);
free(mainMemPtr);
setParameters(mainMemSize, cacheSize, blockSize);
tags = mainMemSize / cacheSize;
mainMemPtr = initMainMemory(mainMemSize);
cachePtr = initCache(cacheSize);
break;
case 2:
readCache(mainMemPtr, cachePtr, mainMemSize, blockSize, cacheSize);
break;
case 3:
writeCache(mainMemPtr, cachePtr, mainMemSize, blockSize, cacheSize);
break;
case 4:
break;
}
}while (option != 4);
if (cachePtr != NULL)
freeCache(&cachePtr, tags);
if (mainMemPtr != NULL)
free(mainMemPtr);
fclose(filePtr);
printf("***Memory Freed Up - Program Terminated");
getchar();
}
void setParameters(int mainMemSize, int cacheSize, int blockSize)
{
if (blockSize > cacheSize)
{
printf("*** Error – Block size is larger than cache size\n");
}
else if ((cacheSize % blockSize) != 0)
{
printf("*** Error – Cache size is not a power of 2\n");
}
else if ((blockSize % 2 == 0) && (cacheSize % 2 == 0))
{
printf("***Data Accepted \n");
}
}
void showMenu()
{
printf("\nMain memory to Cache memory mapping: \n");
printf("------------------------------------ \n");
printf("1) Enter Configuration Parameters\n");
printf("2) Read from cache\n");
printf("3) Write to cache\n");
printf("4) End\n");
}
int* initMainMemory(int size)
{
int j;
//initialize main memory.
int* ptr = (int*)malloc(size * sizeof(int));
for (j = 0; j < size; ++j)
*(ptr + j) = size - j;
return ptr;
}
line* initCache(int tags)
{
int j;
line* ptr = (line*)malloc(tags * sizeof(line));
for (j = 0; j < tags; ++j)
{
ptr[j].tag = -1;
ptr[j].block = NULL;
}
return ptr;
}
void freeCache(line **ptr, int size)
{
int j = 0;
for (; j < size; ++j)
{
if ((*ptr)[j].block != NULL)
free((*ptr)[j].block);
}
free(*ptr);
}
void readCache(int* mainMemPtr, line* cachePtr, int mmSize, int blockSize,
int cacheSize)
{
//Declare and initialize variables.
int address = 0;
int value = 0;
int tag;
int myBlock;
int word;
int j;
int baseOffset;
int alreadyMissed = 0;
address = mmSize;
//Compute.
baseOffset = (address / blockSize) * blockSize;
tag = address / cacheSize;
word = address % blockSize;
myBlock = (address % cacheSize) / blockSize;
//Check if tag does not match or not.
if (cachePtr[myBlock].tag != tag)
{
//Display this.
printf("***Cache hit\n");
alreadyMissed = 1;
cachePtr[myBlock].tag = tag;
}
//Check if cache block memory is equal to NULL or not.
if (cachePtr[myBlock].block == NULL)
{
//Condition check.
if (alreadyMissed == 0)
printf("***Cache hit\n");
//Block Allocation.
cachePtr[myBlock].block = (int*)malloc(blockSize * sizeof(int));
}
//Read from the main memory
for (j = 0; j < blockSize; ++j)
{
cachePtr[myBlock].block[j] = mainMemPtr[baseOffset + j];
}
printf("Word %d of block %d with tag %d have %d\n", word, myBlock, tag,
cachePtr[myBlock].block[word]);
}
void writeCache(int* mainMemPtr, line* cachePtr, int mmSize, int
blockSize, int cacheSize)
{
//Declare and initialize variables.
int address = 0;
int value = 0;
int tag;
int myBlock;
int word;
int j;
int baseOffset;
int alreadyMissed = 0;
address = mmSize;
//Compute.
baseOffset = (address / blockSize) * blockSize;
tag = address / cacheSize;
word = address % blockSize;
myBlock = (address % cacheSize) / blockSize;
//Assign new value.
mainMemPtr[address] = value;
//Check if tag does not match or not.
if (cachePtr[myBlock].tag != tag)
{
printf("***Write miss - First Load block from memory\n");
alreadyMissed = 1;
cachePtr[myBlock].tag = tag;
}
//Check if cache block memory is equal to NULL or not.
if (cachePtr[myBlock].block == NULL)
{
if (alreadyMissed == 0)
printf("Write miss!\n");
//Block Allocation.
cachePtr[myBlock].block = (int*)malloc(blockSize * sizeof(int));
}
//Transfer from the main memory to the cache.
for (j = 0; j < blockSize; ++j)
cachePtr[myBlock].block[j] = mainMemPtr[baseOffset + j];
printf("***Word %d of block %d with tag %d have %d\n", word, myBlock, tag,
cachePtr[myBlock].block[word]);
}
This should be the desire output after the program starts debugging.
*** Starting to Read Data from the input file: prg2_data.txt
*** Error - Cache Size is not a Power of 2! Returning to Main Menu
*** Error - Block Size is Larger than Cache Size! Returning to Main Menu
*** All Input Parameters Accepted. Starting to Process Write/Read Requests
* Write Miss... First load Block from Memory!
* Word 15 of Cache Line 63 with Tag 63 contains Value 14
* Cache Hit
* Word 15 of Cache Line 63 with Tag 63 contains Value 14
* Cache Hit
* Word 14 of Cache Line 63 with Tag 63 contains Value 512
* Read Miss... Load Block from Memory!
* Word 15 of Cache Line 63 with Tag 0 contains Value 64513
*** Memory Freed Up - Program Terminated Normally
What happens instead is an infinite loop. I can't seem to spot the problem.Can someone please help me out.
while (!eof(filePtr))
fscanf(filePtr, "%d %d %d %d", &option, &mainMemSize, &cacheSize, &blockSize);
There are two things wrong here:
The eof function doesn't predict the future. You can't use it to predict that a future read will fail and thereby avoid that read. Instead, check if the read actually succeeded or failed and, if it failed, stop.
This repeats the fscanf operation over and over, each time overwriting the previous results. You don't want to call fscanf again after it returns, so the loop should not be here.
I am trying to create a c code that will sort an array with multiple threads, so i need to use barriers to synchronize threats
void sort(struct ThreadArguments* args){
struct ThreadArguments* the_args= (struct ThreadArguments*)args;
printf("thread %d started \n", the_args->id);
fflush(stdout);
pthread_barrier_wait (the_args->barrier);
printf("thread %d finished the iteration \n", the_args->id);
fflush(stdout);
}
My arguments structure looks like that
struct ThreadArguments {
unsigned int id;
int* array;
pthread_barrier_t* barrier;
}
And this is how I initialize barriers
pthread_barrier_init (&barrier, NULL, 4);
I expect it to do one iteration of sorting method then wait for all threads finish at the barrier then proceed, but what is does is
thread 0 started
thread 1 started
thread 2 started
thread 3 started
and then get stuck. What might be the problem?
EDIT: Full code
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <pthread.h>
#define MAXFILENAME 64
#define TIMESTEP 200000
#define MAXTHREADS 2046
//Thread arguemnt struct
struct ThreadData {
unsigned int id; //thread's id
int start; //starting index of the workers's part
int step; //step between each consecutive cells
int cells; //how many cells is worker respnsible for
pthread_barrier_t* enter_barrier; //this barrier synchornizes threads to wait till the copy of the array is created
pthread_barrier_t* exit_barrier; //this barrier is used to wait till all threads finished updating
pthread_barrier_t* print_barrier;
int print;
int iter;
int rows; //row dimensions
int columns; //column dimensions
char* array; //pointer to the original array
char* working_array; //pointer to the dublicate array used during each step
};
int readIn(int *rows, int *columns, int *iter, int *num_cells, FILE *fp);
char *initialize(int rows, int columns, int num_cells, FILE *fp);
void printBoard(int rows, int columns, char *cells, int num_cells);
int checkNeighb(int rows, int columns, char *cells, int num_cells, int target);
void evolve(struct ThreadData* args);
void printUsage(int code);
void initializeThreads(int part_type, int num_iter, int print_opt, struct ThreadData* data, int num_threads, int num_rows, int num_cols, char* cells);
int processAgrs(int argc, char **argv, char **filename, int* print_opt, int* num_threads, int* part_type, int* print_per_thread);
// Main method
int main(int argc, char *argv[]) {
int num_rows; //number of rows on the board
int num_cols;
int num_iter;
int num_cells;
int print_opt;
int num_threads;
int part_type;
int print_per_thread;
int i, ret;
char *filename = malloc(MAXFILENAME*sizeof(char));
ret = processAgrs(argc, argv, &filename, &print_opt, &num_threads, &part_type, &print_per_thread);
if(ret == -1)
{
exit(1);
}
FILE *fp = fopen (filename, "rb"); //openning file
if(fp == NULL)
{
perror("Error openning file");
exit(1);
}
if(readIn(&num_rows, &num_cols, &num_iter, &num_cells, fp) == -1) //check that everything was successful
{
printf("Error reading from file \n");
exit(1);
}
char* cells = initialize(num_rows, num_cols, num_cells, fp);
if(cells == NULL)
{
printf("Error initializing board! \n");
exit(1);
}
struct ThreadData *data = malloc(num_threads * sizeof(struct ThreadData));
initializeThreads(part_type, num_iter, print_opt, data, num_threads, num_rows, num_cols, cells);
struct timeval start_time, end_time;
double elapsed = 0;
if(gettimeofday(&start_time, NULL) == -1)
{
printf("Error getting time \n");
elapsed = -1;
}
pthread_t *thread = malloc(num_threads*sizeof(pthread_t));
printf("Start creating threads");
fflush(stdout);
// Launching Threads
for (i=0; i<num_threads; i++) {
printf("Create threads %d \n", i);
fflush(stdout);
ret = pthread_create(&thread[i], NULL,(void *) &evolve,(void *) &data[i]);
if(ret != 0)
{
printf("Error creating thread");
}
}
// Waiting for Threads to Finish
for (i=0; i<num_threads; i++) {
pthread_join(thread[i], NULL);
}
if(gettimeofday(&end_time, NULL) == -1 || elapsed == -1)
{
printf("Time was not calulcated due to error! \n");
}
else{ //print ellapsed time
elapsed = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0;
printf("total time for %d iterations of %dx%d world is %.6f secs \n",num_iter, num_rows, num_cols, elapsed);
}
free(cells);
free(filename);
return 0;
}
void initializeThreads(int part_type, int num_iter, int print_opt, struct ThreadData* data, int num_threads, int num_rows, int num_cols, char* cells)
{
int i, prev;
int num_of_extras; //extras is thread that gets one more line/column
pthread_barrier_t enter_barrier; //this barrier synchornizes threads to wait
//till the copy of the array is created
pthread_barrier_t exit_barrier;//this barrier waits for all threads to finish updating cells
pthread_barrier_t print_barrier;
pthread_barrier_init (&enter_barrier, NULL, num_threads); //initialize barrier for copying array
pthread_barrier_init (&exit_barrier, NULL, num_threads); //initialize exit barrier
pthread_barrier_init (&print_barrier, NULL, num_threads);
char *copy_cells = malloc((num_rows * num_cols) * sizeof(char));
if(copy_cells == NULL) //Checking malloc
{
perror("Error mallocing");
free(copy_cells);
return;
}
for (i = 0; i < num_threads; i++)
{
data[i].enter_barrier = &enter_barrier;
data[i].exit_barrier = &exit_barrier;
data[i].print_barrier = &print_barrier;
data[i].iter = num_iter;
data[i].rows = num_rows;
data[i].columns = num_cols;
data[i].working_array = copy_cells;
data[i].array = cells;
data[i].print = print_opt;
}
if( part_type == 0) //if row-wise paritioning
{
int lines_per_thread = num_rows / num_threads;
num_of_extras = num_rows % num_threads;
prev = 0;
for (i = 0; i < num_threads; i++)
{
data[i].id = i;
data[i].start = prev;
if( num_of_extras == 0)
{
data[i].cells = lines_per_thread * num_cols;
prev+=data[i].cells;
}
else{
data[i].cells = (lines_per_thread + 1) * num_cols;
prev+=data[i].cells;
num_of_extras--;
}
data[i].step = 1;
}
}
else{ //column-wise patitioning
int columns_per_thread = num_cols / num_threads;
num_of_extras = num_cols % num_threads;
prev = 0;
for (i = 0; i < num_threads; i++)
{
data[i].id = i;
data[i].start = prev;
if( num_of_extras == 0)
{
data[i].cells = columns_per_thread * num_rows;
}
else{
data[i].cells = (columns_per_thread + 1) * num_rows;
num_of_extras--;
}
data[i].step = num_cols;
prev++;
}
}
}
int processAgrs(int argc, char **argv, char **filename, int* print_opt, int* num_threads, int* part_type, int* print_per_thread)
{
if (argc < 6) { //reading arguments from command line
printf("Too few arguments!");
printUsage(1);
return -1;
}
else if(argc > 6)
{
printf("Too many arguments!");
printUsage(1);
return -1;
}
else
{
strcpy(*filename, argv[1]);
*print_opt = strtol(argv[2], NULL, 10); //using strtol() to convert string to int
if(*print_opt < 0 || *print_opt > 1)
{
printf("Illiegal prinitng option! \n 1 - Print \n 0 - Don't print \n");
printUsage(1);
return -1;
}
*num_threads = strtol(argv[3], NULL, 10); //using strtol() to convert string to int
if(*num_threads < 1 || *num_threads > MAXTHREADS)
{
if( *num_threads == -1)
{
printf("Having %d thread is not allowed! \n",*num_threads); //for correct grammar print "thread" if user entered -1
}
else{
printf("Having %d threads is not allowed! \n",*num_threads);
}
return -1;
}
*part_type = strtol(argv[4], NULL, 10); //using strtol() to convert string to int
if(*part_type < 0 || *part_type > 1)
{
printf("Illiegal partitioning option! \n");
printUsage(2);
return -1;
}
*print_per_thread = strtol(argv[5], NULL, 10); //using strtol() to convert string to int
if(*print_per_thread < 0 || *print_per_thread > 1)
{
printf("Illiegal prinitng option! \n 1 - Print \n 0 - Don't print \n");
printUsage(1);
return -1;
}
return 0;
}
}
/* #biref this method prints usage infromation for a specified case
* #arg code ths arguemnts sepcifies which help message should be printed, general usage is argument 0
*/
void printUsage(int code)
{
switch( code )
{
case 0:
printf("Usage: \n");
printf(" ./gol print-option number of threads partitioning-type print-per-thread\n");
printf(" Example: \n");
printf(" ./gol file1.txt 0 8 0 1 \n");
printf(" run with config values read from file1.txt, do not print the board after\n each round, create 8 threads, use row-wise partitioning, print per-thread\npartitioning details");
break;
case 1:
printf("Print options are 1 or 0.\n");
printf(" 1 for print \n 0 for do not print");
break;
case 2:
printf("Partitioning orptions are 1 or 0.\n");
printf(" 0 for row-wise partitioning \n 1 for column-wise partitioning");
break;
default :
break;
}
}
/* #biref this method does one step of the game by first calling checkNeighb() and then choosing apporopriate action
* #param rows - number of rows of the field
* #param columns - number of comuns of the filed
* #param cells - pointer to the 1D array representing our field
* #param num_cells - total number of cells
*/
void evolve(struct ThreadData* args)
{
//////////////
struct ThreadData* the_args= (struct ThreadData*)args;
printf("thread %d started", the_args->id);
fflush(stdout);
/* int i;
int neighb;
int start = the_args->start;
int step = the_args->step;
int num_cells = the_args->cells;
int end;
int total_cells = (the_args->columns * the_args->rows);
if(the_args->id == 0) //print the initial state of the board
{ system("clear");
if(the_args->print == 1)
{
printf("Time step: %d \n\n", TIMESTEP);
printBoard(the_args->rows, the_args->columns , the_args->array, total_cells);
usleep(TIMESTEP);
}
}
///Main loop. Each itteration of the loop is a one round of game.
for(i = 0; i < the_args->iter; i++)
{
//DEBUG
end = (start + (num_cells * step));
for(i = start; i < end ; i+=step) //copy cell state to the array
{
the_args->working_array[i] = the_args->array[i];
}
//barrier
printf("at the barrier, %d!", the_args->id);
fflush(stdout);
*/
pthread_barrier_wait (the_args->enter_barrier);
/*
for(i = start; i < end; i+=step)
{
neighb = checkNeighb(the_args->rows, the_args->columns, the_args->array, num_cells, i); //get number of neighbors
if((neighb < 2 || neighb > 3) && the_args->array[i] == 1)
{
the_args->working_array[i] = 0;
}else if( the_args->array[i] == 0 && neighb == 3)
{
the_args->working_array[i] = 1;
}
}
//barrier
pthread_barrier_wait (the_args->exit_barrier);
for(i = start; i < end; i+=step)
{
the_args->array[i] = the_args->working_array[i];
}
//barrier
pthread_barrier_wait (the_args->print_barrier);
if(the_args->id == 0) //first (0th) thread should print the board
{ system("clear");
printf("at the second print \n");
if(the_args->print == 1)
{
printf("Time step: %d \n\n", TIMESTEP);
printBoard(the_args->rows, the_args->columns , the_args->array, total_cells);
usleep(TIMESTEP);
}
}
}
*/
}
/*
* #biref this read in main parameters from text file
* #param num_rows - pointer to the number of rows of the field
* #param num_columns - pointer to the number of comuns of the filed
* #param num_iter - pointer to the number of iterations
* #param num_cells - pointer to the total number of cells
* #param fp - pointer to the open file
* #return returns 0 on success and -1 on error
*/
int readIn(int *num_rows, int *num_columns, int *num_iter, int *num_cells, FILE *fp)
{
if(fscanf(fp, "%d", num_rows) < 1)
return -1;
if(fscanf(fp, "%d", num_columns) < 1)
return -1;
if(fscanf(fp, "%d", num_iter) < 1)
return -1;
if(fscanf(fp, "%d", num_cells) < 1 )
return -1;
return 0;
}
/* #biref this method creates a 1D array and fills it with the corrct data
* #param rows - number of rows of the field
* #param columns - number of comuns of the filed
* #param - which way should the array be asigned by columns or by rows (used to optimize perfomance in a column partitioning)
* #param num_cells - total number of cells
* #param fp - pointer to the open file
* #return - returns pointer to the 1D array
*/
char* initialize(int rows, int columns, int num_cells, FILE *fp)
{
int k = 0;
int i, j, index;
int length = (rows * columns); //total number of elements in the array (area of the board)
char *cells = calloc((rows * columns), sizeof(char));
if(cells == NULL) //checking malloc
{
perror("Error mallocing");
free(cells);
return NULL;
}
while( k < num_cells )
{
if(fscanf(fp, "%d %d",&i ,&j) == 2)
{
index = ((i * columns) + j);
if(index < length)
{
cells[index] = 1;
}
else{ //in case entries are outside of the board
printf("Invalid entry: %d %d is outside the boundaries", i, j);
}
k++;
}
else{
printf("Error reading i j coordinate pair %d", k);
}
}
return cells;
}
/*
* #biref this method counts number of naeighbors of the cell with a given index in a 1D representation
* #param rows - the number of rows of the field
* #param columns - the number of comuns of the filed
* #param cells - pointer to the 1D arrray
* #param num_cells - the total number of cells
* #param target - index of the cell
* #return returns number of neighbors
*/
int checkNeighb(int rows, int columns, char *cells, int num_cells, int target)
{
int count = 0;
if((target % columns) == 0) //left edge
{
if( target == 0 ) //top left corner
{
if( cells[(rows*columns) -1 ] == 1) //up-left 1
{
count++;
}
if( cells[((rows - 1) * columns)] == 1) //up 2
{
count ++;
}
if( cells[((rows - 1) * columns)+ 1] == 1) //up-right 3
{
count ++;
}
}
else{ //if not top left corner
if( cells[target - 1] == 1) //up-left 1.1
{
count++;
}
if( cells[(target - columns)] == 1) //up 2.1
{
count ++;
}
if( cells[(target - columns) + 1] == 1) //up-right 3.1
{
count++;
}
}
if( target == (rows - 1) * columns) //bottom left corner
{
if( cells[(columns)-1 ] == 1) //down-left 4
{
count++;
}
if( cells[0] == 1) //down 5
{
count ++;
}
if( cells[1] == 1) //up-right 6
{
count ++;
}
}
else{
//if not bottom left corner
if( cells[ target + (2 * columns) - 1 ] == 1) //down-left 4.1
{
count++;
}
if( cells[ target + columns ] == 1) //down 5.1
{
count ++;
}
if( cells[ (target + columns) + 1] == 1) //down-right 6.1
{
count ++;
}
}
if( cells[ target + 1] == 1) //right 7
{
count++;
}
if(cells[(target + columns) - 1] == 1) //left 8
{
count++;
}
}
else if(((target +1) % columns) == 0) //right edge
{
if( target == (columns - 1) ) //top right corner
{
if( cells[(rows * columns) - 2 ] == 1) //up-left 1
{
count++;
}
if( cells[(rows * columns) - 1] == 1) //up 2
{
count ++;
}
if( cells[((rows-1) * columns)] == 1) //up-right 3
{
count ++;
}
}
else{ //if not top right corner
if( cells[(target - columns) - 1] == 1) //up-left 1.1
{
count++;
}
if( cells[(target - columns)] == 1) //up 2.1
{
count ++;
}
if( cells[(target - (2 * columns)) + 1] == 1) //up-right 3.1
{
count++;
}
}
if( target == ((rows * columns) -1)) //bottom right corner
{
if( cells[columns - 2 ] == 1) //down-left 4
{
count++;
}
if( cells[ columns - 1 ] == 1) //down 5
{
count ++;
}
if( cells[0] == 1) //down-right 6
{
count ++;
}
}
else{
//if not bottom right corner
if( cells[ (target + columns) - 1 ] == 1) //down-left 4.1
{
count++;
}
if( cells[ target + columns ] == 1) //down 5.1
{
count ++;
}
if( cells[ target + 1 ] == 1) //down-right 6.1
{
count ++;
}
}
if( cells[(target - columns) + 1] == 1) //right 7
{
count++;
}
if(cells[target - 1 ] == 1) //left 8
{
count++;
}
}
else if(target > ((rows-1)*columns)) //bottom edge not corner
{
if(cells[target - 1] == 1) //left 1
{
count++;
}
if(cells[target + 1] == 1) //right 2
{
count++;
}
if(cells[target - columns] == 1) //up 3
{
count++;
}
if(cells[(target - columns) - 1] == 1) //up -left 4
{
count++;
}
if(cells[(target - columns) + 1] == 1) //up -right 5
{
count++;
}
if(cells[target % columns] == 1) //down 5
{
count++;
}
if(cells[(target % columns) + 1] == 1) //down -right 7
{
count++;
}
if(cells[(target % columns) + -1] == 1) //down -left 8
{
count++;
}
}
else if(target < columns) //top edge not corners
{
if(cells[target - 1] == 1) //left 1
{
count++;
}
if(cells[target + 1] == 1) //right 2
{
count++;
}
if(cells[target + ((rows-1) * columns)] == 1) //up 3
{
count++;
}
if(cells[(target + ((rows-1) * columns)) - 1] == 1) //up -left 4
{
count++;
}
if(cells[(target + ((rows-1) * columns)) + 1] == 1) //up - right 5
{
count++;
}
if(cells[target + columns] == 1) //down 5
{
count++;
}
if(cells[(target + columns) + 1] == 1) //down -right 7
{
count++;
}
if(cells[(target + columns) + -1] == 1) //down -left 8
{
count++;
}
}
else{ //middle
if(cells[target - 1] == 1) //left 1
{
count++;
}
if(cells[target + 1] == 1) //right 2
{
count++;
}
if(cells[target - columns] == 1) //up 3
{
count++;
}
if(cells[(target - columns) - 1] == 1) //up -left 4
{
count++;
}
if(cells[(target - columns) + 1] == 1) //up -right 5
{
count++;
}
if(cells[target + columns] == 1) //down 5
{
count++;
}
if(cells[(target + columns) + 1] == 1) //down -right 7
{
count++;
}
if(cells[(target + columns) + -1] == 1) //down -left 8
{
count++;
}
}
return count;
}
// #biref this method prints out the board
void printBoard(int rows, int columns, char *cells, int num_cells)
{
int i, j;
for( i = 0; i < rows; i++)
{
for( j=0; j < columns; j++)
{
if( cells[ (i * columns) + j ] == 1)
{
printf("# "); //if 1
}
else{
printf("- "); //if 0
}
}
printf("\n");
}
printf("\n");
return;
}
The barrier
pthread_barrier_t enter_barrier; //this barrier synchornizes threads to wait
is a local object in the function initializeThreads(). The lifetime of this object ends when initializeThreads() finishes, which is before the threads start and call pthread_barrier_wait (the_args->enter_barrier). It's no wonder that waiting on a non-existent barrier doesn't work.
Consider the following functions
void alloco(int **ppa)
{
int i;
printf("inside alloco %d\n",ppa); /*this function allocates and fills 20 * sizeof(int) bytes */
*ppa = (int *)malloc(20 * sizeof(int));
/*fill all 20 * sizeof(int) bytes */
}
int main()
{
int *app = NULL;
int i;
printf("inside main\n");
alloco(&app);
for(i=0;i<20;i++) /*ISSUE::how will i know to traverse only 20 indexes?*/
printf("app[%d] = %d \n", i, app[i]);
return(0);
}
Basically how will main() come to know number of bytes to traverse i.e memory allocated by alloco() function. Is there any delimiter like NULL in character arrays?
That is not possible, you need to keep that value somewhere, for example you could do this,
void alloco(int **ppa, int count)
{
int i;
printf("inside alloco %d\n",ppa);
*ppa = malloc(count * sizeof(int));
if (*ppa == NULL)
return;
for (i = 0 ; i < count ; ++i)
/* fill it here. */
}
int main()
{
int *app;
int i;
int count;
count = 20;
app = NULL;
printf("Inside main\n");
alloco(&app, count);
if (app == NULL)
return -1;
for (i = 0 ; i < count ; i++)
printf("app[%d] = %d \n", i, app[i]);
/* done with `app' */
free(app);
return 0;
}
Many other combinations could work, for example
int alloco(int **ppa)
{
int i;
printf("inside alloco %d\n",ppa);
*ppa = malloc(20 * sizeof(int));
if (*ppa == NULL)
return;
for (i = 0 ; i < count ; ++i)
/* fill it here. */
return 20;
}
int main()
{
int *app;
int i;
int count;
printf("Inside main\n");
app = NULL;
count = alloco(&app);
if (app == NULL)
return -1;
for (i = 0 ; i < count ; i++)
printf("app[%d] = %d \n", i, app[i]);
/* done with `app' */
free(app);
return 0;
}
But I personally don't like this because if there is going to be a fixed number of integers it's not a good idea to use malloc() just,
int main()
{
int app[20];
int i;
printf("Inside main\n");
for (i = 0 ; i < sizeof(app) / sizeof(app[0]) ; i++)
printf("app[%d] = %d \n", i, app[i]);
return 0;
}
Is there any delimiter like NULL in character arrays?
If you define one, yes.
This however only is possible if your use case does not need all possible integer values.
If for example you would only need positive values including 0 you can define the value of -1 to be the "End-of-Array" marker.
You then would allocate one more element to the array then you need and assign -1 to this additional very last array element.
Example:
#include <stdlib.h> /* for malloc */
#include <errno.h> /* for errno */
#define EOA (-1)
int array_allocate(int ** ppi)
{
int result = 0;
if (NULL = ppi)
{
result = -1;
errno = EINVAL;
}
else
{
size_t number_of_elements = ...; /* Assign some positive value here. */
*ppi = malloc((number_of_elements + 1) * sizeof ** ppi);
if (NULL == *ppi)
{
result = -1;
}
else
{
(*ppi)[number_of_elements] = EOA;
}
}
return result;
}
ssize_t array_number_of_elements(int * pi)
{
int result = 0;
if (NULL == pi)
{
result = -1;
errno = EINVAL;
}
else
{
int * pi_tmp = pi;
while (EOA != *pi_tmp)
{
++pi_tmp;
}
result = pi_tmp - pi;
}
return result;
}
Use it like this:
#include <stdlib.h> /* for size_t and ssize_t */
#include <stdio.h> /* for printf and perror */
int array_allocate(int **);
ssize_t array_number_of_elements(int *);
int main(void)
{
int result = EXIT_SUCCESS;
int * pi = NULL;
if (-1 == array_allocate(&pi))
{
result = EXIT_FAILURE;
perror("array_allocate() failed");
}
else
{
ssize_t result_number_of_elements = array_number_of_elements(pi);
if (-1 == result_number_of_elements)
{
result = EXIT_FAILURE;
perror("array_number_of_elements() failed");
}
else
{
size_t number_of_elements = result_number_of_elements;
printf("The number of array's elements is %zu.\n",
number_of_elements);
}
}
free(pi); /* Clean up. */
return result;
}
It takes becoming a 3-Star Programmer
You can easily allocate some fixed number of elements (less than the maximum) in an function without passing the number of elements between the caller function and the callee. However, it takes creating an array of pointers to pointers to type How/Why? Essentially, you are treating your array as a null-terminated string, initially allocating all pointers to type within the array to NULL and only allocating space for them as needed. (allocating with calloc makes this a snap) When the array is used back in the caller, it allows iterating over all filled values until your reach the first null-pointer.
Now granted,
simply passing a pointer to size as an additional argument to your
function makes much more sense [1]
and eliminates the need for a triple-star rating, but for the purpose of example, enjoy being a 3-Star Programmer for a while:
#include <stdio.h>
#include <stdlib.h>
#define INITSZ 21
void alloco (int ***ppa)
{
printf("inside %s\n", __func__);
int i = 0;
/* allocate 21 pointers-to-int */
if (!(*ppa = calloc (INITSZ, sizeof **ppa))) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
/* allocate/fill 20 values (or anything less than 21) */
for (i = 0; i < INITSZ - 1; i++) {
if (!((*ppa)[i] = calloc (1, sizeof ***ppa))) {
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
*((*ppa)[i]) = i * 2;
}
}
int main()
{
int **app = NULL;
int i = 0;
printf ("inside main\n");
alloco (&app);
/*ISSUE::how will i know to traverse only 20 indexes?*/
while (app[i]) {
printf("app[%d] = %d \n", i, *(app[i]));
i++;
}
return(0);
}
Use/Output
$ ./bin/alloc_array+1
inside main
inside alloco
app[0] = 0
app[1] = 2
app[2] = 4
app[3] = 6
app[4] = 8
app[5] = 10
app[6] = 12
app[7] = 14
app[8] = 16
app[9] = 18
app[10] = 20
app[11] = 22
app[12] = 24
app[13] = 26
app[14] = 28
app[15] = 30
app[16] = 32
app[17] = 34
app[18] = 36
app[19] = 38
footnote [1]: emphasis added to the quote for clarity that this solution was intended to show what was possible, not what was most efficient or most practical.
I know the forum has many questions about heap etc. but nothing helped me this much (except for the understanding of why it doesn't work).
I have a huge quantity of data and of course the heap can't follow. The data I need to store are only integers. Malloc starts returning null quite early.
4 arrays of size: (allocation by malloc)
875715
875715
875715
5105043 cells (but it's a 2D array)
Here are my questions:
1) To know the quantity of memory needed, is it:
875715 * 3 * 4 + 5105043 * 4 = 62454492 ? (because integer is 4)
Does it mean around 62 MB? (Sorry if it seems dumb)
2) How can we know the size of the heap available? Is there a way to increase it?
3) I have 3 arrays of the same size, is there an advantage of merging them into one 2D array?
For example, array[875715][3] instead of 3 different arrays (of course, by using malloc)
I use Window seven, 64 bit, 8GB of RAM.
EDIT: Here is a typical allocation I do for the 1D array and for the beginning of the 2D array (first level):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define FILE_NAME "SCC.txt"
#define ARRAY_SIZE 875714
void getGgraph(int mode,int **graph,int *sizeGraph);
int sizeOfArray(int *array);
void getGraphSize(int mode,int *arr);
void runThroughGraph(int node,int **graph,int *exploredNode,int *magicalPath,int *sizeGraph);
void getMagicalPath(int *magicalPath,int **graph,int *sizeGraph);
void main()
{
int i, *magicalPath,*sizeGraph, **graph;
/* ------------- creation of the array sizeGraph ------------------ */ // contain the size of each level to initiate the array
if ((sizeGraph =(int*) malloc((ARRAY_SIZE + 1) * sizeof(sizeGraph[0]))) == NULL) {
printf("malloc of sizeGraph error\n");
return;
}
memset(sizeGraph, 0, (ARRAY_SIZE + 1) * sizeof(sizeGraph[0]));
/* ------------- create reverse G graph, this will be a 2D array ------------------ */
if ((graph =(int**) malloc((ARRAY_SIZE + 1) * sizeof(*graph))) == NULL) {
printf("malloc of graph error\n");
return;
}
getGgraph(1,graph,sizeGraph);
// [..... Some more code .....]
// end of main()
}
void getGgraph(int mode,int **graph,int *sizeGraph) {
char int_string[40];
char stringToAdd[10];
FILE *integerFile = NULL;
int i = 0, j = 0, n = 0,stCurrentInt, tail,head,*temp;
getGraphSize(mode,sizeGraph);
for (i = 0; i < (ARRAY_SIZE + 1); i++) {
if ((graph[i] =(int*) malloc((ARRAY_SIZE + 1) * sizeof(graph[i][0]))) == NULL) {
// THIS IS WHERE IT STOPS (i = 594)
printf("Malloc of graph[%d] error\n",i);
return;
}
}
if ((temp =(int*) malloc((ARRAY_SIZE + 1) * sizeof(temp[0]))) == NULL) {
printf("malloc of temp in getGgraph function error\n");
return;
}
memset(temp, 0, (ARRAY_SIZE + 1) * sizeof(temp[0]));
if ((integerFile = fopen(FILE_NAME, "r")) != NULL) {
while (fgets(int_string,40, integerFile) != NULL) {
n = 0, i = 0, stCurrentInt = 0,head = 0; // initialisation
while (int_string[n] != NULL) {
if (int_string[n] == ' ') {
for (j = stCurrentInt; j < n; j++) {
stringToAdd[j - stCurrentInt] = int_string[j];
}
if (stCurrentInt == 0) // first integer is the index
tail = (int) atoi(stringToAdd);
else {
head = atoi(stringToAdd);
if (mode == 0) {
graph[tail][temp[tail]] = head;
temp[tail]++;
}
else if (mode == 1) {
graph[head][temp[head]] = tail;
temp[head]++;
}
}
for (j = 0; j < 10; j++) { // empty the string for next iteration
stringToAdd[j] = NULL;
}
stCurrentInt = n + 1;
}
n++;
}
}
free(temp);
fclose(integerFile);
}
else {
printf("\n File missing in getGgraph.\n");
return;
}
}
void getGraphSize(int mode,int *arr) {
char int_string[40],stringToAdd[10];
FILE *integerFile = NULL;
int i = 0, j = 0, n = 0,stCurrentInt,tail,head;
if ((integerFile = fopen(FILE_NAME, "r")) != NULL) {
while (fgets(int_string,40, integerFile) != NULL) {
n = 0, i = 0, stCurrentInt = 0,head = 0; // initialisation
while (int_string[n] != NULL) {
if (int_string[n] == ' ') {
for (j = stCurrentInt; j < n; j++) {
stringToAdd[j - stCurrentInt] = int_string[j];
}
if (stCurrentInt == 0) // first integer is the index
tail = (int) atoi(stringToAdd);
else
head = atoi(stringToAdd);
for (j = 0; j < 10; j++) { // empty the string for next iteration
stringToAdd[j] = NULL;
}
stCurrentInt = n + 1;
}
n++;
}
if (mode == 0 && head != 0)
arr[tail]++;
else if (mode == 1 && head != 0)
arr[head]++;
}
}
else {
printf("\n File missing in getGraphSize.\n");
return;
}
}
EDIT2: My program actually works like a charm for smaller inputs.
[..... Some more code .....]: this is after the issue. The failing malloc is inside getGraph, so I don't think the rest is relevant. I free() the arrays later on in the program.
without pulling out a calculator, and without your code, your analysis looks right.
The HEAP will grow as needed, constrained only by OS process limits.. By default, under windows, you get no more that 2Gig. Here's a more specific link.
no significant advantage.
In your case you'd be better served by adjusting your memory allocation algorithms to allocate what you need and no more.