Avatar billede _henrik Nybegynder
31. juli 2006 - 23:33 Der er 17 kommentarer og
2 løsninger

linker fejl i c++ program

Jeg er ved at skrive en 3DS MAX loader til opgenGL i C++, men jeg er løbet ind i et linker problem. Problemet opstår kun i nedenstående metode

void Object3DS::ReadVertices(FILE *file, Chunk* chunk)
{
  unsigned int totalVertices;
 
  //Linker fejl opstår her
  chunk->incrementReadBytes(fread(&totalVertices, 1, 2, file));
  Vertex *vertices = new Vertex[totalVertices];
  double* temp = NULL;
  //Linker fejl opstår her
  chunk->incrementReadBytes(fread(temp, 4, totalVertices, file));

  for(int i=0; i<(totalVertices/3); i++)
  {
    int vertexIndex = 3*i;
    vertices[i] = *(new Vertex(temp[vertexIndex], 
                      temp[vertexIndex+1], temp[vertexIndex+2]));
  }
   
  Mesh* currentMesh = this->meshList.at(totalMeshes-1);
  currentMesh->setVertexArray(vertices);
  currentMesh->setTotalVertices(totalVertices);
}

jeg anvender også chunk i andre metoder, men underlig nok får jeg ikke linker fejl i der.

void Object3DS::LoadModel(char* fileName)
{
  Chunk chunk;
  FILE *file = fopen(fileName, "rb");
  ReadSubChunk(file, &chunk);
}

void Object3DS::ReadSubChunk(FILE *file, Chunk* chunk)
{
  Chunk processingChunk;
  unsigned int length = chunk->getChunkLength(); 

  while( chunk->getChunkLength() < length )
  {
      ReadChunk(file, &processingChunk);

      switch( processingChunk.getChunkID() )
      {
      case MESH_BLOCK:
        {
        ReadSubChunk(file, &processingChunk);
        break;
      }

      case OBJECT_DESCRIPTION_BLOCK:
      {
        Mesh* mesh = new Mesh();
        char name[256];
        chunk->incrementReadBytes(readString(file, name));
        mesh->setMeshObjectName(name);
        meshList.push_back(mesh);
        ReadSubChunk(file, &processingChunk);
        break;
      }

    case TRIANGULAR_POLYGON_OBJECT:
    {
        ReadSubChunk(file, &processingChunk);
        break;
    }

    case VERTEX_LIST:
    {
      ReadVertices(file, &processingChunk);
      break;
    }
    }
    chunk-incrementReadBytes(processingChunk.getChunkLength());
  }
}
Avatar billede tokelil Nybegynder
01. august 2006 - 00:24 #1
det er chunk og ikke fread der giver linker fejl?
Avatar billede _henrik Nybegynder
01. august 2006 - 00:30 #2
ja
Avatar billede miqe Nybegynder
01. august 2006 - 00:38 #3
unsigned int totalVertices = 0;
Skulle løse problemet.
Da du ikke initierer din integer har du en masse bits der svæver, da du kun sætter de 2 laveste med fread().
Det går galt da du i de fleste tilfælde refererer til et adresseområde udenfor Vertex i Vertex[totalVertices];
Avatar billede _henrik Nybegynder
01. august 2006 - 00:47 #4
Jeg har prøvet at sætte totalVertices = 0, men det løser desværre ikke mit problem.
Efter at have eksperimenteret lidt har jeg fundet ud af, at der opstår en linker fejl så snart jeg chunk i ReadVertices metoden. Jeg kan frit benytte chunk andre steder
Avatar billede miqe Nybegynder
01. august 2006 - 01:37 #5
Du får med andre ord ikke linkerfejlen når du bare kører fread() uden chunk->incrementReadBytes()??
Du er sikker på at du at du ikke kommer til at pege udenfor Vertex[]?
Selv med totalVertices initieret skriver du dine 2 bytes til de mest betydende bits i integeren, når du bruger den som buffer på den måde.
Avatar billede _henrik Nybegynder
01. august 2006 - 02:19 #6
det er korrekt. Hvis jeg gør det nedenstående opstår der ikke en linkerfejl

//chunk->incrementReadBytes(fread(temp, 4, totalVertices, file));
fread(temp, 4, totalVertices, file);

Jeg har fundet frem til, at der opstår en linkerfejl så snart jeg kalder en metode på chunk i ReadVertices metoden
Avatar billede miqe Nybegynder
01. august 2006 - 02:47 #7
Ligger void Object3DS::ReadVertices() og void Object3DS::ReadSubChunk() i samme fil?
Avatar billede _henrik Nybegynder
01. august 2006 - 08:38 #8
ja alle metoderne tilhørende Object3DS objektet er placeret i samme fil
Avatar billede tokelil Nybegynder
01. august 2006 - 09:56 #9
Hvis du kun får linker fejl i den funktion, kan det måske være der er forskel i deklarationen af dine funktioner i Object3DS?
Avatar billede _henrik Nybegynder
01. august 2006 - 11:45 #10
min Object3DS.h fil ser således ud

class Object3DS
{
public:
.....
void ReadChunk(FILE *file, Chunk* chunk);
void ReadSubChunk(FILE *file, Chunk* chunk);
void ReadVertices(FILE *file, Chunk* chunk);
....
private:
std::vector<Mesh*> meshList;
int totalMeshes;
};

