Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><em>Edit: As Michael has pointed out in the comments, what is written below really won't work in the real-world due to stack-relative addressing by an optimizing compiler. Therefore a production-level <code>alloca</code> needs the help of the compiler to actually "work". But hopefully the code below could give some ideas about what's happening under the hood, and how a function like <code>alloca</code> might have worked if there were no stack-relative addressing optimizations to worry about.</em></p> <p>BTW, just in case you were stil curious about how you could make a simple version of <code>alloca</code> for yourself, since that function basically returns a pointer to allocated space on the stack, you can write a function in assembly that can properly manipulate the stack, and return a pointer you can use in the current scope of the caller (once the caller returns, the stack space pointer from this version of <code>alloca</code> is invalidated since the return from the caller cleans up the stack).</p> <p>Assuming you're using some flavor of Linux on a x86_64 platform using the Unix 64-bit ABI, place the following inside a file called "my_alloca.s":</p> <pre><code>.section .text .global my_alloca my_alloca: movq (%rsp), %r11 # save the return address in temp register subq %rdi, %rsp # allocate space on stack from first argument movq $0x10, %rax negq %rax andq %rax, %rsp # align the stack to 16-byte boundary movq %rsp, %rax # save address in return register pushq %r11 # push return address on stack ret # return back to caller </code></pre> <p>Then inside your C/C++ code module (i.e, your ".cpp" files), you can use it the following way:</p> <pre><code>extern my_alloca(unsigned int size); void function() { void* stack_allocation = my_alloca(BUFFERSIZE); //...do something with the allocated space return; //WARNING: stack_allocation will be invalid after return } </code></pre> <p>You can compile "my_alloca.s" using <code>gcc -c my_alloca.s</code>. This will give you a file named "my_alloca.o" that you can then use to link with your other object files using <code>gcc -o</code> or using <code>ld</code>.</p> <p>The main "gotcha" that I could think of with this implementation is that you could crash or end up with undefined behavior if the compiler did not work by allocating space on the stack using an activation record and a stack base-pointer (i.e., the <code>RBP</code> pointer in x86_64), but rather explicitly allocated memory for each function call. Then, since the compiler won't be aware of the memory we've allocated on the stack, when it cleans up the stack at the return of the caller and tries to jump back using what it believes is the caller's return address that was pushed on the stack at the beginning of the function call, it will jump to an instruction pointer that's pointing to no-wheres-ville and you'll most likely crash with a bus error or some type of access error since you'll be trying to execute code in a memory location you're not allowed to.</p> <p>There's actually other dangerous things that could happen, such as if the compiler used stack-space to allocate the arguments (it shouldn't for this function per the Unix 64-bit ABI since there's only a single argument), as that would again cause a stack clean-up right after the function call, messing up the validity of the pointer. But with a function like <code>execvp()</code>, which won't return unless there's an error, this shouldn't be so much of an issue.</p> <p>All-in-all, a function like this will be platform-dependent.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload