创建临时文件时 std::function 内存访问错误
我目前正在实现一些抽象来表示 3D 对象的水平集操作.基本上是在 this GLSL 着色器的惊人页面中描述的内容.
I'm currently implementing few abstractions to represent level-set operations for 3D objects. Basically what is described in this amazing page for GLSL shaders.
为了简要概述,可以通过将 R^3 域映射到称为水平集(或有符号距离函数)的标量的函数来描述 3D 对象.例如,对于一个球体,水平集函数由 phi(X) = X.Norm2() - R*R
定义,其中 Norm2
表示平方欧几里得范数R^3 中的向量.
To give a brief overview, a 3D object can be described by a function that maps the R^3 domain to a scalar called level-set (or signed-distance-function). For example, for a sphere, the level-set function is defined by phi(X) = X.Norm2() - R*R
where Norm2
represents the squared Euclidean norm of a vector in R^3.
于是我想出了一个代表这样一个概念的LevelSetObject
类:
So I came out with a LevelSetObject
class that represents such a concept:
class LevelSetObject
{
using SDFFunction = std::function<double(double, double, double)>;
protected:
SDFFunction m_SDF;
public:
double SDF(double x, double y, double z) const {
return m_SDF(x, y, z);
}
现在我想在 LevelSetObject
之间定义几个运算符.例如 union 运算符:
Now I wanted to define few operators between LevelSetObject
s. For example the union operator:
LevelSetObject LevelSetObject::operator+(const LevelSetObject& other) const {
LevelSetObject outObj;
outObj.m_SDF = [this, other]
(double x, double y, double z) {
return std::min(m_SDF(x, y, z), other.m_SDF(x, y, z));
};
return outObj;
}
但是,当我创建一个临时对象时,我遇到了糟糕的内存访问,例如,由于三重总和(而如果我在评论的情况下分别对两个对象求和,则使用 Valgrind 而不是 SIGSEV 不会发现内存泄漏).LevelSetSphere
是 LevelSetObject
的派生类,我在其中专门定义了球体的 SDF(给定它的 center
及其 radius
)
But I'm experiencing bad memory access when I create a temporary due to, for example, a triple sum (while if I sum the two objects separately as in the commented case, no memory leak is spotted using Valgrind and not SIGSEV). LevelSetSphere
is a derived class of LevelSetObject
where I define specifically the SDF of a sphere (given its center
and its radius
)
int main(int argc, char* argv[]) {
// Generate the central sphere
double radius = 1.0;
SimpleVector center(2, 2, 2);
LevelSetSphere sphere(radius, center);
// Generate the ears spheres
LevelSetSphere ear1(radius/2, SimpleVector(1, 1, 2));
LevelSetSphere ear2(radius/2, SimpleVector(3, 1, 2));
// Combine objects
auto mickeyMouse = sphere + ear1 + ear2;
//auto first = sphere + ear1;
//auto mickeyMouse = first + ear2;
// Materialize in the domain
mickeyMouse.SDF(0.0, 0.0, 0.0);
}
我想在 operator+
定义中, std::function
保留对 other
的引用,当我实际上调用 m_SDF
因为在三重和期间创建了一个临时文件.我也试过把operator+
的签名改成operator+(const LevelSetObject other)
,这样通过copy,结果还是一样的.
What I suppose is that in the operator+
definition, the std::function
keeps a reference to other
that becomes a dangling reference when I actually call m_SDF
because a temporary is created during the triple sum. I also tried to change the signature of operator+
to operator+(const LevelSetObject other)
, so passing by copy, but the outcome is the same.
我在哪里失败了?:)
推荐答案
你的错误内存访问不是由于 other
变量,而是 this
的指针临时对象超出范围.
Your bad memory access isn't due to the other
variable, it's the this
pointer of the temp object going out of scope.
您可以通过显式捕获 SDF 变量来修复它,如下所示:
You can fix it by capturing the SDF variables explicitly, like this:
LevelSetObject LevelSetObject::operator+(const LevelSetObject& other) const {
LevelSetObject outObj;
auto& SDF=this->m_SDF;
auto& other_SDF=other.m_SDF
outObj.m_SDF = [SDF, other_SDF]
(double x, double y, double z) {
return std::min(SDF(x, y, z), other_SDF(x, y, z));
};
return outObj;
}
相关文章