ograniczenia pamięci?

0

Witam.
Mam pewien problem. Pierwszy raz sie z czymś takim spotkałem i nie bardzo mam pomysł co sie dzieje.
Otóż pisze sobie programik (mniejsza z tym jaki). Mam tam troche struktur, klas, zmiennych itp. I teraz problem. Otóż w pewnym momencie po dodaniu dodatkowych zmiennych (tablic typu char) program nagle zaczyna sie sypać. Dodam, że jedyną zmianą którą robie jest dodanie tylko i wyłącznie dodatkowej zmiennej w strukturze. Nie jest ona nigdzie wykorzystywana (czytana, zapisywana czy coś). Po wykomentarzowaniu nowej zmiennej program śmiga... Czy to możliwe, że mam po prostu za dużo zamiennych, bajzel w pamięci czy coś w tym stylu?

0

Pokaż kod to może coś się da z tym zrobić.

0

a mi to wygląda na to, że coś kompilatorowi się pomieszało. Np BCB 6 był taki problem, że czasami po jakieś modyfikacji, jeden moduł nie był re-kompilowany mimo, że powinien.
Moja rada, zrób czystego builda.
Wymuś kompilację wszystkiego od początku (odpowiednia opcja lub wykasować pewne pliki kompilacji).
Inny powód błędu to, że masz gdzieś starą kopię nagłówka i jeden moduł używa nowej wersji a inny starej.

0

Ad 1: Moge kod pokazać, nie wiem tylko na ile on będzie czytelny, bo uzbierało sie już kilkaset linijek kodu
Ad 2:używam Deva. Build od zera nic nie daje...

Może póki co fragmenty, wg kluczowe:

Struktury:

struct tMat
{
     int texID;  
     unsigned int R,G,B;
     char szName[255];
     char TexFile[255];     
};

struct tObject
{
   int numVert;
   int numFaces;    
   char name[255];
   tVector3 *vertex;
   tVector2 *texCoord;
   tVector3 *normals;
   tFace *faces;
};

i jedyny moment, w którym wykorzystuje je:

case MATERIAL:                                        //zawiera informacje o materiałach
          model -> numMaterial++;
          tMat mat;
          readMaterialChunk(&mat, tmpChunk);           
          model -> vMaterials.push_back(mat);
          break;      
  case OBJECT:                                          //zawiera informacje o obiektach
          model -> numObject++;
          tObject obj;
          readObjectChunk(&obj, tmpChunk);
          model -> vObjects.push_back(obj);
          break;       

Dodam, że struktura tMat sprawia problemy, tObject działa wszystko. Po wykomentarzowaniu zmiennych znakowych wszystko działa poprawnie.
w funkcji readMaterialChunk nie korzystam jeszcze w żaden sposób z obiektu mat.
i teraz moment, w którym zdaje sie program wykrzaczać:

void C3dsl::readVertex(tObject *object, tChunk *chunk)
{
  chunk -> bytesRead += fread(&(object -> numVert),1,2,filePTR);
  
  std::cout<<"    VERTEX: "<<object -> numVert<<std::endl; 
    
  object -> vertex = new tVector3[object -> numVert];
  
  for(int i=0;i<object -> numVert;i++)
  {
     chunk -> bytesRead += fread(&object -> vertex->x,1,4,filePTR);     
     chunk -> bytesRead += fread(&object -> vertex->y,1,4,filePTR); 
     chunk -> bytesRead += fread(&object -> vertex->z,1,4,filePTR); 
     
     //std::cout<<object -> vertex ->x<<" "<<object -> vertex ->y<<" "<<object -> vertex ->z<<std::endl;
  }

po zmianach program źle wczytuje liczbe numVert... Powinna być ona 50, natomiast program wczytuje ją jako 4063282.
w razie czego moge udostępnić całość kodu.

BTW, jakby ktoś pytał, to program ma wczytywać i przetwarzać dane z plików *.3ds

0

Źle czytasz przez fread :

chunk -> bytesRead += fread(&object -> vertex->x,1,4,filePTR);
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
#include <stdio.h>
size_t fread(void *ptr, ile_razy,rozmiar_danej_w_bajtach, FILE *stream);
0
MarekR22 napisał(a)

a mi to wygląda na to, że coś kompilatorowi się pomieszało. Np BCB 6 był taki problem, że czasami po jakieś modyfikacji, jeden moduł nie był re-kompilowany mimo, że powinien.
Moja rada, zrób czystego builda.
Wymuś kompilację wszystkiego od początku (odpowiednia opcja lub wykasować pewne pliki kompilacji).
Inny powód błędu to, że masz gdzieś starą kopię nagłówka i jeden moduł używa nowej wersji a inny starej.

FYI: VS2001-2005 tez tak mialy. na VS2008/2010 jeszcze szczesliwie nie trafilo mi sie.

//Na VS2008 przy większym projekcie raz mi się zdarzyło, że po updacie SVN'em linker krzyczał, że mu brakuje definicji których już nie było w kodzie. Dopiero pełny rebuild pomógł - adf88

0

Źle czytasz przez fread :

Chyba jednak dobrze, w każdym razie, po zmianach program sie wiesza i nie wczytuje nic

0

A , bo strzeliłem byka , powinno być :

chunk -> bytesRead += fread(&(object -> vertex->x),1,sizeof(object -> vertex->x/*lub typ */),filePTR);
chunk -> bytesRead += fread(&(object -> numVert),1,sizeof(int),filePTR);

masz przydzieloną pamięć dla ' tVector3 *vertex;' ?

0

pamięć jest przydzielona.

co do tego fread'a to "stara" wersja zdaje sie działać poprawnie. Po prostu wczytuje poprawnie to co ma wczytywać (sprawdzone).

Co do problemu ze wczytywaniem liczby numVert to znika on gdy wykomentarzujemy 2 zmienne typu char ze struktury tMat. I właśnie to jest dla mnie magiczne jaki jest tu w ogóle związek... (w kodzie nijak jedno nie jest powiązane z drugim).

W razie czego moge zamieścić całość kodu, tylko, że jest to kilkaset już lini, więc nie wiem czy ktokolwiek będzie miał ochote na choćby pobieżne przejrzenie

0

Bez potrzeby , myślę że wystarczy zamieścić fragmenty dotyczące :
1.)tworzenia tObject object do którego odwołujke się fun readVertex (jak jest tworzony).
2.)tworzenia tVertex dla object .
Og. dla 2 i 3 jak przydzielasz pamięć ?
3.)formatu pliku tzn. Jak to jest wszystko zapisane , ile bajtów zajmuje poszczególna
zmienna w pliku i gdzie się znajduje czyli opis formatu pliku .
Event daj gdzieś plik do pobrania .
4.) Podaj Definicję tVector3,tVector2,tFace ( dla pewności )
5.) Kod funkcji readMaterialChunk(&mat, tmpChunk);

Zachowanie w Dev jakie opisałeś występuje przy przypadkowym nadpisywaniu
danych i objawia się właśnie po dodaniu dowolnej zmiennej do struct lub innego bloku danych .

0

czytasz tylko dwa bajty do numVert zamiast 4 (int), więc te dwa górne zostają przypadkowe.

4063282 = 0x003E0032
i tu się zgadza: 50 = 0x0032, natomiast 0x003E to przypadkowe śmieci...

Jeśli chcesz nadal czytać tylko 2 bajty to musisz sam zerować te pozostałe, albo tak:
numVert = 0;
read ...

0

Ad 1)
To już jest:

case OBJECT:                                          //zawiera informacje o obiektach
          model -> numObject++;
          tObject obj;
          readObjectChunk(&obj, tmpChunk);
          model -> vObjects.push_back(obj);
          break;

Tutaj jest tworzony obiekt tObject dodawany do kontenera i potem jest przekazywany przez kilka funkcji po kolei aż dojdzie do readVertex.

Ad 2)
To też już jest:

object -> vertex = new tVector3[object -> numVert];

gdzie numVert jest wczytywaną z pliku ilością wierzchołków

Ad 3)
http://www.martinreddy.net/gfx/3d/3DS.spec

Aczkolwiek z góry mówie, że format jest nieco magiczny i 3/4 danych niepotrzebnych

struct tVector3
{
       float x,y,z;
};

struct tVector2
{
  float u,v;     
};

struct tFace
{
 unsigned int verIndex[4];   
};

Ad 5)
Nie wiem czy to coś zmieni, bo na dobrą sprawe ta funkcja jeszcze nic nie robi.

void C3dsl::readMaterialChunk(tMat *material, tChunk *chunk)
{
     skipChunk(chunk);
}

Po prostu przechodzimy w pliku dalej.

0
fi napisał(a)

czytasz tylko dwa bajty do numVert zamiast 4 (int), więc te dwa górne zostają przypadkowe.

4063282 = 0x003E0032
i tu się zgadza: 50 = 0x0032, natomiast 0x003E to przypadkowe śmieci...

Jeśli chcesz nadal czytać tylko 2 bajty to musisz sam zerować te pozostałe, albo tak:
numVert = 0;
read ...

Hmm, w specyfikacji formatu powinienem czytać 2 bajty (unsigned int). Faktycznie w programie zrobiłem z tego zwykłego inta.

Faktycznie, wyzerowanie zmiennej pomogło, wielkie dzięki za pomoc :)

Tylko jedno mnie cały czas zastanawia. Jaki wpływ na te "śmieci" w numVert miały zmienne w strukturze tMat, zupełnie nie powiązane ze sobą...

0

vetrex to jest tablica :
object -> vertex = new tVector3[object -> numVert];
Więc zamiast :
....bytesRead += fread(&(object -> vertex->x),1,4,filePTR);
powinno być:
.....bytesRead += fread(&(object -> vertex[i].x),1,4,filePTR);

0

Może to dziwne, ale to nie działa....
Po zmianach wszystkie wierzchołki mają dokładnie takie same współrzędne, natomiast teraz nie...
Co śmieszniejsze podobny kod jest przy wczytywaniu face'ów, tylko, że tam już zastosowałem "poprawne" wczytywanie i działa..

void C3dsl::readFaces(tObject *object, tChunk *chunk)
{   
  object ->  numFaces = 0;  
  chunk -> bytesRead += fread(&(object -> numFaces),1,2,filePTR);              //wczytujemy ilość face'ów
  std::cout<<"    FACES: "<<object -> numFaces<<std::endl;
   
  object -> faces = new tFace[object -> numFaces];
  
  for(int i=0;i<object -> numFaces;i++)
  {
   object -> faces[i].verIndex[0]=0;                      //wpierw zerujemy zmienne, żeby nie było rzadnych śmieci
   object -> faces[i].verIndex[1]=0;                      //tak bezpieczniej przy wczytywaniu 2 bajtów do 4-bajtowych zmiennych         
   object -> faces[i].verIndex[2]=0;
   object -> faces[i].verIndex[3]=0;      
   chunk -> bytesRead += fread (&object -> faces[i].verIndex[0],1,2,filePTR);        //wczytujemy po kolei indexy oraz 4 zmienną która coś tam robi
   chunk -> bytesRead += fread (&object -> faces[i].verIndex[1],1,2,filePTR);
   chunk -> bytesRead += fread (&object -> faces[i].verIndex[2],1,2,filePTR);
   chunk -> bytesRead += fread (&object -> faces[i].verIndex[3],1,2,filePTR); 
    
    //std::cout<<object -> faces[i].verIndex[0]<<" "<<object -> faces[i].verIndex[1]<<" "<<object -> faces[i].verIndex[2]<<" "<<object -> faces[i].verIndex[3]<<std::endl;      
  }
0
gooziec napisał(a)

Hmm, w specyfikacji formatu powinienem czytać 2 bajty (unsigned int). Faktycznie w programie zrobiłem z tego zwykłego inta.

unsigned int ma taki sam rozmiar jaki int (signed).

[unsigned] short, ma 2 bajty na 32 bitowych procesorach (albo raczej kompilatorach...).
Zwykle definiujesz sobie typ: WORD, albo uint16 aby rozmiar był niezależny od kompilatora.

gooziec napisał(a)

Tylko jedno mnie cały czas zastanawia. Jaki wpływ na te "śmieci" w numVert miały zmienne w strukturze tMat, zupełnie nie powiązane ze sobą...

Deklarujesz potem te struktury jako zmienne lokalne, więc one leżą normalnie na stosie.
Liczby na stosie zależą od tego co wcześnie tam leżało - inne funkcje również tam trzymają swoje zmienne lokalne do których coś zapisują, potem te zmienne znikają (po wyjściu z funkcji), ale stos nie znika, przesuwa się tylko wskaźnik wierzchołka stosu, więc to co tam było zapisane zostaje.

int stosuj()
{ int x[10];

 x[9] = 1; x[8] = 2; // stos jest odwrócony...
 
 return 0;
}

int czytaj()
{
  int y;
  return y; // wartość wcześniej zapisana na stosie
}

// teraz wywołujesz gdzieś te funkcje tak:

stosuj(); 
int q = czytaj(); // q = 1, 

wynik może zależeć oczywiście od kompilatora, ale bez optymalizacji powinno tak wyjść.

Ten Twój kod to w ogóle jakaś totalna masakra i improwizacja - same błędy i 90% redundancji.
Po co liczysz tam te przeczytane bajty... dla rozrywki?
Po co czytasz te wektory w pętlach? Takie coś ładujesz jednym strzałem:
readf(tablica, sizeof(sztuki), liczba_sztuk, ...).

Zero kontroli błędów in/out... normalnie szkoda gadać. :-[

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