I am getting the error variable sized object may not be initialized and I don't understand why.
Could someone show me how to fix this line?
int arr[size] = (int *)(augs->one);
Here is my code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <pthread.h>
#include <assert.h>
int count = 0;
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct structure {
int two;
int *one;
};
void *sort(void *augments) {
struct structure *augs = (struct structure*)augments;
int i = 0;
int size = 1;
size = augs->two;
int arr[size] = (int *)(augs->one);
//int *arr = (int *)data;
//printf("sizeof:%d\n", sizeof(arr));
qsort(arr, size, sizeof(int), cmpfunc);
printf("finaloutput:\n");
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return NULL;
}
int main(int argc, char *argv[]) {
FILE *myFile;
myFile = fopen("data.txt", "r");
// number of lines in file
char charicter;
for (charicter = getc(myFile); charicter != EOF; charicter = getc(myFile)) {
if (charicter == '\n') {
count++;
}
}
printf("count is %d\n", count);
int numberArray[count];
int i = 0;
if ((myFile = fopen("data.txt", "r"))) {
while ((fscanf(myFile, "%d", &numberArray[i]) != EOF)) {
++i;
}
fclose(myFile);
}
assert(argv[1] != NULL);
int num = atoi(argv[1]); //num equals number input
int arrayarray[num - 1][(count / num)];
int idx;
for (i = 0; i < (count); i++) {
printf("numberarray[%d]= %d\n", i, numberArray[i] /*[0],numberArray[i][1]*/);
}
for (i = 1; i < num + 1; i++) {
for (idx = 0; idx < (count / num); idx++) {
arrayarray[i - 1][idx] = numberArray[i * idx];
}
}
///*
for (i = 0; i < ((count / num)); i++) {
printf("arrayarray[0]=%d\n", arrayarray[0][i]);
}
//*/
int lastarray[((count / num) + (count % num))];
for (idx = 0; idx < ((count / num) + (count % num)); idx++) {
lastarray[idx] = numberArray[idx + ((count / num) * (num - 1))];
}
for (i = 0; i < ((((count / num) + (count % num)))); i++) {
printf("lastaray[%d]=%d\n", i, lastarray[i]);
}
//*******************
pthread_t thread_id_arr[num];
for (i = 0; i < num; i++) {
pthread_t tid;
struct structure *augs;
if (i != (num - 1)) {
augs = malloc(sizeof(struct structure) + sizeof(int) + sizeof(int) * num);
(*augs).one = arrayarray[i];
(*augs).two = (count / num);
pthread_create(&tid, NULL, sort, augs);
} else {
(*augs).one = lastarray;
(*augs).two = (count / num) + (count % num);
pthread_create(&tid, NULL, sort, augs);
//pthread_create(&tid, NULL, sort, (void*)lastarray);
}
thread_id_arr[i] = tid;
}
for (i = 0; i < num; i++) {
pthread_join(thread_id_arr[i], NULL);
}
return 0;
}
As others pointed out, you can't initialize a Variable Length Array with a pointer, like you are doing. However, you don't actually need a VLA at all. Use this instead :
int *arr = augs -> one;
You want to act directly on the array that is passed into the thread, not make a copy of it.
That being said, I see another problem. In the loop that spawns the sorting threads, you are not allocating a new args on the last loop iteration, it reuses the allocated args from the previous iteration, which can cause disaster for the 2nd-to-last thread. You need to move the malloc() call above the if.
Also, the malloc() is allocating more memory than your threads actually use. You only need to allocate enough memory for just the struct by itself, not for any integers following the struct.
Also, when each thread is done using the allocated args that it is given, it needs to free() the args to avoid leaking memory.
Related
It's been a few hours and i can't seem to understand the issue. Build this program to count from 1 - 10. The goal of this program is to use multithreading and dynamically split the array depending on how many threads it requested. Problem is the first 2 threads are being skipped and the last thread is doing most of th e process. I suspect it's the for loop that creates the threads.
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
typedef struct
{
int *array;
int batch;
int start;
int end;
} Parameter;
void *method(void *p)
{
Parameter *param = (Parameter *)p;
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
}
}
int main(int argc, char **argv)
{
// Getting the user input
int array_length = atoi(argv[1]);
int batches = atoi(argv[2]);
printf("User specified Array:%d\tBatch:%d\n", array_length, batches);
// Creating an array
int *array = (int *)calloc(array_length, sizeof(int));
// Fill it up with some data
for (int i = 0; i < array_length; i++)
{
array[i] = i;
}
// Determine the Batches
int batch_size = array_length / batches;
int remainder = array_length % batches;
printf("%d\n", batch_size);
printf("%d\n", remainder);
int start = 0;
int end = 0;
int index =0;
// List of parameters
Parameter *param = (Parameter *)calloc(batches, sizeof(Parameter));
pthread_t *threads = (pthread_t *)calloc(batches, sizeof(pthread_t));
// Loop through each batch.
for (int i = 0; i < batches; i++)
{
printf("\n\nBatch number -> %d\n", i);
end = start + batch_size;
if (remainder > 0)
{
remainder --;
end ++;
}
// Fill the parameters
param[i].array = array;
param[i].end = end;
param[i].start = start;
param[i].batch = i;
// Call the thread.
pthread_create(threads + index, NULL, method, (void *)¶m[i]);
index++;
start = end;
}
for (int i = 0; i < batches; i++)
{
pthread_join(threads[i], NULL);
}
free(param);
free(threads);
free(array);
return 0;
}
Been playing with the index of the for loop(line 57) as i'm certain it's the cause of the issue. been getting some results but the main problem still persisted.
Code Works as intended. I'm a dumbas who didn't put the printf in the void function. like so:
void *method(void *p) {
Parameter *param = (Parameter *)p;
printf("\n\nBatch number -> %d\n", param->batch); //<-- moved from main method
for (int i = param->start; i < param->end; i++)
{
printf("Start:%d\tEnd:%d\tIndex:%d\tValue:%d\n", param->start, param->end, i,param->array[i]);
} }
Thanks for pointing it out that the program works
I can't understand why if I use
while (tab[i+1] == 0)
{
i+=1;
}
My program hangs
but if I use
while (tab[++i] == 0);
It executes as it should. What am I missing?
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <limits.h>
#define SIZE 100
typedef struct
{
unsigned int prime;
unsigned int size;
unsigned int *tab;
} shared_data;
void *sieve(void *);
sem_t mutex;
int main()
{
pthread_t tid;
unsigned int tab[SIZE];
sem_init(&mutex, 0, 0);
for (unsigned int i = 0; i < SIZE; i++)
{
tab[i] = i;
}
unsigned int i = 2; //index startowy
shared_data shared = {i, SIZE, tab};
while (i < SIZE)
{
shared.prime = tab[i];
pthread_create(&tid, NULL, sieve, &shared);
sem_wait(&mutex);
while (tab[++i] == 0);
}
pthread_join(tid, NULL); // czekaj az ostatni watek zakonczy dzialanie
sem_destroy(&mutex);
printf("Liczby pierwsze:\n");
for (unsigned int i = 0; i < SIZE; i++)
if (tab[i]) //pomin 0 przy wyswietlaniu
printf("%d | ", tab[i]);
printf("\n");
return 0;
}
void *sieve(void *arg_p)
{
shared_data arg = *(shared_data *)arg_p;
shared_data io = arg;
int unlock_thread = 1;
for (unsigned int i = io.prime + 1; i < io.size; i++)
{
if (io.tab[i] % io.prime == 0)
io.tab[i] = 0;
else if (unlock_thread)
{
sem_post(&mutex);
unlock_thread = 0;
}
}
if (unlock_thread)
sem_post(&mutex);
return NULL;
}
while (tab[i+1] == 0)
{
i+=1;
}
Checks the next element of tab and doesn't change i when it is zero.
This means i won't change to the value where tab[i] becomes zero.
In the other hand,
while (tab[++i] == 0);
First go to the next element of tab and therefore i can be changed to make tab[i] zero.
To separate access to tab and update of i, you can do like this:
do {
i+=1;
} while (tab[i] == 0);
Also note that you must not access (no read nor write) out-of-range elements of arrays. The array tab has only SIZE elements, so the available indices are only 0 to SIZE-1. This means you must not read tab[SIZE]. You should add range check to the loops like this:
while (++i < SIZE && tab[i] == 0);
do {
i+=1;
} while (i < SIZE && tab[i] == 0);
I tried to create dynamically growing array I did with realloc. I have example below but I do not understand how this code works by using malloc.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int cnt = 0;
double *numbers = NULL;
double newnum;
while (scanf("%lf", &newnum) == 1 && newnum != -1) {
double *newarr = (double*) malloc(sizeof(double) * (cnt+1));
for (int i = 0; i < cnt; ++i)
newarr[i] = numbers[i];
free(numbers);
numbers = newarr;
numbers[cnt] = newarr;
++cnt;
}
for (int i = cnt-1; i >= 0; --i) {
printf("%f\n", numbers[i]);
}
free(numbers);
return 0;
}
realloc() is the same as malloc(), memcpy(), free() all in one function (*).
The loop in your code effectively replaces memcpy()
// memcpy(newarr, numbers, cnt * sizeof *newarr);
for (int i = 0; i < cnt; ++i)
newarr[i] = numbers[i];
(*) realloc() may be smart enough to avoid the memcpy() and free() and reuse memory.
How can I implement this in my code?
It helps to encapsulate the pointer and the total/used elements in a structure.
#include <stdio.h>
#include <stdlib.h>
struct DynArray {
double *data;
size_t m; // total
size_t n; // used
};
void growarray(struct DynArray *x) {
size_t newsize = x->m * 13 / 8 + 1; // use phi aproximation 13/8
double *newarr = realloc(x->data, newsize * sizeof *x->data);
if (!newarr) exit(EXIT_FAILURE);
fprintf(stderr, "INFO: realloc'ed with %d elements.\n", (int)newsize);
x->data = newarr;
x->m = newsize;
}
int main(void) {
struct DynArray numbers = { 0 };
double newnum;
while (scanf("%lf", &newnum) == 1 && newnum != -1) {
if (numbers.n == numbers.m) growarray(&numbers);
numbers.data[numbers.n] = newnum;
numbers.n++;
}
for (int i = numbers.n - 1; i >= 0; --i) {
printf("%f\n", numbers.data[i]);
}
free(numbers.data);
return 0;
}
See code running on ideone or previous version without growarray function or previous version with cnt
All the solutions I have seen online has calloc() function used twice, is it possible to do with only using it once?
The below code is not printing the correct array elements
int **ptr;
//To allocate the memory
ptr=(int **)calloc(n,sizeof(int)*m);
printf("\nEnter the elments: ");
//To access the memory
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
scanf("%d",ptr[i][j]);
}
}
Since C99 you can use pointers to VLAs (Variable Length Arrays):
int n, m;
scanf("%d %d", &n, &m);
int (*ptr)[m] = malloc(sizeof(int [n][m]));
for (i = 0; i < n; i++)
{
for (j = 0; j < m; j++)
{
scanf("%d", &ptr[i][j]); // Notice the address of operator (&) for scanf
}
}
free(ptr); // Call free only once
If it's just about minimising the number of calls to memory allocation functions you can created such a jagged array like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t n, size_t m)
{
int ** result = NULL;
size_t t = 0;
t += n * sizeof *result;
t += n*m * sizeof **result;
result = calloc(1, t);
if (NULL != result)
{
for (size_t i = 0; i < n; ++i)
{
result[i] = ((int*) (result + n)) + i*m;
}
}
return result;
}
Use it like this:
#include <stdlib.h>
#include <stdio.h>
int ** alloc_jagged_2d_array_of_int(size_t, size_t);
int main(void)
{
int result = EXIT_SUCCESS;
int ** p = alloc_jagged_2d_array_of_int(2, 3);
if (NULL == p)
{
perror("alloc_jagged_2d_array_of_int() failed");
result = EXIT_FAILURE;
}
else
{
for (size_t i = 0; i < 2; ++i)
{
for (size_t j = 0; j < 3; ++j)
{
p[i][j] = (int) (i*j);
}
}
}
/* Clean up. */
free(p);
return result;
}
I am having trouble with assigning a return value of a function in heap part of the program. When I tried it in main, it gives an error "Segmentation fault". I believe it is because of the size of my array, which is the return value that I mentioned earlier because when I make my max_size smaller, the code works correctly (I think up to 45000). When I call the function in main, it uses the memory of stack, which is much smaller than memory of heap. Therefore I tried to call the function in heap and make the assignment in there but the compiler gave an error
deneme.c:6:15: error: initializer element is not constant
int *primes = listPrimes(1000000, &size);
After that I did some research and found out that stack is 8 MB memory, which is around 8000000 bytes. Then I estimated my array size as using the prime number theorem (up to 1000000, there are approximately 200000 primes) and sizeof(int) = 4 bit value so it gives 100000 bytes, which is much less than 8 MB. Therefore I have two questions in mind:
1. Why the compiler gives segmentation fault error although my array size is not too large?
2. How can I make the assigment in heap instead of main in order to avoid this problem?
Here is my code:
#include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int *listPrimes(int max_size, int *size) {
*size = 1;
int *result = malloc(*size * sizeof(int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc(max_size*sizeof(int));
for (i = 0; i < max_size; i++) {
nums[i] = i;
}
result[0] = 2;
int j = 2;
while (j < max_size) {
int k = j;
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
if (j == 2) {
j++;
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
else {
j += 2;
if (nums[j] != 0) {
*size = *size + 1;
result = realloc(result, *size * sizeof(int));
result[index++] = nums[j];
}
}
}
return result;
}
and main function:
#include <stdio.h>
#include <stdlib.h>
#include "mathlib.h"
int size = 0;
int *primes = listPrimes(1000000, &size);
int main() {
printf("size = %d\n", size);
for (int i = 0; i < size; i++) {
printf("%d th prime is %d\n", i+1, primes[i]);
}
free(primes);
return 0;
}
Use unsigned int for j, k and max_size in listPrimes and it works properly . Below is the tested code:
// #include "mathlib.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int size = 0;
int *
listPrimes (unsigned int max_size, int *size)
{
*size = 1;
int *result = malloc (*size * sizeof (int));
int i;
int index = 1;
// Finding the list of primes using a sieve algorithm:
int *nums = malloc (max_size * sizeof (int));
for (i = 0; i < max_size; i++)
{
nums[i] = i;
}
result[0] = 2;
unsigned int j = 2;
while (j < max_size)
{
unsigned int k = j;
while (j * k <max_size)
{
nums[j * k] = 0;
k++;
}
if (j == 2)
{
j++;
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
else
{
j += 2;
if (nums[j] != 0)
{
*size = *size + 1;
result = realloc (result, *size * sizeof (int));
result[index++] = nums[j];
}
}
}
free(nums);
return result;
}
int
main ()
{
int *primes = listPrimes (1000000, &size);
printf ("size = %d\n", size);
for (int i = 0; i < size; i++)
{
printf ("%d th prime is %d\n", i + 1, primes[i]);
}
free (primes);
return 0;
}
nums is allocated to have max_size elements, so the index of its last element is max-size-1.
This loop:
while (j*k <= max_size) {
nums[j*k] = 0;
k++;
}
may access an element with index j*k that equals max_size, thus writing beyond the end of the array. The loop should be limited to j*k < max_size.
Regarding your second question, the size of the result array is determined while finding the primes and is not readily calculable in advance, so it cannot easily be allocated prior to calling listPrimes. It could be done by evaluating the prime-counting function, but that is likely more than you want to do for this project.