I've recently decided to learn more about systems programming, and felt it would be helpful to see what my code is actually doing under the hood.
To do this, I wrote a short LinkedList class in C++ and decided to trace it using dtruss (read: dtrace).
My expectation was that any instructions that extend the heap (e.g. using the new keyword, or instantiating LinkedList objects) would invoke the mmap or sbrk/break system calls. This was not the case!
In fact, running dtruss with the -s switch, I don't see any system calls being invoked from inside my LinkedList::Add function! Testing, I'm certain elements are being added.
Can anyone explain why I don't see references to mmap/sbrk in my dtruss output?
Bonus points if someone could explain the purpose of mprotect and madvise.
I've included my LinkedList class, main.cpp, and dtruss output below.
Thank you!
dtruss output
SYSCALL(args) = return
Created new LinkedList
Created new LinkedList
Destroyed a LinkedList
open("/dev/dtracehelper\0", 0x2, 0xFFFFFFFFE3236D70) = 3 0
ioctl(0x3, 0x80086804, 0x7FFEE3236CD0) = 0 0
close(0x3) = 0 0
access("/AppleInternal/XBS/.isChrooted\0", 0x0, 0x0) = -1 Err#2
thread_selfid(0x0, 0x0, 0x0) = 198178 0
bsdthread_register(0x7FFF5BAB5C50, 0x7FFF5BAB5C40, 0x2000) = 1073742047 0
issetugid(0x0, 0x0, 0x0) = 0 0
mprotect(0x10C9D0000, 0x1000, 0x0) = 0 0
mprotect(0x10C9D5000, 0x1000, 0x0) = 0 0
mprotect(0x10C9D6000, 0x1000, 0x0) = 0 0
mprotect(0x10C9DB000, 0x1000, 0x0) = 0 0
mprotect(0x10C9CE000, 0x88, 0x1) = 0 0
mprotect(0x10C9DC000, 0x1000, 0x1) = 0 0
mprotect(0x10C9CE000, 0x88, 0x3) = 0 0
mprotect(0x10C9CE000, 0x88, 0x1) = 0 0
getpid(0x0, 0x0, 0x0) = 1698 0
stat64("/AppleInternal/XBS/.isChrooted\0", 0x7FFEE32362E8, 0x0) = -1 Err#2
stat64("/AppleInternal\0", 0x7FFEE3236380, 0x0) = -1 Err#2
csops(0x6A2, 0x7, 0x7FFEE3235E20) = -1 Err#22
sysctl([CTL_KERN, 14, 1, 1698, 0, 0] (4), 0x7FFEE3235F68, 0x7FFEE3235F60, 0x0, 0x0) = 0 0
csops(0x6A2, 0x7, 0x7FFEE3235710) = -1 Err#22
getrlimit(0x1008, 0x7FFEE32374F0, 0x0) = 0 0
fstat64(0x1, 0x7FFEE3237508, 0x0) = 0 0
ioctl(0x1, 0x4004667A, 0x7FFEE3237554) = 0 0
write_nocancel(0x1, "Created new LinkedList\n\0", 0x17) = 23 0
write_nocancel(0x1, "Created new LinkedList\n\0", 0x17) = 23 0
write_nocancel(0x1, "Destroyed a LinkedList\n\0", 0x17) = 23 0
LinkedList.cpp
#include <iostream>
#include "LinkedList.h"
using namespace std;
LinkedList::LinkedList() {
this->length = 0;
this->head = NULL;
this->tail = NULL;
cout << "Created new LinkedList" << endl;
}
LinkedList::~LinkedList() {
Node* curr;
Node* temp;
curr = this->head;
while ( curr ) {
temp = curr;
curr = curr->next;
delete temp;
}
cout << "Destroyed a LinkedList" << endl;
}
void LinkedList::Add(int v) {
Node* n = new Node();
n->val = v;
n->next = NULL;
if (!this->head) {
this->head = n;
this->tail = n;
} else {
this->tail->next = n;
this->tail = n;
}
}
main.cpp
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main() {
LinkedList l; // You should require a heap increase, right?
LinkedList* ll = new LinkedList(); // Surely you require more heap!
for (int i=0; i<1000; i++)
l.Add(i);
return 0;
}
I found that Mac OS doesn't use
sbrk/brk/break()for memory management like most UNIX/Linuxes. Basically, it's using the Mach kernel that Apple inherited from NeXT so the memory calls are going to bempadvise(2)andmprotect(2)which offer finer grain control thansbrk().From "Mac OS X and iOS Internals" by Jonathan Levin:
So to interpret your memory allocations you'd need to know the
mprotect(2)arguments from thesys/mman.hheader.And so your system calls would imply:
Regarding
mmap(2), on Linux systems it's used to map the object code of the shared libraries but not used formalloc/freeornew/delete.References: