0

I have a function in C (my_malloc is just a wrapper with testing if the allocation was suscessful):

#define MAXIMUM {                   \
    int value = 0;                  \
    for (int i = 0; i < n; i++) {   \
        if (value < (*numbers)[i]) {\
            value = (*numbers)[i];  \
        }                           \
    }                               \
    return value;                   \
}

int maximum1(int n, int **numbers) MAXIMUM;

int maximum2(int n, int (*numbers)[n]) MAXIMUM;

Then I call it like this (n in some number of elements in an array):

int *numbers = my_malloc(n * sizeof(int *));
// array numbers is filled
int value = maximum1(n, &numbers);

and

int numbers[n];
// array numbers is filled
int value = maximum2(n, &numbers);

Can something be done with it to make it cleaner? I would like to only have one maximum function.

Here is where all the problems started:

int numbers[n]; 
//int *numbers = my_malloc(n * sizeof(int *)); 
// There is no way, I could find, to use dynamically allocated array...
// the pointer of numbers array changes after calling MPI_Recv...
// only a fixed array worked here, otherwise exactly two  
// elements are received all the time...meh 

//printf("address before: %p\n", numbers); 
MPI_Recv(numbers, n, MPI_INT, 0, 0, MPI_COMM_WORLD, &status); 
//printf("address after: %p\n", numbers); //<-- changing when using malloc
value = maximum2(n, &numbers);


// Copying contents of the static array to dynamically allocated 
// one works (just maximum1 is required)
//int *numbers = my_malloc(n * sizeof(int *)); 
//for (i = 0; i < n; i++)  
    //numbers[i] = numbers_old[i]; 
//value = maximum1(n, &numbers);

The uncommented is current working state. The comments pose two working solutions:

  1. creating fixed array and copying its contents over to dynamically allocated one (just one maximum funciton is then needed but it is a stupid solution)
  2. using just the fixed array with maximum2 funciton

EDIT

After hours of headache it does magically appear to be working correctly, without the apparent change, so I am not sure what is going on....

The my_malloc function:

void *my_malloc(size_t size) {
    void *p = malloc(size);
    if (p == NULL) {
        printf("Memory allocation unsuccessful.\n");
        exit(EXIT_FAILURE);
    }   
    return p;
}
peter.babic
  • 3,214
  • 3
  • 18
  • 31
  • 1
    sizeof(int * ) is probably not the same as sizeof(int)? MPI_INT would expect n*sizeof(int), I think. – haraldkl Oct 21 '15 at 01:10
  • Helo @haraldkl, i think it is the same. I have spent hours resolving this, but now it looks like it is working both ways...with or without the asterisk. Very strange. – peter.babic Oct 21 '15 at 01:15

1 Answers1

3

First, you have a problem with your memory allocation: assuming my_malloc() is just, as you said, "a wrapper with testing if the allocation was successful", then you would expect something like int *numbers = my_malloc(n * sizeof(int)); , not like int *numbers = my_malloc(n * sizeof(int *));. The former is correct while the latter would (un)luckily work only on machines where sizeof(int) == sizeof(int*). I have the feeling that there originates all of your problems.

Then I don't understand why you create this cumbersome MAXIMUM macro and two different functions maximum1() and maximum2. What would be wrong with this single function?

int maximum(int n, int *numbers) {
    int value = 0;
    for (int i = 0; i < n; i++) {
        if (value < numbers[i]) {
            value = numbers[i];
        }
    }
    return value;
}

This should work just fine, should numbers be dynamically or statically allocated.

Try fixing these and you'll have make progresses towards getting a more reliable code.


EDIT: I forgot to mention that this new maximum() function should be called this way:

int numbers[n]; // works also with: int *numbers = my_malloc(n * sizeof(int));
int value = maximum(n, numbers);
Gilles
  • 9,269
  • 4
  • 34
  • 53
  • Hello, I have added the `my_malloc` function to the original post. You can see there is not much in it. The thing is, your proposed function requires input `int *numbers` that none of my calls would match . It is still working for me now, so I am voting for close. – peter.babic Oct 21 '15 at 09:11
  • @delmadord Indeed, there's not much in it. But that confirms that it should be called with `sizeof(int)` not `sizeof(int*)`. And if you don't see why this is different, nor why the proposed version of `maximum()` works with either dynamic or static memory allocation, and if furthermore you are not interested in learning it, then sure, go on a delete your question. – Gilles Oct 21 '15 at 09:52
  • It does not change the output if I change the `sizeof(int *)` to `sizeof(int)` meaning that the size of the `int` is the same as size of pointer to `int` as someone noted and if I understand it correctly. The problem is that it started to work and I cannot decipher, even from previous commit what did I change to make it work. – peter.babic Oct 21 '15 at 10:30
  • This looks suspiciously like a latent bug in the code: it looks like it works, but that is just by chance... Changing something seemingly completely unrelated somewhere else might suddenly make it to fail. So I'd encourage you to switch as many debugging information on as possible at your compiler's level, and to run the code through a memory debugger. If on Linux, [valgrind](http://valgrind.org) can do a great job in tracking down memory errors. – Gilles Oct 21 '15 at 10:42
  • Thank you, the edit helped, now it is allright. I have removed the asterisks from sizeof as you and @heraldkl suggested. I will study more on the topic, originally I got it from the [book](https://books.google.sk/books?id=vrbzAgAAQBAJ&dq=k+n+king+c+programming+modern+approach+2nd+edition&hl=en&sa=X&ved=0CB4Q6AEwAGoVChMI5rCvhLLTyAIV4yxyCh1MOwaw) – peter.babic Oct 21 '15 at 10:52
  • The **valgrind** looks interesting, thank you for this too. – peter.babic Oct 21 '15 at 11:00