2010-02-04 3 views
1

Может ли кто-нибудь сказать мне, почему эта программа дает ошибку отладки с сообщением
«ПОВРЕЖДЕНИЕ: после обычного блока (# 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; 
} 
} 
+1

Вы должны уменьшить код до некоторой небольшой версии, которая вызывает ошибку. Как это довольно сложно. –

+0

Realloc не должен вызывать такую ​​проблему, но я тоже столкнулся с проблемой при ее использовании. В общем, я предпочитаю делать что-то вроде этого: int * tmp = malloc (new_size); memcpy (tmp, ptr, old_size); Бесплатно (ptr); ptr = tmp; Не знаю, если это вообще полезно здесь ... – mingos

ответ

6

Вы передаете функцию ptr в свою функцию и затем меняете ее с помощью 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

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

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

Смежные вопросы