Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

sheepopo39

macrumors 6502
Original poster
Sep 18, 2008
251
0
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?
 
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
 
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.
 
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
 
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.
 
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.
 
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.
 
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.

This is correct.

i
Code:
nt array[50] = { 1 };

If at least 1 initializer is provided the remainders will be filled with 0.
 
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.

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.
 
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.

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.
 
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.

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.
 
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.

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 :)
 
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).
 
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.
 
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.
 
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.
 
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.

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.
 
The test question is whether or not a process can access data in RAM freed from another process.

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 :)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.