堆栈或堆上的对象分配

时间:2013-02-10 12:21:33

标签: c++ object stack runtime heap

我正在尝试建立一种可以分辨出类对象分配位置的机制。 考虑在类中创建一个标志,但是不可能设置一个值,因为在调用“new”运算符期间没有启动对象的生命周期。 在C ++中是否可以判断对象是在堆栈还是堆(运行时)?

2 个答案:

答案 0 :(得分:1)

没有可移植的方法可以做到这一点,但是如果我们假设你有一些有限的系统类型,你可以尝试以下方法:

获取main中某个局部变量的地址(或其他“callstack中的低位”)。将其存储在全局变量中,然后调用char *stackbase;

然后在您正在检入的函数中获取局部变量的地址,让我们称之为char *stacktop;

现在,如果我们有char *obj = reinterpret_cast<char *>(object_in_test);,那么:

if (obj > stacktop && obj < stackbase) on_stack = true;
else on_stack = false; 

请注意,这有以下几个缺陷:

  1. 这是技术上未定义的行为。它适用于大多数系统,因为整个内存空间是连续的。但是有些系统中堆栈和其他内存部分具有单独的“地址空间”,这意味着指向不同类型内存的两个指针可以具有相同的地址。
  2. 线程需要有一个“每线程堆栈库”。
  3. 假设堆栈“向零增长”(如果不是,则必须反转if中的><
  4. 全局变量将被视为not on stack
  5. 自行承担使用风险!
  6. 我完全希望不得不删除这个答案,因为它会被语言律师贬低,尽管下面有免责声明。

答案 1 :(得分:1)

我一直在做一些实验,并且发现这似乎能够在运行时始终告诉对象是否已在堆栈上分配。

界面如下:

if ($depOption == "bitcoin" or "ethereum" or "lisk")
    {

        // Get information on altcoin values
        $request = 'https://api.coinmarketcap.com/v1/ticker/';
        $response  = file_get_contents($request);
        $data = json_decode($response, true);
        $price = null;
        foreach ($data as $item) {
            if ($item["id"] == "$depOption") {
                $VAL = $item["price_usd"];
                break;
            }
        }
    }
elseif ($depOption == "EUR")
    {
        // Get EUR exchange rate
        $eurrequest = 'http://api.fixer.io/latest';
        $eurresponse  = file_get_contents($eurrequest);
        $eurdata = json_decode($eurresponse, true);
        $VAL = $eurdata['rates']['USD'];
    }

elseif ($depOption == "USD")
    {
        $VAL = 1;
    }

else
    {
        die("Something went wrong.");
    }

实施是:

#ifndef HEAPAWARE_H
#define HEAPAWARE_H

#include <cintttypes>

class HeapAware
{
public:
    HeapAware();
    void *operator new(std::size_t size);
    void *operator new[](std::size_t size);
    void operator delete(void *ptr, std::size_t);
    void operator delete[](void *ptr, std::size_t);
    bool is_on_heap() const { return on_heap; }
    std::ptrdiff_t get_heap_array_index() const { return heap_array_index; }
private:
    const bool on_heap;
    const std::ptrdiff_t heap_array_index;
    static thread_local HeapAware * last_alloc;
    static thread_local std::size_t allocated_size;
};
#endif

这似乎始终正常。对于在堆上分配的数组,条目的索引也可用。对于在堆栈上分配的值,或者对于刚刚单独分配的条目,void *HeapAware::operator new(std::size_t size) { auto result = last_alloc = reinterpret_cast<HeapAware*>(malloc(size)); allocated_size = 1; return result; } void *HeapAware::operator new[](std::size_t size) { auto result = last_alloc = reinterpret_cast<HeapAware*>(malloc(size)); allocated_size = size; return result; } void HeapAware::operator delete(void *ptr, std::size_t) { free(ptr); } void HeapAware::operator delete[](void *ptr, std::size_t) { free(ptr); } HeapAware::HeapAware():on_heap(this>=last_alloc && this<last_alloc+allocated_size),heap_array_index(allocated_size>1?this-last_alloc:-1) { } thread_local HeapAware * HeapAware::last_alloc = nullptr; thread_local std::size_t HeapAware::allocated_size = 0; 函数返回-1。

此代码的假设是在构造任何给定线程之前立即调用new运算符。然而,这个假设似乎适用于我所尝试的一切。