"reallocowanie" tablicy dwuwymiarowej

0

Witam.

Mam problem z realokacją pamięci za pomocą funkcji realloc dla tablicy dwuwymiarowej. W tablicy zapisują się liczby i po przekroczeniu rozmiaru funkcja powinna realokować pamięć. Chcę zrobić tak, że można zarówno dodawać nowe wiersze jak i zwiększać rozmiar danego wiersza.

 if(i==rozmiar){
		  
		  int ni_size = ++rozmiar * sizeof(int);
		  printf("void* ptr = realloc(%p, %d);\n", tab_wyn, ni_size);
		  void *ptr = realloc(*tab_wyn, ni_size);
		  if (!ptr) 
		  {
		    free(tab_wyn);
		    perror("realloc");
		    return EXIT_FAILURE;
		  }
		  *tab_wyn = ptr;
		  
		}  
		
		if(m==rozmiar){
		  
		  int nm_size = ++rozmiar * sizeof(int);
		  printf("void* ptr = realloc(%p, %d);\n", *tab_wyn, nm_size);
		  void* ptr = realloc(tab_wyn, nm_size);
		  if (!ptr) 
		  {
		    free(tab_wyn);
		    perror("realloc");
		    return EXIT_FAILURE;
		  }
		  tab_wyn = ptr;
		  
		}

Czy ktoś wie czy to jest dobra koncepcja? Nie działa mi ten kod - wywala Segmentation Fault. :/ Z góry dziękuję za pomoc ;)

0

nie pokazałeś czym jest tab_wyn

0

"mallokuje" pamieć tak:

  int **tab_wyn = malloc(rozmiar * sizeof *tab_wyn);
    *tab_wyn = malloc(rozmiar * rozmiar * sizeof **tab_wyn);
    
    if ((!tab_wyn)||(!*tab_wyn)) 
    {
	perror("malloc");
	return EXIT_FAILURE;
    }
    
    
    for (i = 1; i<rozmiar; ++i) {
	tab_wyn[i] = tab_wyn[0] + (i * rozmiar);
    }
 
    for (i = 0; i<rozmiar; ++i) {
      for (j = 0; j<rozmiar; ++j) {
	tab_wyn[i][j] = (i+1)*(j+1);
      }
    }

"tab_wyn" jest wskaźnikiem na wskaźnik

0

Jak zwiększyłeś ilość wierszy to dla tych nowych wierszy musisz przydzielić pamięć.
Pamiętaj że w tych nowych komórkach (wskaźnikach na nowe wiersze) mogą być śmieci.

0

No właśnie próbuję alokować pamięć zarówno pod nowe wiersze jak i pod większą długość wierszy. Tylko nie wiem gdzie robię błąd. Co powinienem zrobić, żeby sie pozbyć "smieci"?

0

Po pierwsze powinieneś trzymać ten wskaźnik razem z rozmiarami, np:

struct TB { int **tb; unsigned rx,ry; };
TB t={NULL,0,0};

wtedy możesz wykorzystać to że realloc działa jednocześnie jako malloc oraz free.

void resize(TB *t,unsigned rx,unsigned ry)
  {
   unsigned y;
   if(t->ry!=ry)
     {
      if(t->ry>ry) for(y=ry;y<t->ry;++y) free(t->tb[y]);
      t->tb=(int**)realloc(t->tb,ry*sizeof(int*));
      if(t->ry<ry)
         {
          if(t->rx!=rx) for(y=t->ry;y<ry;++y) t->tb[y]=0;
          else for(y=t->ry;y<ry;++y) { t->tb[y]=(int*)malloc(rx*sizeof(int)); /*plus ewentualnie memset*/ }
         }
      t->ry=ry;
     }
   if(t->rx!=rx)
     {
      for(y=0;y<ry;++y) { t->tb[y]=(int*)realloc(t->tb[y],rx*sizeof(int));  /*plus ewentualnie memset*/ }
      t->rx=rx;
     }
  }

Ta funkcja będzie ci ładnie zwiększać i zmniejszać, rozmiar tablicy.

0
_13th_Dragon napisał(a)

Po pierwsze powinieneś trzymać ten wskaźnik razem z rozmiarami, np:

struct TB { int **tb; unsigned rx,ry; };
TB t={NULL,0,0};

wtedy możesz wykorzystać to że realloc działa jednocześnie jako malloc oraz free.

void resize(TB *t,unsigned rx,unsigned ry)
  {
   unsigned y;
   if(t->ry!=ry)
     {
      if(t->ry>ry) for(y=ry;y<t->ry;++y) free(t->tb[y]);
      t->tb=(int**)realloc(t->tb,ry*sizeof(int*));
      if(t->ry<ry)
         {
          if(t->rx!=rx) for(y=t->ry;y<ry;++y) t->tb[y]=0;
          else for(y=t->ry;y<ry;++y) { t->tb[y]=(int*)malloc(rx*sizeof(int)); /*plus ewentualnie memset*/ }
         }
      t->ry=ry;
     }
   if(t->rx!=rx)
     {
      for(y=0;y<ry;++y) { t->tb[y]=(int*)realloc(t->tb[y],rx*sizeof(int));  /*plus ewentualnie memset*/ }
      t->rx=rx;
     }
  }

