View Full Version : random question about alloca
feisty2
17th February 2016, 18:02
I really really really really really don't wanna do the GC stuff cuz I don't want to
seems I got 2 choices in C++, and I tried them both
#include <iostream>
#include <memory>
#include <cstdlib>
#include <cstdint>
#include <malloc.h>
using namespace std;
class test {
public:
test() {
cout << "test!" << endl;
}
void func() {
cout << "123" << endl;
}
~test() {
cout << "~test!" << endl;
}
};
void _auto_ptr_test() {
test *ptr = new test;
auto_ptr<test> aptr(ptr);
aptr->func();
}
void _alloca_test(uint64_t &addr) {
double *ptr = reinterpret_cast<double *>(alloca(sizeof(double)));
*ptr = 0.1234;
cout << endl << *ptr << endl;
addr = reinterpret_cast<uint64_t>(ptr);
}
void main() {
uint64_t addr;
_auto_ptr_test();
_alloca_test(addr);
cout << *reinterpret_cast<double *>(addr) << endl;
system("pause");
}
and it's like
http://i.imgur.com/PH81SV6.png
so auto_ptr works, the dtor actually ran automatically
and alloca, docs state that it allocates memory on stack, so no GC is required, things are automatically freed as the function returns
and that's the weird part, the last line should be some random garbage data cuz the pointer was already automatically freed, but it's still 0.1234 like the previous line...
wtf?:confused:
vivan
17th February 2016, 18:49
It was only freed (marked as free), of course it doesn't mean that it will be filled with garbage instantly.
void _alloca_test(uint64_t &addr, double val) {
double *ptr = reinterpret_cast<double *>(_alloca(sizeof(double)));
*ptr = val;
cout << endl << *ptr << endl;
addr = reinterpret_cast<uint64_t>(ptr);
}
void main() {
uint64_t addr, addr2;
_alloca_test(addr, 0.1234);
cout << *reinterpret_cast<double *>(addr) << endl;
_alloca_test(addr2, 0.2345);
cout << *reinterpret_cast<double *>(addr) << endl;
system("pause");
}
LoRd_MuldeR
17th February 2016, 19:14
Yes, alloca() allocates on the stack. And that memory gets "freed", implicitly, as soon as the function, from which alloca() had been called, returns.
But that does not mean the memory will be "cleaned" or overwritten with "garbage", when the function returns! It just means that the pointer returned by alloca() gets invalidated as soon as your function returns :eek:
Trying to access this invalidated ("dangling") pointer causes undefined behavior. Trying to read from such a dangling pointer can result in anything from "I still get the old data as if the memory had never been freed" over "I get some arbitrary 'garbage' data" to "my application crashes with access violation". Even worse, trying to write to a dangling pointer is probably going to corrupt some other data, because that memory might already have been re-allocated to something else.
Note: There is very few reason to use alloca() in practice, because you can just use a normal local variable, if you want to store something on the stack. And if you need to store something on the heap, so that it can survive even after your function has returned, you have to use malloc() or new anyway. Furthermore, allocating large buffers on the stack is a bad idea, because stack space is limited! You can get nasty stack overflow crashes. There is a reason why _malloca() exists ;)
(malloc() and new allow for "gracefully" handling out-of-memory situations, while alloca() does not. Also, the heap is MUCH less likely to ever run out of memory)
feisty2
18th February 2016, 09:45
@vivan
@LoRd_MuldeR
I think I got it now...
I found this alloca thing cuz new and malloc are pretty slow, alloca is way faster and free of manual GC, anyway, I might happen to have some practical use for it someday.. who knows, also not a bad thing to learn something new..
smart pointers seem to be the only choice to be free from the misery business of manual GC..
nevcairiel
18th February 2016, 09:50
Need to be careful with alloca though, stack space is limited. Its generally considered bad style to use it extensively.
LoRd_MuldeR
18th February 2016, 19:59
I found this alloca thing cuz new and malloc are pretty slow, alloca is way faster and free of manual GC, anyway, I might happen to have some practical use for it someday.. who knows, also not a bad thing to learn something new..
If malloc() and free() (or the new and delete equivalents) take a noteworthy amount of CPU time in your program, you probably should re-think your design. It's better to allocate all buffers right at the beginning (e.g. in the constructor), re-use them for all your computations and release them at the very end (e.g. in the destructor). Allocating and releasing a whole lot of short-lived buffers during your computations is usually a bad idea.
BTW: If you need a (small) temporary buffer, you can simply use a local variable, which will be allocated on the stack. The alloca() function is pretty much a workaround for compilers without VLA (Variable Length Arrays) support...
smart pointers seem to be the only choice to be free from the misery business of manual GC..
Working with malloc() and free() (or the new and delete equivalents) should be fine, if you organize your code well. It should be clear which object "owns" the buffer. That object is responsible for allocating the buffer (either in the constructor or "on demand") as well as for releasing the buffer when it's no longer needed (typically in the destructor). Other objects should not "steal" the pointer. Ideally, the pointer to the buffer should never "leak" outside of the owning object.
(It's also considered good practice to NULL-ify any pointer that has been free'd)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.