Whenever I run my code I get through 4 iterations of reading the file and creating a pthread until it segfaults with ID 11.
The segfault is caused by my print ln:
printf("%s %s\n", "Calling lab_manifes_alignment with package", *package);
But why does this cause a segfault?
Halp?
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
pthread_mutex_t mutex;
FILE *packageList;
void *submitPackage(void * packageReq){
char ** package = packageReq;
strcat(packageReq, " | sh lab_manifest_alignment.sh");
printf("%s %s\n", "Calling lab_manifes_alignment with package", *package);
system(packageReq);
return NULL;
}
int main(){
int numThreads;
pthread_t threads[numThreads];
//Init mutex
if(pthread_mutex_init(&mutex, NULL)){
fprintf(stderr, "Error initializing mutex");
}
int rc;
FILE *packageList = fopen("package_list.txt", "r");
if(packageList == NULL){
fprintf(stderr, "ERROR: cannot open file.\n");
return 1;
}
int i = 0;
char line[128];
while ( fgets ( line, sizeof line, packageList ) != NULL ){
/* read a line spawn as many threads as needeed*/
printf("%s %d, %s\n", "line: ",i, line);
rc = pthread_create(&(threads[i]), NULL, submitPackage, line);
if(rc){
printf("ERROR: return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
i++;
}
numThreads = i;
for(i = 0; i < numThreads; i++){
pthread_join(threads[i], NULL);
}
fclose(packageList);
return 0;
}
pthread_t threads[numThreads]; numThreads is uninitialized here, you should choose a maximum value of threads or allocate it dynamically.
fgets ( line, sizeof line, packageList ) reads 128 bytes into line (the size of the array), but strcat(packageReq, " | sh lab_manifest_alignment.sh"); adds something behind it. This is the reason for your segfault. You should increase the size of the array and decrease the size parameter in fgets.
The next iteration in your main thread overwrites your line array, while the threads working with it. You should use a 2D array or allocate a buffer in each iteration and free it in the thread after working with it. Each thread must get his own buffer, not everyone the same.
char ** package = packageReq; should be char *package = packageReq; and remove the * at the printf.
I think problem in here:
char ** package = packageReq;
Try to change:
char ** package = &packageReq;
Related
I have 2 threads and they should use the same memory. Main method should start both threads. Trå A must read the contents of a file and share it with Trå B. Trå B must also receive the data that Trå A has shared and loop through and count the number of bytes in the file. Both Threads run but on the last step before the program terminates before I memory segment fault. I use Semaphore to communicate between the Threads. here i my code:
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <semaphore.h>
#define BUFFER_SIZE 4096
typedef struct _Buffer
{
int size;
char data[BUFFER_SIZE];
} Buffer;
sem_t task1, task2;
void *thread_A(void *arg);
void *thread_B(void *arg);
int main(int argc, char *argv[])
{
Buffer *memory = malloc(sizeof(Buffer));
sem_init(&task1, 0, 0);
sem_init(&task2, 0, 0);
pthread_t thread_A_id;
pthread_t thread_B_id;
pthread_create(&thread_A_id, NULL, &thread_A, &memory);
pthread_create(&thread_B_id, NULL, &thread_B, &memory);
if (pthread_join(thread_A_id, NULL) != 0)
{
perror("Error joining thread A");
exit(1);
}
if (pthread_join(thread_B_id, NULL) != 0)
{
perror("Error joining thread B");
exit(1);
}
free(memory);
return 0;
}
void *thread_A(void *arg)
{
Buffer *buffer = (Buffer*) arg;
FILE *pdf_file = fopen("file.pdf", "rb");
if (pdf_file == NULL)
{
perror("Can not open the file");
}
printf("size of struct %ld\n", sizeof(Buffer));
buffer->size = fread(&buffer->data, sizeof(char), BUFFER_SIZE, pdf_file);
fclose(pdf_file);
sem_post(&task1);
sem_wait(&task2);
printf("A is out\n");
return NULL;
}
void *thread_B(void *arg)
{
printf("IAM IN TREAD B");
Buffer *buffer = (Buffer*) arg;
sem_wait(&task1);
int i=0;;
int byte_counts[256] = {0};
while (buffer->size != i) {
unsigned char byte = buffer->data[i];
byte_counts[byte]++;
i++;
}
for (int i = 0; i < 256; i++)
{
printf("Byte-value %02X: %d\n", i, byte_counts[i]);
}
sem_post(&task2);
printf("threadB is done 2\n");
return NULL;
}
memory is a pointer to a Buffer (Buffer *), and by taking its address, you get a pointer to a pointer to a buffer (Buffer **):
Buffer *memory = malloc(sizeof(Buffer));
...
pthread_create(&thread_A_id, NULL, &thread_A, &memory);
pthread_create(&thread_B_id, NULL, &thread_B, &memory);
But in the thread functions, you're assuming that arg is a Buffer *:
Buffer *buffer = (Buffer*) arg;
This causes undefined behaviour.
Clearly there's one indirection too many; memory is already a pointer so we don't need to take its address:
pthread_create(&thread_A_id, NULL, &thread_A, memory);
pthread_create(&thread_B_id, NULL, &thread_B, memory);
If file fails to open, fread will return -1 and it's not checked. So the loop in thread_B will read first garbage from buffer->data and then will continue out of limit (because of comparison with -1).
So, at first, there is missing handling of error from fopen() - thread_a continues after perror, second - missing error check after fread().
By the way, the check for
if (buffer->size == i)
after while (buffer->size != i) is superfluous :)
I am learning how to use threads in C and have run into a problem when creating the threads. I am making a program that takes in 2 or more file names as command line arguments, counts the number of bytes in each file in their own thread, and then outputs the name of the largest file. When I use pthread_join() directly after creating a thread, the program runs as intended. However, I know this isn't how threads should be used because it defeats the purpose. When I use pthread_join() in a for loop after creating all the threads, then the program does not work correctly. Could anyone tell me what I am doing wrong? All help is appreciated. Here is my main function.
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //mutex for changing max_bytes and max_name
int max_bytes = 0;
char max_name[100];
struct arg_struct{ //struct to hold args to pass the threads
int fd;
char name[100];
};
int main(int argc, char* argv[])
{
if(argc < 3){ //checks for correct number of arguments passed
perror("Wrong number of arguments");
return EXIT_FAILURE;
}
int arg_num = argc - 1; //holds number of arguments passed
pthread_t threadid[arg_num]; //array of thread IDs
struct arg_struct args;
for(int i = 0; i < arg_num; i++){
args.fd = open(argv[i+1], O_RDONLY);
memcpy(args.name, argv[i+1], sizeof(args.name)); //copies file name into arg_struct
int thread_err = pthread_create(&threadid[i], NULL, count_bytes, (void*)&args); //create thread by calling count_bytes and passing it a struct of args
//pthread_join(threadid[i], NULL);
if(thread_err != 0){
perror("pthread_create failed");
return EXIT_FAILURE;
}
}
for(int i = 0; i < arg_num; i++){
pthread_join(threadid[i], NULL);
}
printf("%s is the largest of the submitted files\n", max_name);
return 0;
}
This is the function that the threads are running.
void *count_bytes(void* arguments)
{
struct arg_struct *args = (struct arg_struct*)arguments; //casting arguments back to struct from void*
int fd = args -> fd;
char name[100];
memcpy(name, args -> name, sizeof(name)); //copies file name into name from args.name
int bytes = 0;
int size = 10;
char* buffer = (char*) malloc(size);
if(buffer == NULL){
perror("malloc failed");
exit(EXIT_FAILURE);
}
int buffer_count = 0;
for(int i = 0; i < size; i++){
buffer[i] = '\0'; //sets all elements to '\0' to determine end of file later
}
int read_return = read(fd, &buffer[buffer_count], 1);
if(read_return == -1){
perror("reading failed");
exit(EXIT_FAILURE);
}
while(buffer[buffer_count] != '\0'){
bytes++;
buffer_count++;
buffer[buffer_count] = '\0'; //sets previous element to '\0' to determine end of file later
if(buffer_count >= size){
buffer_count = 0; //buffer will hold up to 10 elements and then go back to the beginning
}
read_return = read(fd, &buffer[buffer_count], 1);
if(read_return == -1){
perror("reading failed");
exit(EXIT_FAILURE);
}
}
printf("%s has %d bytes\n", name, bytes);
pthread_mutex_lock(&mutex);
if(bytes > max_bytes){
max_bytes = bytes;
memcpy(max_name, name, sizeof(max_name));
}
//locks mutex to avoid race condition
//then sets bytes to max_bytes if it is later than max_bytes
//then locks mutex to allow another thread to have access
pthread_mutex_unlock(&mutex);
return NULL;
}
If it is of any use, these are the two outputs produced when it is running correctly
./a.out another buffered_readword.c
another has 8 bytes
buffered_readword.c has 3747 bytes
buffered_readword.c is the largest of the submitted files
And not correctly
./a.out another buffered_readword.c
buffered_readword.c has 1867 bytes
buffered_readword.c has 1881 bytes
buffered_readword.c is the largest of the submitted files
The problem is that there is only one args structure. After pthread_create is called the new thread may not run immediately. By the time the threads run it is likely that they will both see the same args values. Calling pthread_join inside the thread creation loop "fixes" that because it ensures each thread finishes before args is updated to the next value.
To fix properly pass a different args to each thread. Illustrative code to do that:
struct arg_struct args[arg_num];
for(int i = 0; i < arg_num; i++){
args[i].fd = open(argv[i+1], O_RDONLY);
memcpy(args[i].name, argv[i+1], sizeof(args[i].name));
int thread_err = pthread_create(&threadid[i], NULL, count_bytes, &args[i]);
....
I am trying to get into the world of threads and am having some trouble. The code below works every once in a while but seems to be completely random. Giving it the same input keeps giving me different results and I am quite confused.
Sometimes PrintHello() prints out the arguments and other times it prints garbage and sometimes it just segfaults.
#define NUM_THREADS 5
char *prompt = "% ";
struct thread_data{
int thread_id;
//int sum;
char *message;
};
void *PrintHello(void *threadarg)
{
struct thread_data *local_data;
local_data = (struct thread_data *) threadarg;
int taskid = local_data->thread_id;
const char *arguments = local_data->message;
fprintf(stderr, "Hello World! It's me, thread %s!\n", arguments);
pthread_exit(NULL);
}
PrintHello() is where I think the issue is.
int main()
{
int pid;
//int child_pid;
char line[81];
char *token;
char *separator = " \t\n";
char **args;
char **args2;
char *hp;
char *cp;
char *ofile;
int i;
int j, h, t, rc;
args = malloc(80 * sizeof(char *));
args2 = malloc(80 * sizeof(char *));
signal(SIGINT, SIG_IGN);
while (1) {
fprintf(stderr, "%s", prompt);
fflush(stderr);
if (fgets(line, 80, stdin) == NULL)
break;
/* get rid of the '\n' from fgets */
if (line[strlen(line) - 1] == '\n'){
line[strlen(line) - 1] = '\0';
}
// split up the line
i = 0;
while (1) {
token = strtok((i == 0) ? line : NULL, separator);
if (token == NULL)
break;
args[i++] = token;
}
args[i] = NULL;
ofile = args[i-1];
printf("%s\n", ofile);
The stuff above this is just tokenizing the input and works fine.
struct thread_data thread_data_array[i];
pthread_t threads[i];
for(t=0; t<i; t++){
thread_data_array[t].thread_id = t;
thread_data_array[t].message = args[t];
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&thread_data_array[t]);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
}
}
There are several issues with your code, but I'll focus on the key ones that affect stability.
You're not checking the return values of malloc(). If the return value is NULL, it means the operation failed, and you have to either re-try, or start cleaning up all dynamically allocated memory from malloc(), calloc(), strdup(), etc, and finish up with your program gracefully. Attempting to dereference NULL (ie: use the pointer from the failed memory allocation call) will crash your program.
Your program doesn't account for zero valid arguments provided (ie: just hitting ENTER at the prompt. Change ALL newline instances to '\0', and continue.
Also, count the number of tokens you've discovered. Good practise, and helps you check if no valid input was found.
Consider reading up on starting threads in a detached state versus a joinable state. The biggest problem in your code is that you start all the threads, and then your while loop immediately executes again, and re-assigns new values to the thread[] array. Also, the same argument is passed to them while still in use (thread_data_array[t]), and you have no mutexes to protect them. Also, if your program's main() exits early, then all running threads get killed off immediately, and don't get to finish.
You should pthread_join() on joinable threads to ensure you wait until they complete before you proceed.
You provide no way to exit the program without either using CTRL+C or crashing it. Not a good idea.
Note that the threads don't necessarily execute in the order you created them, though they luckily did in this case. You'll need to learn about barriers, condition variables (condvars) and mutexes to do more advanced synchronization handling.
You're missing a lot of important header files. Surprised your code compiled.
Learn how to debug your code with gdb. In this case, I compiled it via gcc test.c -lpthread -O0 -ggdb, then stepped through the code via the "next" n command after starting it in gdb with run. It makes your life a lot easier.
Updated Code Listing
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#define NUM_THREADS 5
#define BUF_LEN (80)
char *prompt = "% ";
struct thread_data{
int thread_id;
//int sum;
char *message;
};
void *PrintHello(void *threadarg)
{
struct thread_data *local_data;
local_data = (struct thread_data *) threadarg;
int taskid = local_data->thread_id;
const char *arguments = local_data->message;
fprintf(stderr, "Hello World! It's me, thread %s!\n", arguments);
pthread_exit(NULL);
}
int main()
{
int pid;
//int child_pid;
char line[81];
char *token;
char *separator = " \t\n";
char **args;
char **args2;
char *hp;
char *cp;
char *ofile;
int i;
int j, h, t, rc;
args = malloc(BUF_LEN * sizeof(char *)); // ISSUE: Can fail. Check return value.
args2 = malloc(BUF_LEN * sizeof(char *)); // ISSUE: Can fail.
signal(SIGINT, SIG_IGN);
while (1)
{
fprintf(stderr, "%s", prompt);
fflush(stderr);
if (fgets(line, BUF_LEN, stdin) == NULL)
{
break;
}
/* get rid of the '\n' from fgets */
/*
if (line[strlen(line) - 1] == '\n'){
line[strlen(line) - 1] = '\0';
}
*/
for ( t = 0; t < BUF_LEN; t++ )
{
if ( line[t] == '\n' )
{
line[t] = '\0';
}
}
// split up the line
i = 0;
int numTokens = 0;
while (1) {
token = strtok((i == 0) ? line : NULL, separator);
if (token == NULL)
{
break;
}
args[i++] = token;
numTokens++;
}
// Abort if zero tokens found.
if ( numTokens == 0 )
{
continue;
}
// Exit if input is "quit"
if ( strcasecmp(line, "quit") == 0 )
{
break;
}
args[i] = NULL;
ofile = args[i-1];
printf("%s\n", ofile);
struct thread_data thread_data_array[i];
pthread_t threads[i];
for(t=0; t<i; t++)
{
thread_data_array[t].thread_id = t;
thread_data_array[t].message = args[t];
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&thread_data_array[t]);
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
// Wait for threads to complete work.
for(t=0; t<i; t++)
{
pthread_join(threads[t], NULL);
}
}
}
Sample Run
%
%
%
% Hello world. This is a test
test
Hello World! It's me, thread test!
Hello World! It's me, thread a!
Hello World! It's me, thread is!
Hello World! It's me, thread This!
Hello World! It's me, thread world.!
Hello World! It's me, thread Hello!
%
% 1 2 3
3
Hello World! It's me, thread 3!
Hello World! It's me, thread 2!
Hello World! It's me, thread 1!
% QUit
I write a C code that reads a file and do some works on it, using multi-threads functions. I read file in the fun1 so I expect that file read linearly, but some tests I do on this code show me that it seems that the file does not read in the right order. What is wrong about my code?!
#include <pthread.h>
#define BUFSIZE 1024*10
#define NUM_THREADS 4
typedef struct _thread_data_t {
unsigned char id;
char *msg;
unsigned int msg_len;
} thread_data_t;
/* thread function */
void *thr_func(void *arg) {
thread_data_t *data = (thread_data_t *)arg;
fun2(data->msg, data->msg_len);
pthread_exit(NULL);
}
void fun1(FILE *file) {
unsigned char i, j, buf[BUFSIZE];
pthread_t thr[NUM_THREADS];
thread_data_t thr_data[NUM_THREADS];
int rc, fr, fd = fileno(file);
for (;;) {
for (i = 0; i < NUM_THREADS; i++) {
fr = read(fd, buf, BUFSIZE);
if (fr <= 0) break;
thr_data[i].id = i;
thr_data[i].msg = buf;
thr_data[i].msg_len = fr;
if ((rc = pthread_create(&thr[i], NULL, thr_func, &thr_data[i]))) {
fprintf(stderr, "error: pthread_create, rc: %d\n", rc);
fr = -1;
break;
}
}
for (j = 0; j < i; j++) {
pthread_join(thr[j], NULL);
}
if (fr <= 0) break;
}
}
Edit:
I think that until all threads finish their works nothing new read from the file. Is it true?
I think your problem is the single buffer:
buf[BUFSIZE];
In each loop you read data into that buffer and then prepare data for the thread
thr_data[i].msg = buf;
which I assume doesn't include a copy of the buffer itself. I assume msg is just a pointer.
So in the next iteration, you'll overwrite the buf with new data from the file and consequently change data for already created threads.
I guess you'll need
buf[NUM_THREADS][BUFSIZE];
so that each thread gets its own data area to work on.
Quote:
I think that until all threads finish their works nothing new read from the file. Is it true?
Correct, that's what pthread_join does for you
This code receives a input file with 10 filenames, stores them into an 2d array and creates 10+1 threads: a requester and 10 converters. This is only a skeleton, so my threads only print their id, thei're not accessing any global or shared variable or something that requires a mutex. So, what should I do to avoid a segmentation fault here?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <string.h>
#include <time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <math.h>
#include <unistd.h>
#include <errno.h>
#define READ_BUFFER_LEN 16
//#define MAX_LENGTH 128
enum {
MAX_LENGTH = 512
};
typedef struct FileNameArray {
size_t nfiles; /* Number of file names allocated and in use */
size_t maxfiles; /* Number of entries allocated in array */
char **files; /* Array of file names */
} FileNameArray;
//GLOBAL vars
int num_images, *threads_ids /*threads ids*/;
pthread_t *threads;
void deallocate2D(FileNameArray *names) {
size_t i;
for (i = 0; i < names->nfiles; i++)
free(names->files[i]);
free(names->files);
names->nfiles = 0;
names->files = 0;
names->maxfiles = 0;
}
int readInputFile(FILE *fp, FileNameArray *names) {
num_images = names->nfiles;
int max_lines = names->maxfiles;
char **file_names = names->files;
char line[MAX_LENGTH];
char **final_filenames, **array;
while (fgets(line, sizeof line, fp) != NULL) {
if (line[0] != '\n') {
/* Remove newline from end of file name */
char *nl = strchr(line, '\n');
if (nl != 0)
*nl = '\0';
if (num_images >= max_lines) {
max_lines += 100;
array = realloc(file_names, max_lines * sizeof (char*));
if (array == NULL) {
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = max_lines;
names->files = array;
file_names = array;
}
if ((file_names[num_images] = malloc(strlen(line) + 1)) == NULL) {
fprintf(stderr, "Error allocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->nfiles++;
strcpy(file_names[num_images], line);
printf("name of file %d is: %s \n", num_images, file_names[num_images]);
num_images++;
}
}
printf("Num_lines: %d\n", num_images);
//realloc to number of lines in the file, to avoid wasting memory
if ((final_filenames = realloc(file_names, num_images * sizeof (char*))) == NULL) {
fprintf(stderr, "Error reallocating space for 2d array: %s\n",
strerror(errno));
return -1;
}
names->maxfiles = num_images;
names->files = final_filenames;
return 0;
}
void* requester(void* arg) {
printf("This is the requester thread\n");
//sleep(1);
pthread_exit(NULL);
return NULL;
}
void* converter(void *id) {
int my_id = *((int*) id);
printf("Thread's id is: %d\n", my_id);
pthread_exit(NULL);
return NULL;
}
int main(int argc, char *argv[]) {
FileNameArray names = {0, 0, 0};
int i, rc;
pthread_attr_t attr;
//check parameters
if (argc < 4) {
fprintf(stderr, "Usage: %s input_filename.ppm charWidth charHeight\n",
argv[0]);
return -1;
}
printf("Opening input file [%s]\n", argv[1]);
FILE *fpin = fopen(argv[1], "r");
if (fpin == NULL) {
fprintf(stderr, "Could not open input file %s (%s)\n",
argv[1], strerror(errno));
return -1;
}
if ((names.files = malloc(10 * sizeof (char*))) == NULL) {
fprintf(stderr, "Error allocating initial space for 2d array: %s\n",
strerror(errno));
return -1;
}
names.maxfiles = 10;
if (readInputFile(fpin, &names) == -1) {
fprintf(stderr, "Error reading image filenames from input\n");
return -1;
}
threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
/* Initialize and set thread detached attribute */
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
//creates requester thread, the 1st one on the list
pthread_create(&threads[0], &attr, requester, &threads_ids[0]);
threads_ids[0] = 0;
//creates so many converter threads as the number of images to convert
for (i = 1; i < num_images + 1; i++) {
threads_ids[i] = i;
rc = pthread_create(&threads[i], &attr, converter, &threads_ids[i]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for (i = 0; i < num_images + 1; i++) {
printf("Waiting for thread nr %d\n", i);
rc = pthread_join(threads[i], NULL);
if (rc) {
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
}
fclose(fpin);
free(threads);
free(threads_ids);
printf("###########\n");
deallocate2D(&names);
printf("Done!\n");
return 0;
}
This is one of the possible ouputs:
Num_lines: 10
This is the requester thread
Thread's id is: 1
Thread's id is: 2
Thread's id is: 3
Thread's id is: 5
Thread's id is: 4
Thread's id is: 6
Thread's id is: 7
Thread's id is: 8
Thread's id is: 9
Waiting for thread nr 0
Thread's id is: 10
Segmentation fault
and this is the result of gdb:
Program received signal SIGSEGV, Segmentation fault.
0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
3724 malloc.c: No such file or directory.
in malloc.c
(gdb) where
#0 0x001bfea9 in *__GI___libc_free (mem=0x804c278) at malloc.c:3724
#1 0x00120802 in *__GI__dl_deallocate_tls (tcb=<value optimized out>,
dealloc_tcb=112) at dl-tls.c:487
#2 0x00133748 in __free_stacks (limit=41943040) at allocatestack.c:274
#3 0x00133849 in queue_stack (pd=0xb5fd9b70) at allocatestack.c:302
#4 __deallocate_stack (pd=0xb5fd9b70) at allocatestack.c:740
#5 0x00134b37 in pthread_join (threadid=3053296496, thread_return=0x0)
at pthread_join.c:110
#6 0x0804955c in main (argc=4, argv=0xbffff4a4) at main.c:261
threads = (pthread_t*) malloc(num_images + 1 * sizeof (pthread_t));
threads_ids = (int*) malloc(num_images + 1 * sizeof (int));
Certainly you must have intended to write
threads = malloc((num_images + 1) * sizeof (pthread_t));
threads_ids = malloc((num_images + 1) * sizeof (int));
or
threads = calloc(num_images + 1, sizeof (pthread_t));
threads_ids = calloc(num_images + 1, sizeof (int));
instead?