Thread execution issue - c

I'm approaching C programming with threads and I can't get this program to work properly. Basically there's a vector with k elements, n threads and each thread has to calculate the max on its k/n elements.
My code is (please note it's not the whole code):
// Struct code used later
struct maxStruct
{
double *vettore;
int dimensione;
};
// Gathering data input from user
[ . . . ]
vector = (double *) malloc (dimensione * sizeof(double));
pid_thread = (int *) malloc (numero_thread * sizeof(int));
thread = (pthread_t *) malloc (numero_thread * sizeof(pthread_t));
// Generating the vector
[ . . . ]
for (i = 0; i < numero_thread; i++)
{
e = generaStruct(i, vettore, dimensione, numero_thread);
if (status = pthread_create(&thread[i], NULL, calcolaMassimo, (void *) e))
{
pthread_perror("pthread_join", status);
exit(1);
}
}
//Note that the function doesn't calculate the max, I've coded it in this way
//in order to see whether it was being called by each thread and apparently it is not.
void *calcolaMassimo(void * e)
{
printf("Sono chiamata!!\n");
struct maxStruct *sottoVettore = e;
printf("Dimensione: %d\n", ((*sottoVettore).dimensione));
}
Apparently this function is not being called by each thread and I can't figure out why. Will you please help me solve this issue?

Firstly, a minor nit pick, the idiomatic way to write (*sottoVettore).dimensione) is sottoVettore->dimensione.
The process containing all of threads will exit when main() exits. I know you said you're joining in you're actual code so that should not be an issue but if you're not joining in the test code then that could be an issue.
It is also possible that the issue is not that the code in each thread isn't executing, but that the statements aren't actually reaching stdout. You might want to try a fflush(stdout) at the end of calcolaMassimo and see if that changes things.

Related

How can I create a function object in C

I would like to create a wrapper for c functions, so that I can convert a function call of the form ret = function(arg1,arg2,arg3); into the form /*void*/ function_wrapper(/*void*/);. That is similar to function objects in C++ and boost bind.
Is this possible? how can I do it?
Update:
To explain in more details what I am looking for:
We start with this function:
int f(int i){
//do stuff
return somevalue;
}
Obvioulsy, it is called like this:
// do stuff
int x = 0;
ret = f(0);
// do more stuff.
I would like to do some magic that will wrap the function into void function(void)
struct function_object fo;
fo.function_pointer = &f;
fo.add_arg(x, int);
fo.set_ret_pointer(&ret);
fo.call();
Note: I saw that there was a vote for closing this question and marking it as unclear. Please do not do that. I have a legitimate need to get this question answered. If you need explanation, ask and I will be glad to elaborate.
I came up with a better code that might allow you to do what you want. First I'll explain how it works, show the code and explain why I still don't think it's a good idea to use it (though the code might open doors for improvements that addresses those issues).
Functionality:
Before you start using the "function objects", you have to call an initialization function (FUNCTIONOBJ_initialize();), which will initialize the mutexes on every data structure used in the library.
After initializing, every time you want to call one of those "function objects", without using the parameters, you will have to set it up first. This is done by creating a FUNCTIONOBJ_handler_t pointer and calling get_function_handler(). This will search for a free FUNCTIONOBJ_handler data structure that can be used at the moment.
If none is found (all FUNCTIONOBJ_handler data structures are busy, being used by some function call) NULL is returned.
If get_function_handler() does find a FUNCTIONOBJ_handler data structure it will try to lock the FUNCTIONOBJ_id_holder data structure, that holds the ID of the FUNCTIONOBJ_handler of the function about to be called.
If FUNCTIONOBJ_id_holder is locked already, get_function_handler() will hang until it's unlocked by the thread using it.
Once FUNCTIONOBJ_id_holder is locked, the ID of the grabbed FUNCTIONOBJ_handler is wrote on it and the FUNCTIONOBJ_handler pointer is returned by get_function_handler.
With the pointer in hand, the user can set the pointer to the arguments and the return variable with set_args_pointer and set_return_pointer, which both take a void * as arguments.
Finally, you can call the function you want. It has to:
1 - Grab the FUNCTIONOBJ_handler ID from the FUNCTIONOBJ_id_holder data structure and use it to get a pointer to the FUNCTIONOBJ_handler itself.
2 - Use the FUNCTIONOBJ_handler to access the arguments.
3 - Return by using one of the return function (on the example we have ret_int, which will return an integer and unlock the FUNCTIONOBJ_handler)
Below is a simplified mind map describing a bit of what is going on:
Finally, the code:
funcobj.h:
#include <stdio.h>
#include <pthread.h>
#define MAX_SIMULTANEOUS_CALLS 1024
typedef struct {
//Current ID about to be called
int current_id;
//Mutex
pthread_mutex_t id_holder_mutex;
} FUNCTIONOBJ_id_holder_t;
typedef struct {
//Attributes
void *arguments;
void *return_pointer;
//Mutex
pthread_mutex_t handler_mutex;
} FUNCTIONOBJ_handler_t;
FUNCTIONOBJ_handler_t FUNCTIONOBJ_handler[MAX_SIMULTANEOUS_CALLS];
FUNCTIONOBJ_id_holder_t FUNCTIONOBJ_id_holder;
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value);
void FUNCTIONOBJ_initialize(void);
FUNCTIONOBJ_handler_t *get_function_handler(void);
funcobj.c:
#include "funcobj.h"
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->return_pointer = pointer;
}
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->arguments = pointer;
}
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value){
if(this->return_pointer){
*((int *) (this->return_pointer)) = return_value;
}
pthread_mutex_unlock(&(this->handler_mutex));
}
void FUNCTIONOBJ_initialize(void){
for(int i = 0; i < MAX_SIMULTANEOUS_CALLS; ++i){
pthread_mutex_init(&FUNCTIONOBJ_handler[i].handler_mutex, NULL);
}
pthread_mutex_init(&FUNCTIONOBJ_id_holder.id_holder_mutex, NULL);
}
FUNCTIONOBJ_handler_t *get_function_handler(void){
int i = 0;
while((0 != pthread_mutex_trylock(&FUNCTIONOBJ_handler[i].handler_mutex)) && (i < MAX_SIMULTANEOUS_CALLS)){
++i;
}
if(i >= MAX_SIMULTANEOUS_CALLS){
return NULL;
}
//Sets the ID holder to hold this ID until the function is called
pthread_mutex_lock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
FUNCTIONOBJ_id_holder.current_id = i;
return &FUNCTIONOBJ_handler[i];
}
main.c:
#include "funcobj.h"
#include <string.h>
//Function:
void print(void){
//First the function must grab the handler that contains all its attributes:
//The FUNCTIONOBJ_id_holder is mutex locked, so we can just access its value and
//then free the lock:
FUNCTIONOBJ_handler_t *this = &FUNCTIONOBJ_handler[FUNCTIONOBJ_id_holder.current_id];
//We dont need the id_holder anymore, free it!
pthread_mutex_unlock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
//Do whatever the function has to do
printf("%s\n", (char *) this->arguments);
//Return the value to the pointed variable using the function that returns an int
ret_int(this, 0);
}
void *thread_entry_point(void *data){
int id = (int) data;
char string[100];
snprintf(string, 100, "Thread %u", id);
int return_val;
FUNCTIONOBJ_handler_t *this;
for(int i = 0; i < 200; ++i){
do {
this = get_function_handler();
} while(NULL == this);
set_args_pointer(this, string);
set_return_pointer(this, &return_val);
print();
}
return NULL;
}
int main(int argc, char **argv){
//Initialize global data strucutres (set up mutexes)
FUNCTIONOBJ_initialize();
//testing with 20 threads
pthread_t thread_id[20];
for(int i = 0; i < 20; ++i){
pthread_create(&thread_id[i], NULL, &thread_entry_point, (void *) i);
}
for(int i = 0; i < 20; ++i){
pthread_join(thread_id[i], NULL);
}
return 0;
}
To compile: gcc -o program main.c funcobj.c -lpthread
Reasons to avoid it:
By using this, you are limiting the number of "function objects" that can be running simultaneously. That's because we need to use global data structures to hold the information required by the functions (arguments and return pointer).
You will be seriously slowing down the program when using multiple threads if those use "function objects" frequently: Even though many functions can run at the same time, only a single function object can be set up at a time. So at least for that fraction of time it takes for the program to set up the function and actually call it, all other threads trying to run a function will be hanging waiting the the data structure to be unlocked.
You still have to write some non-intuitive code at the beginning and end of each function you want to work without arguments (grabbing the FUNCTIONOBJ_handler structure, unlocking the FUNCTIONOBJ_id_holder structure, accessing arguments through the pointer you grabbed and returning values with non-built-in functions). This increases the chances of bugs drastically if care is not taken, specially some nasty ones:
Increases the chances of deadlocks. If you forget to unlock one of the data structures in any point of your code, you might end up with a program that works fine at some moments, but randomly freeze completely at others (because all function calls without arguments will be hanging waiting for the lock to be freed). That is a risk that happens on multithreaded programs anyways, but by using this you are increasing the amount of code that requires locks unnecessarily (for style purposes).
Complicates the use of recursive functions: Every time you call the function object you'll have to go through the set up phrase (even when inside another function object). Also, if you call the recursive function enough times to fill all FUNCTIONOBJ_handler structures the program will deadlock.
Amongst other reasons I might not notice at the moment :p

