I'm trying out Multi-threading in C for the first time, and I seem to be doing something wrong which I hope you could help me with. Here is my code:
#include "stdafx.h"
#define MAX_THREADS 2
int a[100000];
int b[200000];
void startThreads();
DWORD WINAPI populateArrayA(LPVOID data)
{
int i;
int* pA = (int*)data;
for(i = 0; i < sizeof(a) / sizeof(int); i++)
{
*pA = i;
pA++;
}
return 0;
}
DWORD WINAPI populateArrayB(LPVOID data)
{
int i;
int* pB = (int*)data;
for(i = 0; i < sizeof(b) / sizeof(int); i++)
{
*pB = i;
pB++;
}
return 0;
}
void startThreads()
{
HANDLE threads[MAX_THREADS];
DWORD threadIDs[MAX_THREADS];
threads[0] = CreateThread(NULL,0,populateArrayA,a,0,&threadIDs[0]);
threads[1] = CreateThread(NULL,0,populateArrayB,b,0,&threadIDs[1]);
if(threads[0] && threads[1])
{
printf("Threads Created. (IDs %d and %d)",threadIDs[0],threadIDs[1]);
}
WaitForMultipleObjects(MAX_THREADS,threads,true,0);
}
int main(int argc, char* argv[])
{
int i;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
startThreads();
return 0;
}
In this code, Array "b" seems to populate fine, however Array "a" does not. Sorry if the answer is something stupid!
EDIT: I just tried again, and both arrays are all '0's. Not quite sure what's going on. I'm using Visual Studio in case it's a debugging issue or something.
Cheers.
The last parameter of WaitForMultipleObjects must be INFINITE, not 0.
With 0, the function returns immediatly.
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 have a problem. I have to divide array into dynamic array and return pointer with parameter.
When I try to run this code, I get (interrupted by signal 11: SIGSEGV) this message. I think it is something with my pointers. But I don't even get any warnings, I don't know where to look else.
#include <stdio.h>
#include <stdlib.h>
int splitData(int data[], int size, int splitPlace, int **firstArray);
int main() {
int data[6] = {1, 2, 3, 4, 5, 6};
int size = 6;
int *ptr = NULL;
int n = splitData(data, size, 3, &ptr);
printf("%d", n);
for(int i = 0; i < 3; ++i)
{
printf("[%d]", ptr[i]);
}
return 0;
}
int splitData(int data[], int size, int splitPlace, int **firstArray)
{
*firstArray = (int *)malloc(splitPlace * sizeof(int));
for(int i = 0; i < splitPlace; ++i)
{
*firstArray[i] = data[i];
}
return 0;
}
You have the precedence wrong with *firstArray[i]. You need (*firstArray)[i].
Clearer might be to allocate
int *new_array = malloc(...);
*firstArray = new_array.
Then use new_array in your loop body.
I am trying to make a program that first creates an array in another function, returns it and then calls another function that shuffles the contents of the array and returns it. However I am struggling to do this in C since I do not quite understand the array pointer system that has to be used here.
So far my code doesnt return the values 1-20 from makeArray() but instead returns an array full of 0s and I have a feeling it has to do with the c's array pointer system.
Any help would greatly be appreciated! Thank you in advance
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int arrShuffle();
int arrShuffle(int * arr) {
int arr[21];
// shuffle array
for(int j=0; j<20; j++) {
int randInd = (rand() % 20) + 1;
int temp = arr[j];
arr[j] = arr[randInd];
arr[randInd] = temp;
}
return arr;
}
int makeArray() {
int arr[21];
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
void main() {
int *orgArr;
int *modArr;
srand(time(NULL));
orgArr = makeArray();
for(int i=0; i < 20; i++) {
printf("OrgArr: %d\n", orgArr);
}
modArr = arrShuffle(orgArr);
}
You cannot use variables with automatic storage (aka local ones). You must allocate the array so the memory remains valid after the function ends:
int* makeArray() {
int *arr = calloc(21, sizeof *a);
// make array of 1-20
for(int i=0; i < 20; i++) {
arr[i] = i + 1;
}
return arr;
}
Remember to release the array when it is no longer used:
int main() {
int *orgArr;
...
orgArr = makeArray();
...
free(orgArr);
}
As tstanisl pointed out in their answer, a possible solution is to use dynamic memory allocation. My answer, instead, will give you yet another solution: using an array passed by the caller.
NOTE: both solutions are valid and their usefulness depends on the specific needs of your program. There's no "right" universal solution.
void makeArray(int arr[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
arr[i] = (int) (i + 1);
}
}
void cloneAndModifyArray(const int orig[], int new[], size_t len) {
for (size_t i = 0; i < len; i += 1) {
new[i] = orig[i] * 2; // or some other modification
}
}
And you use it like this:
#define ARR_LEN (100)
int main(void) {
int arr[ARR_LEN];
makeArray(arr, ARR_LEN);
int modified_arr[ARR_LEN];
cloneAndModifyArray(arr, modified_arr, ARR_LEN);
return 0;
}
I have some issues with my code. I need to pass an int array to a thread witch will calculate the ^2 of every int of the array.
My code:
#include <pthread.h> //etc.
#define SIZE 1024
static void * function_thread(void *arg){
int *loc = (int *)arg;
// i tried also int loc[SIZE] = (int *)arg; but won' compile ion' t know why
for (int i = 0; i < SIZE; i++) {
loc[i] = loc[i] * loc[i];
// tried also loc[i] = (*(int *)arg) * (*(int *)arg);
printf("loc[%d]^2 = %d\n",i, loc[i]);
}
return (void *)loc;
}
int main(int argc, char const *argv[]) {
int x[SIZE];
void (*res[SIZE]);
int y[SIZE];
for (int i = 0; i < SIZE; i++) {
x[i] = i;
}
pthread_t thread_1;
pthread_create(&thread_1,NULL,function_thread,x);
pthread_join(thread_1, &res);
for(int i = 0; i < SIZE; i++){
y[i] = res[i];
}
}
So i have few questions:
There is something wrong already in the thread function? is giving me loc[i] = 0 for each i.What's the problem?
why the initialization of *int loc[SIZE] = (int * )arg; doesnìt work?
I have seen that
int x;
int * result;
...
pthread_join(someThread, &result);
x = result + result;
this works.But why? isn't x and result types different?
Thanks you in advice and wish you a good day!
I find this hard to explain but I'll do my best. I am passing an array to a function. I want to be able to grab the pointer of the array in the function and put the values of the array back into an array in the function.
If that doesn't make sense maybe this code will give you an idea of what I'm trying to attempt.
#define LENGTH 3
void FIR(short *filter) {
short temp[LENGTH] = {*filter, *(filter+1), *(filter+2)};
}
int main() {
short filter[LENGTH] = {1,2,5};
FIR(filter);
}
This code works but is quite ridiculous if the filter length is long. How could I do this for any length of filter array? Keep in my mind, I'm trying to preserve efficiency.
Use a loop, *(filter+x) is equivalent to filter[x]
#include <stdio.h>
#define LENGTH 3
void FIR(short *filter) {
short temp[LENGTH];
int i;
for(i = 0; i < LENGTH; ++i){
temp[i] = filter[i];
}
}
int main() {
short filter[LENGTH] = {1,2,5};
FIR(filter);
int i;
for(i = 0; i < LENGTH; ++i){
printf("%d ", filter[i]);
}
}
You can make your code look good by using loops or just use memcpy() to copy the whole array.
void FIR(short *filter)
{
short temp[LENGTH];
int i=0;
for(i=0;i<LENGTH;i++)
temp[i] = filter[i];
// or memcpy(temp,filter,sizeof(short) * LENGTH);
}
Since you talk about efficiency then go for the latter approach i.e. memcpy()
The most efficient approach is likely a memcpy. Since you know the type and size of the array.
#define LENGTH 3
void FIR(short *filter) {
short temp[LENGTH];
memcpy(temp, filter, sizeof(short)*LENGTH)
}
You could use memcpy(), or you could initialize your local array in a loop. For example,
void FIR(short *filter) {
short temp[LENGTH];
memcpy(temp, filter, LENGTH * sizeof(short));
}
or
void FIR(short *filter) {
short temp[LENGTH];
int i;
for (i = 0; i < LENGTH; i += 1) {
temp[i] = filter[i];
}
}
Other than memcopy(), one way is by using pointers:
void FIR(short *filter)
{
short temp[LENGTH], *tempP;
int i = 0;
tempP = temp;
while(LENGTH > i++) *tempP++ = *filter++;
}
If you want the length to be variable then use this
#include <stdio.h>
void FIR(short *filter, int length) {
short *temp = new short[length];
int i;
for(i = 0; i < length; ++i){
temp[i] = filter[i];
}
}
int main() {
short filter[3] = {1,2,5};
FIR(filter, 3);
int i;
for(i = 0; i < 3; ++i){
printf("%d ", filter[i]);
}
}