Ta funkcja będzie ci ładnie zwiększać i zmniejszać, rozmiar tablicy.
Zrozumiałem z kodu, że ta funkcja dowolnie zmienia rozmiar tablicy przyjmując jako argumenty wskaźnik na tab_wyn i rozmiary o które chcemy zwiększać ową tablicę. Dane trzymamy w strukturze, którą wcześniej zdefiniowałem. W main() tworzę strukturę o elementach struct TB t={NULL,0,0} . Później realokuję tab_wyn o rx i ry (argumenty funkcji "resize"). Niestety znowu mam segmentation fault tylko teraz już w ogóle nie wpisuje liczb do tablicy. Wcześniej wpisywało do określonego rozmiaru z wykorzystaniem malloc. Dobrze Cię zrozumiałem "_13th_Dragon" ?

0

Segmentation fault był spowodowany czym innym. Poprawiłem i teraz mam jakieś wycieki pamięci najpierw na funckji free() a potem na realloc(). Mówię o funkcji napisanej przez "Trzynastego Smoka". Co może być przyczyną?

0

Kod, który wykorzystuje do operacji z tab_wyn:

struct TB { int **tb; unsigned rx,ry; };



void resize(struct TB *t,unsigned rx,unsigned ry)
{
   unsigned y;
   
   if(t->ry!=ry)
     {
      if(t->ry>ry) for(y=ry;y<t->ry;++y) free(t->tb[y]);
      t->tb=(int**)realloc(t->tb,ry*sizeof(int*));
      if(t->ry<ry)
         {
          if(t->rx!=rx) for(y=t->ry;y<ry;++y) t->tb[y]=0;
          else for(y=t->ry;y<ry;++y) { t->tb[y]=(int*)malloc(rx*sizeof(int)); /*plus ewentualnie memset*/ }
         }
      t->ry=ry;
     }
     
   if(t->rx!=rx)
     {
      for(y=0;y<ry;++y) { t->tb[y]=(int*)realloc(t->tb[y],rx*sizeof(int));  /*plus ewentualnie memset*/ }
      t->rx=rx;
     }
}

w main(){
 int **tab_wyn = malloc(rozmiar * sizeof *tab_wyn);
    *tab_wyn = malloc(rozmiar * rozmiar * sizeof **tab_wyn);
   
    struct TB t={NULL,0,0};
    
    rozmiar=rx=ry;
    if ((!tab_wyn)||(!*tab_wyn)) 
    {
	perror("malloc");
	return EXIT_FAILURE;
    }
    
    
    for (i = 1; i<rozmiar; ++i) {
	tab_wyn[i] = tab_wyn[0] + (i * rozmiar);
    }

resize(*tab_wyn,rx,ry); 

} 
0
int main()
  {
    struct TB t={NULL,0,0};
    unsigned rozmiar=10,y,x;

    resize(&t,rozmiar,rozmiar);
    for(y=0;y<rozmiar;++y) for(x=0;x<rozmiar;++x) t.tb[y][x]=(y+1)*(x+1);
    for(y=0;y<rozmiar;++y)
      {
       for(x=0;x<rozmiar;++x)
         {
          printf("%d",t.tb[y][x]);
         }
       printf("\n");
      }
    resize(&t,0,0);  
    return 0;
  }
0

Przyznam, że nadal nie rozumiem. Robię tak:

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

struct TB { int **tb; unsigned rx,ry; };



void resize(struct TB *t,unsigned rx,unsigned ry)
{
   unsigned y;
   
   if(t->ry!=ry)
     {
      if(t->ry>ry) for(y=ry;y<t->ry;++y) free(t->tb[y]);
      t->tb=(int**)realloc(t->tb,ry*sizeof(int*));
      if(t->ry<ry)
         {
          if(t->rx!=rx) for(y=t->ry;y<ry;++y) t->tb[y]=0;
          else for(y=t->ry;y<ry;++y) { t->tb[y]=(int*)malloc(rx*sizeof(int)); /*plus ewentualnie memset*/ }
         }
      t->ry=ry;
     }
     
   if(t->rx!=rx)
     {
      for(y=0;y<ry;++y) { t->tb[y]=(int*)realloc(t->tb[y],rx*sizeof(int));  /*plus ewentualnie memset*/ }
      t->rx=rx;
     }
}



main(){

    struct TB t={NULL,0,0};
    unsigned rozmiar=10,y,x;
 
    resize(&t,rozmiar,rozmiar);
    for(y=0;y<1000;++y){ for(x=0;x<10000;++x) {
	if((rozmiar==y)||(rozmiar==x)){
	resize(&t,rozmiar,rozmiar);
	}t.tb[y][x]=(y+1)*(x+1);
    }}
   
    //for(y=0;y<rozmiar;++y) for(x=0;x<rozmiar;++x) t.tb[y][x]=(y+1)*(x+1);
    resize(&t,rozmiar,rozmiar);
    printf("rozmiar: %d\n",rozmiar);
    
    
    for(y=0;y<rozmiar;++y)
      {printf("Kolejny wiersz\n\n");
       for(x=0;x<rozmiar;++x)
         {
          printf("%d",t.tb[y][x]);
         }
       printf("\n");
      }
    resize(&t,0,0);  
    return 0;


}

I dalej mam segmentation fault.:/

0

Ok już problem rozwiązałem. Trzeba było zwiększać "rozmiar" przed każdym wywołaniem funkcji resize();

Dziękuję za pomoc :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1