Проблема динамического перераспределения памяти - PullRequest
1 голос
/ 04 февраля 2010

Может кто-нибудь сказать мне, почему эта программа выдает ошибку отладки с сообщением
Msgstr "УЩЕРБ: после нормального блока (# 42) в 0x00430050". Сообщение генерируется в режиме без связи (ptr);
Я полагаю, что проблема связана с перераспределением памяти.

#include<stdio.h>
#include<stdlib.h>
#define DELTA 5

void include(int d,int* p,int n,int k,int flag);

void main(void)
{
 int *ptr;     
 int i=0,digit,koef=1;

 ptr=(int *)malloc(DELTA*sizeof(int));  
 fp=fopen("test.txt", "r")) 
 do{    

      fscanf(fp,"%d",&digit);  
      if (!(i % DELTA))
        koef++;
      if(i<(DELTA*koef))
        include(digit,ptr,i,koef,1);
      else
       include(digit,ptr,i,koef,2);
       i++;     
  }

}while(!feof(fp));     

free(ptr);      
}

 void include(int d,int* p,int n,int k,int flag)
 {
    switch(flag){
        case 1: *(p+n)=d;break;
        case 2: if((p=(int *)realloc(p,k*DELTA*sizeof(int)))==NULL){  
               printf("Error!Memory not allocated!\n");
               exit(1);
 }
       *(p+n)=d;break;
 }
}

Ответы [ 3 ]

6 голосов
/ 04 февраля 2010

Вы передаете ptr в свою функцию, а затем изменяете ее с помощью realloc. Вам нужно передать указатель на указатель для правильной работы.

Я предлагаю вам распечатать адрес, на который указывает указатель, до и после вызова, чтобы включить и до и после вызова в realloc. Это должно показать вам, что происходит или посмотреть на код ниже:

#include <stdio.h>

void a( int **ptrptr)
{
    printf("ptrptr = %p,  ptr = %p\n",ptrptr,*ptrptr) ;
    *ptrptr = (int*)realloc(*ptrptr, 10*sizeof(int)) ;
    printf("ptrptr = %p,  ptr = %p\n",ptrptr,*ptrptr) ;
}


int main(int argc, char **argv)
{
    int *ptr = malloc(5*sizeof(int)) ;
    printf("ptr = %p\n",ptr) ;
    a(&ptr) ;
    printf("ptr = %p\n",ptr) ;
    free(ptr) ;
    return 0;
}
1 голос
/ 04 февраля 2010

Вызов realloc() в include() может переместить блок. Вот почему realloc() возвращает указатель, чтобы сказать вам, куда он наконец поместил данные. Ваш код временно использует это значение (вы сохраняете его в локальной переменной p и используете его), но не можете передать его обратно вызывающей стороне. Функция main() сохраняет в своей локальной переменной ptr указатель на исходный блок и никогда не меняется.

Помните, что когда вы передаете аргумент функции, функция получает свою собственную копию. Здесь вы передаете содержимое ptr в качестве аргумента, и include() видит это значение как переменную с именем p, но этот p является только копией ptr. Изменения p не видны ptr.

Вы можете изменить include(), чтобы он возвращал новый указатель; что-то вроде:

int *include(int d,int* p,int n,int k,int flag)
{
    ...
    return p;
}

, а затем вызвать его с помощью:

ptr = include(digit, ptr, i, koef, 1);

, который является способом передачи нового значения указателя вызывающей стороне.

Примечания:

  • main() должен возвращать int, а не void.
  • Вам не нужно приводить возвращаемое значение malloc() или realloc(). Эти функции возвращают void *, который компилятор C успешно конвертирует в любой тип указателя без явного преобразования. Явное приведение - это способ сказать компилятору: «заткнись, я знаю, что делаю». Так как в этой ситуации компилятор в любом случае не говорил бы, приведение - просто трата пространства исходного кода. Кроме того, приведение может быть вредным в некоторых ситуациях, когда компилятор будет громко предупреждать: если malloc() введен с ошибкой, компилятор предположит, что он возвращает int, и предупредит об использовании int в качестве указателя; но актеры предотвратят это предупреждение.
  • Ваш код не компилируется, есть дополнительная закрывающая скобка.
0 голосов
/ 04 февраля 2010

Спасибо большое! Ваши замечания были действительно полезны. Проблема была в логике вызова функции include (). Я исправил это и на данный момент программа работает нормально. Моя функция теперь возвращает указатель на выделенный блок памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...