Неизвестная ошибка в памяти в C - PullRequest
0 голосов
/ 22 марта 2010

У меня есть 2D динамический массив.Я ввожу строку из 0 после строки, которая имеет наибольшее число:

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;
    }
}

Если я сделаю размер массива 3, 5, 7, 9, ... он работает правильно.Но если количество строк равно 2, 4, 6, ..., это ошибка нарушения доступа, когда я пытаюсь напечатать свой массив:

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");
    }
}

код: http://codepad.org/JcUis6W4

Ответы [ 2 ]

0 голосов
/ 22 марта 2010

В вашей функции InsertZero у вас есть локальная переменная a. Эта локальная переменная изначально имеет адрес указателя на целое число (вы, вероятно, хотели адрес указателя на массив целых чисел, т.е. int ***a).

Когда вы вызываете realloc, вы присваиваете локальной копии a указатель на блок памяти, однако, как только вы закончите с вашей функцией, вполне возможно, что ваша локальная копия a будет указывать где-то отличается от остальной части вашей программы. Вы, вероятно, хотели сказать *a = (int **)realloc(a, n * sizeof(int *));.

Опасно, вы используете n, который не передается вашей функции. Похоже, вы сделали предположение, что n будет на 1 больше, чем предыдущий размер массива - в противном случае ваш вызов calloc будет излишним, и вы просто вращаете массив, позволяя последнему элементу выпадать как утечка памяти.

Давайте использовать более простой пример без массивов, без измерений. Допустим, вы хотите создать функцию:

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 );
}

Однако в вашем случае вы просто присвоили a = realloc ... и таким образом никогда не передавали новый адрес a вне вашей функции.

0 голосов
/ 22 марта 2010

Глядя на это, я не могу понять ... Посмотрите на комментарий 1, у вас n установлен где-то на realloc блок памяти, который a имеет тип int ** - двойной указатель, как вы вызываете эту функцию? Во-вторых, комментарий 2. Почему вы вызывали calloc, когда ранее вызывался realloc для двойного указателя ...? Предположим, что n имеет значение 5, тогда realloc вызывается по двойному указателю a, что означает a[0][1]..a[4][1], теперь calloc вызывается, таким образом a[4] имеет новый блок памяти ...

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;
    }
}

Комментарий 3, для чего используется d - бесполезная переменная? Комментарий 4, вы предполагаете, что блок памяти имеет индексы массива от [0][0] до [4][4], если n имеет значение 5!

Можете ли вы уточнить все это?

Редактировать: Глядя на это снова ... вполне вероятно, что a был перезаписан при сбое вызова realloc! Я рекомендую этот раздел кода, чтобы противодействовать этому

    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++){
            ....
        }
    }   
...