Arrays in C++

Discussion in 'Mac Programming' started by sheepopo39, Dec 7, 2009.

  1. sheepopo39 macrumors 6502

    Joined:
    Sep 18, 2008
    #1
    Alright, so I was working with arrays in C++ on my mb and the code is

    Code:
    #include <iostream>
    using namespace std ;
    int main()
    {
    int nums[50] ;		
    cout << nums[4] << endl ;
    
    	return 0 ;
    }
    So when I compile and run it through terminal I get this "1606417072" and I know I haven't initialized the nums array yet, so shouldn't all of the elements be zero?
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    Why should it be 0? That's not guaranteed behavior. Initialization takes time. If you don't need it, the compiler shouldn't choose to waste time for you. If you do need it, just say so.

    -Lee
     
  3. sheepopo39 thread starter macrumors 6502

    Joined:
    Sep 18, 2008
    #3
    My question is then, how did it get that number?
     
  4. lixuelai macrumors 6502a

    Joined:
    Oct 29, 2008
    #4
    When a program releases memory back to the system it does not clear it. It only gets rewritten when it is reinitialized. So that garbage value is from whatever was using that memory before your code did. Just think of it as a whiteboard with stuff written on it. All you are doing right now is drawing a border around the area you want to use to tell other "its my territory don't touch it". You still have not erased what was on it before.
     
  5. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #5
    The memory set aside there just has garbage. Maybe it had been used by another program, maybe it's just plain garbage. It COULD be zero. Or anything. Never depend on the value of uninitialized memory.

    -Lee
     
  6. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #6
    Prior to 10.6, malloc() did zero-fill memory. Unfortunately, a number of apps came to rely on this.

    None of that applies to stack-allocated stuff anyway.
     
  7. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #7
    Malloc never guaranteed to zero-fill (I'm not saying Catfish_Man is claiming that), but I do know that operating systems were starting to do so, because it is a security risk otherwise (on a multi-user system, at least): simply malloc a large chunk of memory and start sifting through the garbage looking for interesting data. So I'm surprised that SL no longer does it.

    Perhaps it's optimized to remember whether a piece of memory was previously used by the same user, in which case the cleaning step can be omitted - pretty nifty.
     
  8. Detrius macrumors 68000

    Joined:
    Sep 10, 2008
    Location:
    Asheville, NC
    #8
    Code:
    #include <iostream>
    using namespace std ;
    int main()
    {
    int nums[50] ;		
    [COLOR="Blue"]memset(nums,0,sizeof(nums))[/COLOR];
    cout << nums[4] << endl ;
    
    	return 0 ;
    }

    There. Fixed it. Note that using "sizeof(nums)" is more future proof than saying "50" again, as it won't break if you change the allocated size of nums. Even though they are sitting right next to each other, you'd be surprised how easy it is to speed through and change a size and miss other important details like this.

    Actually, here's another fix:

    Code:
    #include <iostream>
    using namespace std ;
    int main()
    {
    int nums[50] [COLOR="Blue"]= { 0 }[/COLOR];		
    cout << nums[4] << endl ;
    
    	return 0 ;
    }
    Technically, I've never tried this, but I believe it was in one of the Effective C++ books. If you initialize any of an array/struct and leave out the rest, then the rest is automatically initialized to zero.
     
  9. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #9
    This is correct.

    i
    Code:
    nt array[50] = { 1 };
    If at least 1 initializer is provided the remainders will be filled with 0.
     
  10. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #10
    If memory serves it keeps a pool of freed blocks that it can reuse with zero-filling.
     
  11. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #11
    It doesn't work like that, at least on a sane operating system (including MacOS X): No memory block that your application can access will _ever_ include data from another application. Every page of memory in RAM that you access was either yours, so it contains your data and nobody else's, or it has just been swapped in from the page file, and contains your data, or it is just freshly allocated, and at that point it is filled with information-free data (usually all zeroes, but could be all 1's, or all genuine random data, as long as it is nothing from another application).

    malloc cannot access the memory used by another application. It can re-use memory blocks, but they are your own and contain your own leftover bits of data.
     
  12. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #12
    Are you sure? Memory addresses are virtualized, but the real, physical memory will contain whatever the previous process left in there. When an application terminates; the whole working set is yielded to the OS to hand out to new applications. Malloc will call sbrk() or a similar system call to claim more pages. If sbrk() is coded with security in mind, it will zero pages before handing them to your process.
     
  13. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #13
    At some point the OS will map a physical RAM page to your process that previously didn't belong to that process. That RAM page will be mapped to a virtual page belonging to your application. That virtual page either has been previously written to the swap file, in which case it _must_ be read from the swap file and therefore will be filled with data from your own application, or it is not present in the swap file, in which case the OS must and will fill the page with data destroying any information of the previously owning process.

    This is a thing that _must_ be done by the operating system, and this is not a matter of "coding with security in mind", not doing it would be so criminally mindboggingly incompetent that anyone doing this today would get their ass sued off.

    PS. You forgot that a process doesn't only lose a RAM page when it quits; it loses physical RAM pages every single time a page gets swapped out because another process needs it.
     
  14. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #14
    I seem to remember that in the past, this was an attack vector. But of course, I can't find any documentation to back this up now. I looked at the brk() implementation on Minix and it doesn't seem to clean pages. I couldn't find a specific reference to it in my Tanenbaum book, but it's been a while since I read it.

    I remember from my hobby OS project (haven't we all started one..?) that this "page cleaning" effort is something I needed to add specifically, and I didn't bother. It has quite a performance impact since you are touching all the memory just brk()d, which kills your caches.

    Of course, this was at the time I felt every clock cycle was important. (I still don't like "wasting" them, but "waste" is a relative term. I prefer to look at it as "paying" for certain features with clock cycles :) )

    P.S. During my googling, I stumbled upon this - the source code to MacOS' sbrk(). It carries "14-Feb-89 Avadis Tevanian (avie) at NeXT." in the copyright header :)
     
  15. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #15
    Hm... Perhaps a test is in order:

    App 1: Allocates something over 1/2 of total physical RAM and writes a distinctive string over all of it.

    App 2: Allocates something over 1/2 of total physical RAM and searches for the distinctive string.

    Test: Run App1 then run App2. Does App2 find the string?

    The idea is that there will be at least some physical RAM overlap between the allocations of Apps 1 and 2. But I don't know if paging will occur. If so then a more sophisticated way of ensuring that physical RAM from App1 is reused in App2 would be needed.

    I'll try this if I get a chance (though it probably won't be tonight).
     
  16. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #18
    Re: "Note that the position of the cutoff between small and large allocator on MacOS X can and will change. It should not be relied on." from that last link: make that "can, will, and did". The small/large cutoff is 2x higher in Snow Leopard than in Leopard.
     
  17. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #19
    We shouldn't "test" this. The data you get by testing is only valid for your machine, for your exact OS version, etc.

    Just read the spec. If you need zero-initialized memory, there's calloc(). If you don't (because you're going to fill the memory yourself anyway, and don't want to pay for the zeroing) you use malloc().

    I derailed part of this thread by suggesting the contents of the malloc()ed memory could even be data from another process. This was (perhaps) the case when computers still ran on steam, and is totally irrelevant to this thread. I'm sorry.
     
  18. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #20
    Why not?

    The question is no longer whether or not memory is zero-initialized -- we already know there is no guarantee of that.

    The test question is whether or not a process can access data in RAM freed from another process. I didn't see a spec for that, maybe I missed it.
     
  19. Detrius macrumors 68000

    Joined:
    Sep 10, 2008
    Location:
    Asheville, NC
    #21
    My understanding from the links I posted is that PAGES are definitively zero-initialized. The fact that it's done lazily is not logically relevant here. malloc does NOT zero-initialize, so it's possible to allocate memory that has already been used by your application and therefore already has your own data in it. Malloc works within the subset of pages allocated to your program. Any new page allocated to your program will be zero-filled. Therefore, any and all memory given to your program will start zero-filled and therefore not have data from another process.
     
  20. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #22
    Ah, OK. I thought you wanted to "test" whether malloc zero-initializes your memory. I didn't read your post correctly.

    I think you'll find that you won't get the strings from the other app. At least, I hope that's the case :)
     

Share This Page