views:

131

answers:

2

I have a 2D dynamic array. I enter a line of 0's after line which has a biggest number:

void InsertZero(int **a, int pos){
    int i, j;
    a = (int**)realloc(a, n * sizeof(*a));
    a[n-1] = (int*)calloc(n, sizeof(**a));
    d = 0;
    for(i = n-1; i > pos; i--){
        for(j = 0; j < n; j++){
            a[i][j] = a[i-1][j];
            printf("%d ", a[i][j]);
        }
    }

    for(i = 0; i < n; i++){
        a[pos][i] = 0;
    }
}

If i make a size of array 3, 5, 7, 9, ... it works correctly. But if a number of lines is 2, 4, 6, ... , it is an access violation error, when i try to print my array:

void Print(void){
    int i, j;
    for(i = 0; i < (n-d); i++){
        for(j = 0; j < n; j++){
            printf("%d\t", arr[i][j]);
        }
        printf("\n");
    }
}

code: http://codepad.org/JcUis6W4

A: 

Looking at this I cannot make sense of.... Look at comment 1, you have n set somewhere to realloc a block of memory which a is of type int ** - a double pointer, how are you calling this function? Secondly, comment 2, Why did you call calloc when the realloc on a double pointer was called previously...? Assume n has value of 5, then, realloc is called on double pointer a, meaning a[0][1]..a[4][1], now calloc is called thus a[4] has a new block of memory...

void InsertZero(int **a, int pos){
    int i, j;

    /* 1. */
    a = (int**)realloc(a, n * sizeof(*a)); 
    /* Bzzzzt....if realloc failed, a gets overwritten! */

    /* 2. */
    a[n-1] = (int*)calloc(n, sizeof(**a));

    /* 3. */
    d = 0;

    /* 4. */
    for(i = n-1; i > pos; i--){
        for(j = 0; j < n; j++){
            a[i][j] = a[i-1][j];
            printf("%d ", a[i][j]);
        }
    }

    for(i = 0; i < n; i++){
        a[pos][i] = 0;
    }
}

Comment 3, what is d used for - useless variable? Comment 4, you are under the presumption that the block of memory has array subscripts [0][0] to [4][4] if n had a value of 5!

Can you clarify all this?

Edit: Looking at it again... it is likely that a got overwritten when the call to realloc failed! I recommend this section of code to counteract this

    int **tmpA;
    tmpA = (int**)realloc(a, n * sizeof(*a)); 
    if (tmpA != NULL){
        a = tmpA;
        ....
        a[n-1] = (int*)calloc(n, sizeof(**a));
        for(i = n-1; i > pos; i--){
            .... 
        }

        for(i = 0; i < n; i++){
            ....
        }
    }   
tommieb75
1) "a" have "n-1" elements, i make "n" elements with realloc2)a[n-1] i call a new memory.3) i have a "n-1" row and "n" cols. "d"=1, (n-d) is (n-1). When I add a new row, i make d=0 and "n" rows and "n" cols4) i know that
Sergey Gavruk
A: 

In your function InsertZero you have a local variable a. This local variable is initially set with a the address of a pointer to an integer (you probably wanted the address of a pointer to an array of integers, i.e. int ***a).

When you call realloc you are assigning your local copy of a a pointer to a block of memory, however once you have finished with your function it is entirely possible for your local copy of a to be pointing somewhere different to the rest of your program. You probably wanted to say *a = (int **)realloc(a, n * sizeof(int *));.

Dangerously, you're using n which isn't passed to your function. It appears you've made the assumption that n is going to be 1 bigger than the previous size of the array - otherwise your call to calloc is superfluous and you are just rotating the array letting the last element drop off as a memory leak.

Let's use a simpler example with no arrays, no dimensions. Let's say you wanted to create a function:

void make_me_a_pointer( int **mynumber ) {
    *mynumber = (int *)malloc( sizeof(int) );
    **mynumber = 7; /* assign the value 7 to my allocated memory */
}

int main( void ) {
    int *demoint;
    make_me_a_pointer( &demoint );
    printf( "Magic num is %d\n", *demoint );
}

However in your case you merely assigned a = realloc... and thus never communicated the new address of a outside your function.

PP
I have a "Magic num is 7"
Sergey Gavruk
Try writing some simple test code, Sergey, to allow yourself to familiarise with pointers before jumping into the deep end with multi-dimensional arrays and memory allocation...
PP
PP has the right idea. In Sergey's program, arr, n, and d are globals. arr is assigned the pointer to the array of pointers allocated in CreateArray(), but as PP points out, later when you realloc, you never assign the result to the global arr. I'm guessing that when n is even, realloc has to move the block elsewhere, so arr winds up pointing to memory that has been freed.You must check the return from *alloc. This call can fail and return NULL. You program should handle that, perhaps by ending with an error message. Use meaningful variable names, and avoid the use of globals.
Fred