C multidimensional arrays in Cocoa (strange problem)

Discussion in 'Mac Programming' started by PaperFace, Sep 30, 2008.

  1. PaperFace macrumors newbie

    Joined:
    Sep 18, 2008
    #1
    Right, I'm not that keen on Cocoa or Objective C but love the iPhone tech so I'm just about picking it up as I go along, but somethings stuck me.

    I'm using some pretty huge arrays so instead of the NSArray pish I can't quite grasp the purpose of, I'm using old school C multi dimensional arrays..

    for example..

    type arrayname[size1][size2];

    Only thing is, I have that at the top of a function. so it should be creating a temporary array for that function right? but the next time I call that function and create the array, it's already populated with the data from the first time the function ran. It's as if it's creating a static object!

    Any ideas why? It's got me baffled!

    Thanks in advance!
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    local variables will go on the stack. If the stack frames match from one call to the next, this behavior can occur. If your variables need initialization, you must do it using something like bzero.

    -Lee
     
  3. PaperFace thread starter macrumors newbie

    Joined:
    Sep 18, 2008
    #3
    Hi Lee,

    Thanks for a prompt reply. I spent yesterday googling and reading about stacks to grasp what you explained, but from what I can tell, a stack only exists for a routine while it's running and once the routine is finished or returned, the stack should be removed.

    It's only running this function once per cycle, so there is never more than onc instance of the function running simultaneously. So why would the stack frames be matching?

    I don't see why this has only happened now, when all the other functions/routines I write don't zero every local variable they init but don't suffer from the same problems.

    Should I always zero every local variable I declare in my entire app? maybe I've been doing it wrong up until now but have just never hit a problem with it by chance.

    Thanks!
     
  4. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #4
    Each function call you make results in a frame being pushed onto the stack. Its size will be the total of all of its local variables, its arguments, and a pointer to the code for the function. When/if the function returns, it's stack frame will be popped from the stack. However, the area on the stack it was occupying will not be filled with zeros, it will be left with whatever was in there previously. In the case that function A calls function B, B returns, then A calls B again, the second time B runs it will be occupying the same memory on the stack that it was during its first run. If A calls B, B returns, A calls C, and C calls B, B will now be in a different position on the stack, so while its variables may still be garbage, they aren't going to be in the same positions in memory as they were the first time it was called.

    You should always initialize anything you depend on being 0. Some compilers might generate code to initialize the whole stack, etc. for you at invocation, but you can't count on that, and they are very unlikely to clear out the memory above each stack frame. it would simply be wasteful.

    Its your job to make sure that data is as you expect it, whether it's on the stack or the heap. The pointer returned by malloc will not point to memory that has been zerod out for you, it will only give you a pointer to the amount of memory you asked for, and you can zero it if you like. The same applies for local variables. There is no reason for you to assume anything about the memory contents of the stack. Generally the functions memset and bzero, which is essentially a wrapper for memset, are used to accomplish this for large arrays, etc. Assignment of 0 or 0. is normally used for primitives, and 0 as NULL (nil for object pointers, again, still just 0 with a different name) for pointers.

    As an aside, this is all straight C. Cocoa and Objective-C haven't gotten involved at all so far here.

    If you'd like I can write an example program and run it with the debugger, showing you the locations of stack frames and the variables within them if that will help demonstrate this.

    -Lee
     
  5. PaperFace thread starter macrumors newbie

    Joined:
    Sep 18, 2008
    #5
    Thanks for the reply, that makes sense. Never had a problem with it before but to be honest, I'm probably a bit tidier with C/C++.

    So it's just a case of setting pointers to *pointer = nil and zeroing objects with bzero(&object,sizeof(object)); ?
     
  6. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #6
    The nil vs. NULL thing for pointers is just a matter of style. The rule is that nil is for pointers to objects and NULL is for pointers to primitives. You don't need to initialize objects like that, but bzero can be used to initialize arrays and structs.

    -Lee

    Edit: For objects you don't want to just zero the memory space, you would do initialization of all of your fields in the init... method. When you're initializing in the init method you can follow the same rule. Chances are as you progress you won't be using many C-style arrays in favor of NSMutableArrays, etc., and probably not TOO many structs (though a few, for sure) so the use of bzero won't be as common.
     

Share This Page