Selecting a random thread in c

I need to randomly select two out of three threads, and I've come up with a few ideas but I'm not sure if they would work.
Is it better to have an array of 3 threads and then have another thread choose from there, or to have three independent threads? And in both cases, how would you even write the function that would randomly select them? From what I understand, rand() can't be used because it's only for integers, and other than that I have no clue what to use.
This is kind of a game project, and the winner of the two selected threads plays with the remaining thread. Can the same function be used for both instances then, or does there have to be a new one? I'm guessing the most useful thing would be the same thread using the same function, only with its choices narrowed down?
I know this is probably simple but I'm only just starting out with threads, so excuse my poor skills. Any help is greatly appreciated!
EDIT: Thank you everyone! However, since I'm already confused I really don't want to go into semaphores now. I've written some code based on one of the comments but it's not giving me the wanted output. Here's what I have:
EDIT #2: I somehow managed to write it! The only thing left is for the function to call itself again but the pointers kind of confuse me so I don't know how to call it in the else part, and I don't know how else to stop the randomized values from repeating.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *play (void *myvar);
void *select (void *var);
pthread_t tid[3], th;
int i, ra1, ra2;
int main(int argc, char *argv[]) {
pthread_create(&th, NULL, &select, NULL);
for (i = 0; i < 3; i++) {
pthread_create(&tid[i], NULL, &play, NULL);
}
pthread_join(th, NULL);
for (i = 0; i < 3; i++) {
pthread_join(tid[i], NULL);
}
return 0;
}
void *play (void *myvar) {
printf("Thread%i hits the ball!\n", i);
return NULL;
}
void *select (void *var) {
srand ( time(NULL) );
ra1 = rand() % 3 + 1;
ra2 = rand() % 3 + 1;
if (ra1 != ra2) {
printf("Threads have been chosen! Thread%i and Thread%i will start the game!\n",
ra1, ra2);
}
else //what to do?;
return NULL;
}
I'm assuming that you want 2 of 3 threads to perform some task, and that this selection should be random. I further assume that you want these 3 threads to do the selection "in common", i.e. not requiring a forth thread to do the selection (or to have one of the three doing a special selection procedure).
A possible approach would be to use a counting semaphore to "protect" the task and only allow 2 threads to use it, i.e. initialize the semaphore to 2. You can then have each thread sleep a random (small) delay, and try to acquire the semaphore.
Without much comment, see this example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
struct data {
sem_t * semaphore;
int random;
char const * name;
};
void task(char const * name) {
printf("WOOOOO %s\n", name);
}
void * operation(void * d) {
struct data * data = d;
usleep(data->random % 1000);
if (sem_trywait(data->semaphore) == 0) {
task(data->name);
} else {
printf("FAILED, such a shame for %s\n", data->name);;
}
return NULL;
}
int main(void) { // NOTE: Demo, thus no error checking
srand(time(NULL));
sem_t * semaphore = malloc(sizeof(*semaphore));
struct data data[3] = {
{semaphore, rand(), "John"},
{semaphore, rand(), "Marry"},
{semaphore, rand(), "Rupert"}
};
pthread_t others[2];
sem_init(semaphore, 0, 2);
pthread_create(&(others[0]), NULL, &operation, &(data[0]));
pthread_create(&(others[1]), NULL, &operation, &(data[1]));
(void)operation(&(data[2]));
pthread_join(others[0], NULL);
pthread_join(others[1], NULL);
sem_destroy(semaphore);
free(semaphore);
return 0;
}
(Live on ideone)
Note that using rand makes this choice here actually pseudo-random. Getting rid of the sleeping part can lead to a real random selection, especially when the threads have been doing different things previously. (Although I can imagine a situation where one would be able to influence the threads from the outside to achieve a particular selection)
Array of thread ID should server your purpose. Use the rand() function to randomly select the index of the array. Whatever thread ID is stored at that index of your array should be your selected thread.

C MPI - Crash for no apparent reason - Program Received signal SIGSEGV

I am running a program in a linux cluster using MPICH2 1.0.6 (i can't actually update it to MPICH3, so i am stuck to that version) and for no apparent reason the program doesn't execute.
I compile it using mpicc -o prog prog.c -lm and execute with mpiexec
The program is an implementation of the hierarchical agglomerative clustering algorithm using the vector space model. The data collection is an n*m array (in the program DOC*MAXWORDS) which are divided into the nodes of the cluster like PARTS=DOC/procs so every node is responsible for PARTS*MAXWORDS data.
While debugging in a serial machine using gdb and ddd i get that the program has a segmentation error in a specific line of the code, where i can't find what is wrong with it. Take a look.
while(iterations != DOC-k){//bigLoop
iterations++;
x=y=-1;
pos1=pos2=node1=node2=-1;
for(i=0;i<PARTS;i++){//ELEGXOS MEGISTOU TOPIKA
if(max_array[i]>x){
x=max_array[i];
pos1=i;
}
else if(max_array[i]==x){
pos2=i;
} //ELEGXOS META TO LOOP GIA OMOIOTHTES
}
if(max_array[pos1]!=max_array[pos2]){
for(i=0;i<PARTS;i++){
if(max_array[i]>max_array[pos2] && i!=pos1)
pos2=1;
}
}
if(MPI_Allgather(&x,1,MPI_DOUBLE,
n_max,1,MPI_DOUBLE,MPI_COMM_WORLD) != MPI_SUCCESS) {
printf("Allgather high valuer - error");
exit(1);
}
for(i=0;i<procs;i++){
if(n_max[i]>y){
y=n_max[i];
node1=i;
}
else if(n_max[i]==y){
node2=i;
}
}
for(i=0;i<MAXWORDS;i++){
merger_one[i]=merger_two[i]=0;
}
if(n_max[node1]==n_max[node2]){
if(id==node1){
for(i=0;i<MAXWORDS;i++){
merger_one[i]=vector[node1*PARTS+pos1][i];
last_one[i]=vector[(node1*PARTS)+texts_vectors[node1]][i];
}
size_one=size_of[pos1];
nn_array[pos1]=nn_array[texts_vectors[node1]];
max_array[pos1]=max_array[texts_vectors[node1]];
size_of[pos1]=size_of[texts_vectors[node1]];
texts_vectors[node1]--;
}
if(id==node2){
for(i=0;i<MAXWORDS;i++){
merger_two[i]=vector[node2*PARTS+pos2][i];
last_two[i]=vector[(node2*PARTS)+texts_vectors[node2]][i];
}
j=pos2;
pos2=pos1;
pos1=j;
size_two=size_of[pos2];
nn_array[pos2]=nn_array[texts_vectors[node2]];
max_array[pos2]=max_array[texts_vectors[node2]];
size_of[pos2]=size_of[texts_vectors[node2]];
texts_vectors[node2]--;
}
}
else{
node2=node1;
if(id==node1){
for(i=0;i<MAXWORDS;i++){
merger_one[i]=vector[node1*PARTS+pos1][i];
merger_two[i]=vector[node2*PARTS+pos2][i];
last_one[i]=vector[(node1*PARTS)+texts_vectors[node1]][i];/*SIGSEV ERROR*/
last_two[i]=vector[(node2*PARTS)+texts_vectors[node2]-1][i];
}
size_one=size_of[pos1];
size_two=size_of[pos2];
nn_array[pos1]=nn_array[texts_vectors[node1]];
max_array[pos1]=max_array[texts_vectors[node1]];
size_of[pos1]=size_of[texts_vectors[node1]];
nn_array[pos2]=nn_array[texts_vectors[node2]-1];
max_array[pos2]=max_array[texts_vectors[node2]-1];
size_of[pos2]=size_of[texts_vectors[node2]-1];
texts_vectors[node1]=texts_vectors[node1]-2;
}
}
MPI_Bcast(&pos1, 1, MPI_INT,node1, MPI_COMM_WORLD);
MPI_Bcast(&pos2, 1, MPI_INT,node2, MPI_COMM_WORLD);
MPI_Bcast(&size_one, 1, MPI_INT,node1, MPI_COMM_WORLD);
MPI_Bcast(&size_two, 1, MPI_INT,node2, MPI_COMM_WORLD);
MPI_Bcast(merger_one, MAXWORDS, MPI_INT,node1, MPI_COMM_WORLD);
MPI_Bcast(merger_two, MAXWORDS, MPI_INT,node2, MPI_COMM_WORLD);
MPI_Bcast(last_one, MAXWORDS, MPI_INT,node1, MPI_COMM_WORLD);
MPI_Bcast(last_two, MAXWORDS, MPI_INT,node2, MPI_COMM_WORLD);
MPI_Allgather(&texts_vectors,1,MPI_INT,texts_vectors,1,MPI_INT,MPI_COMM_WORLD);
for(i=0;i<MAXWORDS;i++){
vector[node1*PARTS+pos1][i]=last_one[i];
vector[node2*PARTS+pos2][i]=last_two[i];
}
Pmanager=PARTS+1;
for(i=0;i<procs;i++){
if(texts_vectors[i]<Pmanager)
Pmanager=i;
}
texts_vectors[Pmanager]++;
for(i=0;i<MAXWORDS;i++){
x=merger_one[i]*size_one;
y=merger_two[i]*size_two;
vector[Pmanager*PARTS+texts_vectors[Pmanager]][i]=(x+y)/(size_one + size_two);
}
for(i=id*PARTS; i< (id+1)*texts_vectors[id]; i++){
for(j=0;j<procs;j++){
for(m=j*PARTS;m<j*PARTS+texts_vectors[j];m++){
x=0;y=0;z=0;
for(l=0; l < MAXWORDS; l++){
x+=vector[i][l]*vector[m][l];
y+=vector[i][l]*vector[i][l];
z+=vector[m][l]*vector[m][l];
}
if(i!=m){
if(y!=0 && z!=0){
sim_matrix[i-(PARTS*id)][m] = x / (sqrt(y) * sqrt(z) );
}
else{
sim_matrix[i-(PARTS*id)][m] = 0.0;
}
}
}
}
}
for(i=0; i<texts_vectors[id]; i++){
x=0.0;
for(j=0;j<DOC;j++){
if(sim_matrix[i][j]>x){
nn_array[i]=j;
max_array[i]=x=sim_matrix[i][j];
}
}
}
}
Prior to this there is the creation of the arrays and the data input into the vector[i][j]
I created the arrays using malloc :
int **vector = malloc(DOC * sizeof *vector);
for (i = 0; i < DOC; i++){
vector[i] = malloc(MAXWORDS * sizeof **vector);
}
double **sim_matrix = malloc(PARTS * sizeof *sim_matrix);
for (i = 0; i < PARTS; i++)
sim_matrix[i] = malloc(DOC * sizeof **sim_matrix);
int *list = malloc(WHOLE * sizeof(int));
int *nn_array = malloc(PARTS * sizeof(int));
double *max_array = malloc(PARTS * sizeof(double));
int *size_of = malloc(PARTS * sizeof(int));
double *n_max = malloc(procs * sizeof(double));
int *texts_vectors = malloc(procs * sizeof(int));
int *merger_one = malloc(MAXWORDS * sizeof(int));
int *merger_two = malloc(MAXWORDS * sizeof(int));
int *last_one = malloc(MAXWORDS * sizeof(int));
int *last_two = malloc(MAXWORDS * sizeof(int));
The line where the problem persists: last_one[i]=vector[(node1*PARTS)+texts_vectors[node1]][i];/*SIGSEV ERROR*/ is also executed in the first part of the if-loop if(n_max[node1]==n_max[node2]){ but in that case there is no error.
The only thing that feels a little suspicious about this problem is the texts_vectors[i] array which keeps counting the number of vector[i][j] type data that are currently inside the nodes. But even that i think i got it covered.
I really hope that somebody could have a look at this cause it is really frustrating and it needs to be done.
If you have a better idea of what is going on and want to take a look at the whole code, i pasted it into a pastezone. Cheers and thanks in advance.
EDIT:
As it turns out the value that i passed with the array text_vectors where exceeding the boundaries of the array. Since the value was giving the maximum value, for the actual last position in the array i should subtract 1. So that was it, no segmentation fault in the serial gdb and ddd. However this program now it doesn't run for more than 2 nodes. If i execute it in 4> nodes it crashes.
This line has multiple errors in it:
MPI_Allgather(&texts_vectors,1,MPI_INT,texts_vectors,1,MPI_INT,MPI_COMM_WORLD);
First, you are providing a pointer to a pointer to the data as the first argument of the gather-to-all operation. Therefore the value transmitted by each rank is not the first element of text_vectors but rather the memory address of the data (or the lower half of the address on 64-bit little-endian LP64 systems).
Second, if you fix that by removing the address-off operator & from the beginning of the first argument, you will run into another problem. The MPI standard does not allow the source and destination buffers in MPI_Allgather to overlap. Some MPI implementations do not enforce that requirement and silently do The Right Thing (TM). Some other MPI implementations will try to copy the data with memcpy and run into problems with the C library (memcpy does not allow overlapping buffers). And finally, some MPI implementations will give you a nice error message about overlapping buffers and terminate your program.
Since you are sending a single integer element, simply copy the value into a temporary variable and use its address as the first argument.

Using pthread_create

I am having errors when I try to use pthread_create. I understand that my use of argsRight->thread_id / argsLeft->thread_id and NULL are not correct, but I am unsure how else to make a reference to the thread id. It requires a pointer, but it seems like every way I tried (&, *), the GCC compiler would not accept.
Also, is there any reason it will not accept my use of NULL? I can't see any reason that would be wrong, but GCC says my use of the void function is invalid.
Can anyone shed some light on how to properly set up a call to pthread_create? I have included parts from my method where I am using the pthread_create function.
void pthreads_ms(struct ms_args* args)
{
int left_end = (args->end + args->start) / 2;
int right_start = left_end + 1;
int rc1, rc2;
// Create left side struct
struct ms_args* argsLeft;
argsLeft = malloc(sizeof(args));
argsLeft->thread_id = (2 * args->thread_id + 1);
argsLeft->start = args->start;
argsLeft->end = left_end;
argsLeft->array = args->array;
// Same methodology as above to create the right side
if (args->start != args->end)
{
// Print the thread id number, and start and end places
printf("[%d] start %d end %d", args->thread_id, args->start, args->end);
// Sort Left Side
rc1 = pthread_create(argsLeft->thread_id, NULL, pthreads_ms(argsLeft), argsLeft); //problem line here
//Sort right side
rc2 = pthread_create(argsRight->thread_id, NULL, pthreads_ms(argsRight), argsRight); //problem line here
}
It is not your application, it's pthread_create() will fill thread_id field. So, first of all, struct ms_args's field should be of type pthread_t and you should pass a pointer to that field:
pthread_create(&argsLeft->thread_id, ...
According to pthread_create the proper call should be
rc1 = pthread_create(&(argsLeft->thread_id), NULL, &pthreads_ms, argsLeft);
Same goes for right side.
The definition of pthread_ms() should include a return value
void *pthreads_ms(struct ms_args* args) { ... }
Besides that, your code looks pretty dangerous to me, since it creates recursively two threads for every existing one. Depending on your input, this might build a large tree of threads, which could bring your system to a halt.

Running out of memory.. How?

I'm attempting to write a solver for a particular puzzle. It tries to find a solution by trying every possible move one at a time until it finds a solution. The first version tried to solve it depth-first by continually trying moves until it failed, then backtracking, but this turned out to be too slow. I have rewritten it to be breadth-first using a queue structure, but I'm having problems with memory management.
Here are the relevant parts:
int main(int argc, char *argv[])
{
...
int solved = 0;
do {
solved = solver(queue);
} while (!solved && !pblListIsEmpty(queue));
...
}
int solver(PblList *queue) {
state_t *state = (state_t *) pblListPoll(queue);
if (is_solution(state->pucks)) {
print_solution(state);
return 1;
}
state_t *state_cp;
puck new_location;
for (int p = 0; p < puck_count; p++) {
for (dir i = NORTH; i <= WEST; i++) {
if (!rules(state->pucks, p, i)) continue;
new_location = in_dir(state->pucks, p, i);
if (new_location.x != -1) {
state_cp = (state_t *) malloc(sizeof(state_t));
state_cp->move.from = state->pucks[p];
state_cp->move.direction = i;
state_cp->prev = state;
state_cp->pucks = (puck *) malloc (puck_count * sizeof(puck));
memcpy(state_cp->pucks, state->pucks, puck_count * sizeof(puck)); /*CRASH*/
state_cp->pucks[p] = new_location;
pblListPush(queue, state_cp);
}
}
}
free(state->pucks);
return 0;
}
When I run it I get the error:
ice(90175) malloc: *** mmap(size=2097152) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Bus error
The error happens around iteration 93,000.
From what I can tell, the error message is from malloc failing, and the bus error is from the memcpy after it.
I have a hard time believing that I'm running out of memory, since each game state is only ~400 bytes. Yet that does seem to be what's happening, seeing as the activity monitor reports that it is using 3.99GB before it crashes. I'm using http://www.mission-base.com/peter/source/ for the queue structure (it's a linked list).
Clearly I'm doing something dumb. Any suggestions?
Check the result of malloc. If it's NULL, you might want to print out the length of that queue.
Also, the code snippet you posted didn't include any frees...
You need to free() the memory you've allocated manually after you're done with it; dynamic memory doesn't just "free itself"

Resources