funktionen i Cpp filen

void Object3DS::ReadVertices(FILE *file, Chunk* chunk)
{
....
}

fejlen ser således ud:

3DS Loader error LNK2019: unresolved external symbol "public: void __thiscall Chunk::incrementReadBytes(unsigned int)" (?incrementReadBytes@Chunk@@QAEXI@Z) referenced in function "public: void __thiscall Object3DS::ReadVertices(struct _iobuf *,class Chunk *)" (?ReadVertices@Object3DS@@QAEXPAU_iobuf@@PAVChunk@@@Z)
Avatar billede segmose Nybegynder
01. august 2006 - 14:15 #11
Til dit egentlige problem kan jeg kun sige at jeg mangler definition af Chunk, og specialt Chunk::incrementReadBytes.

Men jeg synes dette ser mærkeligt ud:

  double* temp = NULL; // <-- jeg er NULL
  //Linker fejl opstår her
  chunk->incrementReadBytes(fread(temp, 4, totalVertices, file)); // Jeg læser til NULL

  for(int i=0; i<(totalVertices/3); i++)
  {
    int vertexIndex = 3*i;
    vertices[i] = *(new Vertex(temp[vertexIndex], // jeg laver et nyt element bareset på NULL, der laves en new og der derefereres omgående, vil denne new ikke blive til en memory leak?
                      temp[vertexIndex+1], temp[vertexIndex+2]));
  }
Avatar billede _henrik Nybegynder
01. august 2006 - 18:18 #12
Chunk klassen ser således ud:

Chunk::Chunk()
{
  this->id = 0;
  this->length = 0;
  this->bytesRead = 0;
}

Chunk::Chunk(short id,unsigned int length)
{
  this->id = id;
  this->length = length;
  this->bytesRead = 0;
}

Chunk::~Chunk()
{
  ;
}


inline short Chunk::getChunkID()
{
  return this->id;
}


inline void Chunk::setChunkID(short id)
{
  this->id = id;
}

inline unsigned int Chunk::getChunkLength()
{
  return this->length;
}

inline void Chunk::setChunkLength(int chunkLength)
{
  this->length = chunkLength;
}

inline unsigned int Chunk::getBytesReadFromChunk()
{
  return this->bytesRead;
}

inline void Chunk::incrementReadBytes(unsigned int bytesRead)
{
  this->bytesRead += bytesRead;
}

Med hensyn til de andre ting, så kan jeg ikke lige gennemskue om de er valide. det vil jeg se nærmere på når jeg engang har fået løst linker problemet
Avatar billede segmose Nybegynder
02. august 2006 - 10:50 #13
Hmm
mangler der en public: i din Chunk class definition?

ellers prøv:

Hvis du laver
chunk->incrementReadBytes(fread(temp, 4, totalVertices, file));
om til

unsigned int
  num;

num = fread(temp, 4, totalVertices, file); // fread returnerer size_t

chunk->incrementReadBytes(num);
Avatar billede _henrik Nybegynder
02. august 2006 - 22:31 #14
nej chunk klassens metoder er public:

class Chunk
{
public:
  Chunk();
  Chunk(short id,unsigned int length);
  ~Chunk();
  short getChunkID();
  void setChunkID(short id);
  unsigned int getChunkLength();
  void setChunkLength(int chunkLength);
  unsigned int getBytesReadFromChunk();
  void incrementReadBytes(unsigned int bytesRead);

protected:
  short id;
  unsigned int length;
  unsigned int bytesRead;
};

Uanset hvilken metode jeg kalder på chunk når jeg befinder mig i ReadVertices opstår der en linkerfejl.
Avatar billede segmose Nybegynder
03. august 2006 - 10:05 #15
Kunne du forsimple programmet til der kun er en fil som stadig viser problemet? :(
Avatar billede _henrik Nybegynder
03. august 2006 - 12:18 #16
For at gøre det lidt lettere har jeg uploaded min kode.

http://rapidshare.de/files/28016769/3ds_loader.rar.html
Avatar billede segmose Nybegynder
03. august 2006 - 15:41 #17
ja, jo, hmm

du har i din class definition sagt

void incrementReadBytes(unsigned int bytesRead);

og i implementationen

inline void Chunk::incrementReadBytes(unsigned int bytesRead) {

inline i .cpp filen giver ikke nogen mening og er muligvis fejlen, jeg har ikke mulighed for at teste dette i øjeblikket.

Bjarne skiver i C++ PL 3rd §7.1.1 "the definition of the inline function must be in scope" se også §9.2
Avatar billede _henrik Nybegynder
03. august 2006 - 16:40 #18
det virkede ved at fjerne "inline" keyworded, så jeg siger mange tak for hjælpen til alle. Her er nogle velfortjente point til segmose.

Jeg var ellers sikker på, at man kunne ”inline” som instruktion, for at sikre at compileren indsætter en kopi af funktionen, hvor den kaldes og derved optimere sit program. Jeg tog tydeligvis fejl : (
Avatar billede segmose Nybegynder
04. august 2006 - 09:44 #19
Kun hvis den er i scope, hvis du vil inline den skal den stå i en header f.ex. eller i selve class definitionen.

f.ex

class my {
int x;
public:
inline void incX() { ++x; } // typisk one-liner at være inline.
}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester