using the xcode debugger

Apprentice
Posts: 17
Joined: 2007.02
Post: #1
I'm trying to write a simple OBJ loader for practice before I try writing my own filetype. I'm having a problem with a call of memcpy() but I can't figure out what's wrong because I don't exactly know how to use the debugger.

Here is what I know about it so far:

1. debuggers slow down the program so you can see what is going on
2. breakpoints are where you tell the program to pause
3. when stopped a breakpoint you can view the values of variables during runtime
4. the fix button doesn't magically fix the problems you're having with your program

Most of the time the console just gives me "EXC_BAD_ACCESS” and nothing else.

In short, how do I use the Xcode debugger?
Quote this message in a reply
Member
Posts: 241
Joined: 2008.07
Post: #2
Debugging is something that takes a lot of practice, experience, understanding, and education of computer science. It's not really something someone can simply explain to you. Do you have a more specific question?
Quote this message in a reply
Apprentice
Posts: 17
Joined: 2007.02
Post: #3
Maybe I should just post the code:

obj.h
Code:
#include "global.h" // opengl.h, sdl.h, etc...

typedef struct vertex
{
    // vertex location
    float x, y, z;
    
    // uv co-ordinates
    float u, v;
    
    // vertex normals
    float nx, ny, nz;
    
    // what bone is the vertex attached to?
    // temp space
    
    // level of influene from bone to vertex
    float inf;
    
} vert;

typedef struct face
{
    // each face can have a maximum of 4 verticies
    vert *points;
    
} face;

typedef struct object
{

    int noOfVerts;
    int noOfFaces;
    face *faces;
    //std::vector<face> faces;
    
} obj;

obj *edlObj(std::string file);
obj.cpp
Code:
obj *edlObj(std::string file)
{
    
    int i;
    FILE *filein;
    int totalverts = 0, totalfaces = 0;
    vert *tempVerts = NULL;
    obj *tempStorage;
    
    char oneline[255];
    
    filein = fopen(file.c_str(), "rt");
    
    while(!feof(filein))
    {
        fgets(oneline, sizeof(oneline), filein);
        
        if (oneline[0] == 'v' && oneline[1] == ' ')
        {
            totalverts ++;
            
        } else if (oneline[0] == 'f' && oneline[1] == ' ')
        {
            totalfaces ++;
            
        }
    }
    
    
    tempVerts = new vert [totalverts];
    if (tempVerts == NULL)
    {
        printf("error");
    }
    
    tempStorage->faces = new face [totalfaces]; // <------ This line gives me “EXC_BAD_ACCESS” and I don't know what to do about it.
    if (tempStorage->faces == NULL)
    {
        printf("error");
    }
    
    
    rewind(filein);

    int tempint = 0, spamint = 0, uvcount = 0;
    int currentFace = 0;
    int temparray[4];
    
    while (!feof(filein))
    {
        fgets(oneline, sizeof(oneline), filein);
        
        if (oneline[0] == 'v' && oneline[1] == ' ')
        {
            fscanf(filein, "%f", &tempVerts[tempint].x);
            fscanf(filein, "%f", &tempVerts[tempint].y);
            fscanf(filein, "%f", &tempVerts[tempint].z);
            
            tempint ++;
        } else if (oneline[0] == 'v' && oneline[1] == 't')
        {
            fscanf(filein, "%f", &tempVerts[uvcount].u);
            fscanf(filein, "%f", &tempVerts[uvcount].v);
            
            uvcount ++;
        } else if (oneline[0] == 'v' && oneline[1] == 'n')
        {
            fscanf(filein, "%f", &tempVerts[spamint].nx);
            fscanf(filein, "%f", &tempVerts[spamint].ny);
            fscanf(filein, "%f", &tempVerts[spamint].nz);
            
            spamint ++;
        } else if (oneline[0] == 'f' && oneline[1] == ' ')
        {
            
            for (i=0;i>4;i++)
            {
                
                tempStorage->faces[currentFace].points = new vert [4];
                
                fscanf(filein, "%i", temparray[i]);
                
                tempStorage->faces[currentFace].points[i].x = tempVerts[temparray[i]].x;
                tempStorage->faces[currentFace].points[i].y = tempVerts[temparray[i]].y;
                tempStorage->faces[currentFace].points[i].z = tempVerts[temparray[i]].z;
                
                
                
                currentFace ++;
            }
        }
    }
    
    fclose(filein);
    
    delete[] tempVerts;
    
    return(tempStorage);
    
}
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #4
Looks like you're crashing because tempStorage is uninitialized. When you say tempStorage->faces, you're attempting to dereference a random location in memory. You'll need to allocate some storage space for it first.

If you were running this with the Xcode debugger, it should have halted on that line and allowed you to inspect your variables. In this particular case, though, it might not have been informative, since an uninitialized pointer isn't always distinguishable from an initialized one.
Quote this message in a reply
Apprentice
Posts: 17
Joined: 2007.02
Post: #5
I see whats going on now. So if I want to fix this maybe I should try:

Code:
obj *tempStorage = NULL;
tempStorage->faces = NULL;
tempStorage->faces->points = NULL;

Will this work?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #6
No, you can't dereference a NULL pointer without crashing. I'd suggest reading about the basics of memory management in K&R or something similar.
Quote this message in a reply
Apprentice
Posts: 17
Joined: 2007.02
Post: #7
I'll take that book recommendation into consideration, but unfortunately I don't have enough time to wait for a book to be delivered. I looked up this problem on wikipedia and the article said the compiler stops because the variable I'm trying to allocate doesn't equal anything. I remember a pointers tutorial that mentioned always making sure pointers equaled NULL (maybe I misunderstood the instructions). So how do I allocate these structures?
Quote this message in a reply
Moderator
Posts: 1,560
Joined: 2003.10
Post: #8
In C, you can use the malloc function to allocate a block of memory on the heap. See the malloc man page for more details.

Since you're in C++, you can alternately use the new operator. This differs from malloc in that it calls constructors/destructors for C++ objects allocated with it.

In either case, make sure you call free (if you're using malloc) or delete (if you're using new) to release the memory back to the system when you're done with it.

In more general terms, you'll need to understand how pointers and memory work to be able to do this. When you declare "obj *tempStorage;" in your code, the value of tempStorage is interpreted as a memory address. A memory address is simply an unsigned integer (on the Mac, either 32 bits or 64 bits in size, depending on your target CPU architecture) that identifies a location in memory.

When you do "tempStorage->faces = NULL;", what that essentially means is "read the value of tempStorage, add the offset of the faces field from the beginning of the obj struct to it, and write the value 0x00000000 (NULL) to that address in memory". In order for this operation to succeed, tempStorage has to have a value that is a memory address your application is allowed to write to, such as one returned from a call to malloc(sizeof(obj)). If you attempt to write to address 0 (which is what happens if you initialize tempStorage to NULL first) or a random value (which is what happens if you don't initialize it at all), your program crashes due to the memory protection mechanism built into the operating system, since you're trying to write to an address not owned by your process.

NSDuo Wrote:I remember a pointers tutorial that mentioned always making sure pointers equaled NULL (maybe I misunderstood the instructions).

Presumably, this is referring to the practice of always initializing pointer variables to NULL, which is sometimes advocated to help reduce bugs caused by forgetting to initialize a pointer to something valid before using it. Since the pointer is NULL, you'll crash (nicely) right away, and be able to clearly see that the pointer is invalid. This isn't necessarily the case when you don't initialize it, because it contains whatever happened to be in memory at the location the pointer now occupies, which might not be obviously invalid; or worse yet, point to some valid but unintended location in your application's memory space, which leads to nondeterministic and difficult-to-find memory corruption bugs. As long as all code paths leading up to use of a pointer guarantee that it's initialized to something valid, this is unnecessary, but it's somewhat a matter of how much you trust yourself not to forget to initialize it. Many high-profile bugs are caused by uninitialized variables.
Quote this message in a reply
Apprentice
Posts: 17
Joined: 2007.02
Post: #9
I think I'm starting to get the hang of the debugger. I put a breakpoint after the declaration of tempStorage and before I allocated it.
It shows:

the value of tempStorage is 0x970ac367 (seems like a valid address)
the value of faces is 0x55c3c95e (again a valid address)
the value of points is nothing, everything inside points is nothing too.

So my program crashes because I'm trying to access memory with no address. Because its like this right after tempStorage is declared means that tempStorage is being declared with variables inside it with no memory address. How do I fix this?
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Xcode4: Debugger - how do you view class members? SparkyNZ 4 7,537 Jul 4, 2011 03:08 PM
Last Post: bdsowers
  XCode combining debugger and console?? Toontingy 2 5,479 Feb 16, 2010 07:55 PM
Last Post: Toontingy
  iPhone application always opens with the debugger! frogameleon 0 2,583 Mar 6, 2009 10:02 AM
Last Post: frogameleon
  Xcode debugger and C++ global/file scope variables. WhatMeWorry 2 5,067 Sep 9, 2005 12:34 AM
Last Post: WhatMeWorry
  Two Stupid Xcode and debugger questions WhatMeWorry 3 3,518 Aug 13, 2005 04:48 PM
Last Post: WhatMeWorry