0
#include <stdio.h>
#include <stdlib.h>

void setZero (double **, int);

int main (void) {
        double *ptr = NULL;
        int i, size = 3;
        ptr = (double *)malloc(size * sizeof(double));
//*
        setZero(&ptr, size);
/*/
        // Sanity test
        for ( i = 0 ; i < size ; ++i ) {
                printf("index %d/%d\n", i, (size-1));
                ptr[i] = 0;  // NOT EXPLODING...
        }
//*/
        free(ptr);
        return 0;
}

void setZero (double **_ref_array, int _size) {
    int i;

    for ( i = 0 ; i < _size; ++i ) {
        printf("index %d/%d\n", i, (_size-1));
        *_ref_array[i] = 0;  // EXPLODING...
    }
}

1) Why is this not working?

2) What is a "Bus error 10"

P.S. I know better than to initialize an array this way, but this just happens to be a simple and clean example of an underlying concept that I'm not understanding...

Zak
  • 12,213
  • 21
  • 59
  • 105

2 Answers2

3

The dereference is happening after the index. I.e.

This says "Get the double pointer at index 'i', then set the value 0 to the memory at the address within that pointer."

*_ref_array[i] = 0; 

This says "Get the address of the array of doubles from _ref_array, than index off that address by i-doubles.

(*_ref_array)[i] = 0;
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • What's up with the "Bus error 10"? What does that message even mean? – Zak Nov 06 '12 at 02:58
  • @Zak Normally I would say it is a data alignment issue, but in this case it is possibly because you're walking off the end of your array. – WhozCraig Nov 06 '12 at 03:03
2

On the face of the code given, you don't need to pass the address of the pointer to the function. You should be using:

void setZero(double *ptr, int size)
{
    for (int i = 0; i < size; i++)
        ptr[i] = 0.0;
}

and:

setZero(ptr, size);

The trouble you've got is as WhozCraig says:

*_array_ref[i]

is interpreted as:

*(_array_ref[i])

instead of:

(*_array_ref)[i]

as you need it to be. The former is trampling up the stack; the latter is initializing the allocated memory.

If you really must pass a pointer to a pointer to the function, then you can either wrap parentheses around the dereferences, or you can assign a local pointer and use that normally, right up to the point where you need to make use of the double pointer to change the value in the calling function.

void setZero(double **ptr, int size)
{
    double *base = *ptr;
    for (int i = 0; i < size; i++)
    {
        base[i] = 0.0;
        // Or: (*ptr)[i] = 0.0;
    }
    ...presumably some code here needs to assign to *ptr...
    ...if there is no such code, there is no need of the double pointer...
}
Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • The code above is just a simple representation of a much more complex program that has far more requirements and parameters, and DOES need to have the array passed by reference (as I explained in my question). – Zak Nov 06 '12 at 03:00
  • AFAICS, that comment would be accurate if the `setZero()` function allocated memory, or needed to adjust the allocation (or, perhaps, stretching the point, if it needed to pass the location where the pointer to the array is stored to some other function, perhaps so that the pointer could be nulled after the array is released). Otherwise, it is a rather implausible claim. – Jonathan Leffler Nov 06 '12 at 03:03
  • 1
    I concur, Jonathan. I think there is a lot more going on in that function, but unless it can potentially reallocate or free that memory (i.e. have reason to modify the pointer) I would probably code it as you have above. double-indirection is something most regular engineers avoid if for no other reason than because they often don't even know what it *means*. I have to assume that there is an unexposed reason he's doing it this way, and just go with it. – WhozCraig Nov 06 '12 at 03:09
  • Yes, @WhozCraig is exactly right. I just had to make a simple program to illustrate the error I was getting, instead of trying to post 10K lines of code in here. Don't assume that I'm only working on a 10 line function, and for that matter you really shouldn't assume anything... – Zak Nov 06 '12 at 03:12