繁体   English   中英

为什么 alloca 两次返回相同的地址?

[英]Why is alloca returning the same address twice?

我正在尝试实现自己的数学库,并且从向量开始。 想法是给 class 一个指向数字数组的指针,然后复制该数组并将其存储在私有变量指针给出的数据地址中。 首先,我使用alloca尝试为私有变量释放一些 memory

vml.h

namespace vml {
    // Vectors
    template <typename in_type, const int in_length>
    class vec {
    public:
        vec(in_type* in_data) {
            std::cout << data << std::endl;
            std::copy(in_data, in_data + in_length, data);
        }
        vec() {
            data = nullptr;
        }
        in_type& operator()(int index) const {
            _ASSERT(0 <= index && index < in_length);
            return data[index];
        }

    private:
        in_type* data = alloca(in_length * sizeof(in_type));
    };

主文件

int main() {
    int list[] = { 1,2,3 };
    int list2[] = {2,4,6 };

    vml::vec<int, 3> a(list);
    vml::vec<int, 3> b(list);

    return 0;
}

这不会产生任何错误,但是由于某种原因, alloca在调用两个实例时会两次返回相同的地址。 我到处搜索这个,我找不到解释为什么。 所以我决定使用数组分配 memory 。 如果你能回答这个问题,那将是非常有帮助的。 谢谢。

你必须非常小心alloca 它在堆栈而不是堆上分配 memory。 只要调用alloca的 function 退出,就会释放 memory。 在这种情况下,它将在构造函数中调用,因此当您调用operator()时,memory 已经被释放并且您正在处理未定义的行为。

除非您确实需要避免堆分配并且您确定不会溢出堆栈并且您了解使用alloca的所有限制,否则最好避开它。

让我们从基础开始,您的堆栈很可能只有 1 MB,因此在几个向量和递归调用之后,您的程序可能会死掉。

如果你想在堆栈上解决它,你可以使用std::array作为data

警告未测试的代码

template <typename in_type, const int in_length>
class vec {
public:
    vec(in_type* in_data) {
        std::cout << data << std::endl;
        std::copy(in_data, in_data + in_length, data);
    }
    vec() = default;
    in_type& operator()(int index) const {
        _ASSERT(0 <= index && index < in_length);
        return data[index];

    }

private:
  std::array<in_type, in_length> data;
};

或者,如果您想使用std::array中的所有好东西

template <typename in_type, const int in_length>
class vec : public std::array<in_type, in_length> {
public:
  using std::array::array; // use constructors, might need template param to compile
}

这也意味着,如果您在某个时候只想更改为堆,您只需像其他 class 一样分配您的 vec。

另一种选择是使用 C++17 PMR,使用堆栈上的分配作为存储并使vec PMR 感知。

您不能将alloca包装在 function 中并将其指针返回到外部,因为包装器 function 的堆栈将被释放。

如果将它作为成员初始化器调用,它实际上是从构造函数调用的,并且可能会在构造函数返回时被释放,然后重新使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM