【问题标题】:Access violation reading location 0xFFFFFFFFFFFFFFFF访问冲突读取位置 0xFFFFFFFFFFFFFFFF
【发布时间】:2016-05-28 05:48:27
【问题描述】:

我正在尝试使用 OpenGL 来演示分层动画。在早期阶段,我试图为我的“骨骼”对象提供对其父对象的引用。

在我的骨骼类中,我可以成功添加父级,但问题是当我调用 hasParent() 时。它无法读取 this->parent 并崩溃,但出现以下异常:

myprogram.exe 中 0x00007FF6CB723D43 处的未处理异常:0xC0000005:访问冲突读取位置 0xFFFFFFFFFFFFFFFF。**

我的骨骼类的片段:

void Bone::addParent(Bone *bone)
{
    this->parent = bone;
    assert(this->parent);
}

bool Bone::hasParent()
{
    assert(this->parent); //this line causes the error
    if (this->parent)
        return true;
    else return false;
}

glm::mat4 Bone::getBoneModel()
{
    glm::mat4 parentModel = glm::mat4(1.0);
    if (hasParent())
        parentModel = parent->getBoneModel();
    //boneModel = parentModel * boneModel;
    return boneModel;
}

精简了我的主要内容:

#define NUMBONES 3
Bone bone[NUMBONES];

int main( void )
{
    //------------------ Create Bones --------------------------
    float y = 0.0f;
    for (int i = 0; i < NUMBONES; i++)
    {
        bone[i] = Bone(i, vec3(0, y, -30), vec3(0, 0, 0), vec3(0, 0, 0));
        y += 5.0f;
    }

    //----------------- Make relationships ----------------
    bone[0].isRoot = true;
    bone[0].addChild(&bone[1]);
    bone[0].addChild(&bone[2]);
    bone[1].addParent(&bone[0]);
    bone[1].addChild(&bone[2]);
    bone[2].addParent(&bone[1]);

    do{
        ModelMatrix = bone[1].getBoneModel();
    }
    return 0;
}

我发现引用和指针很难理解,所以我希望这对其他人来说是显而易见的!

编辑:

我的构造函数:

Bone::Bone() {
    parent = NULL;
    child = NULL;
    boneID = 0;
    boneModel = glm::mat4(1.0);
}

Bone::Bone(int ID, glm::vec3 T, glm::vec3 R, glm::vec3 S)
{
    boneID = ID;
    isRoot = false;
    pos = T;

    //---------- set boneModel ------------------
    glm::mat4 RotationMatrix = glm::mat4(1.0);
    glm::mat4 TranslationMatrix = translate(glm::mat4(), pos);
    glm::mat4 ScalingMatrix = scale(glm::mat4(), glm::vec3(1.0f, 1.0f, 1.0f));
    boneModel = TranslationMatrix * RotationMatrix * ScalingMatrix;

    std::cout << "bone[" << boneID << "] created.\n";

}

【问题讨论】:

  • 如果您在调试器中运行它并从发生错误的位置获取堆栈跟踪,您可能会发现这要容易得多。
  • 请显示Bone类的构造函数。是否初始化parent
  • 哪一行代码导致了错误?
  • 我没有在构造函数中初始化父级。错误是hasParent()的第一行,assert(this->parent)。
  • 你应该在Bone::Bone(int ID, glm::vec3 T, glm::vec3 R, glm::vec3 S)中初始化父子节点,否则它会有一个随机的垃圾值。

标签: c++ access-violation


【解决方案1】:

添加

parent = NULL;
child = NULL;

到第二个构造函数Bone(int ID, glm::vec3 T, glm::vec3 R, glm::vec3 S)

【讨论】:

  • 最好在初始化列表中完成。对于原始类型来说不是那么重要,但是例如,对于 boneModel 在构造函数中设置它会导致默认的 mat4 构造函数不必要地运行。
【解决方案2】:

你不需要

assert(this->parent)

在 Bone::hasParent() 的第一行。断言某事意味着您希望它始终为真。但是,为什么你首先要有函数 hasParent() 呢?当执行此行并且父级未初始化时,您的程序将崩溃。如果您删除断言,它应该可以工作。

那么你也应该在第二个构造函数中初始化父子和子(可能是 nullptr)。

与您的问题无关,但为了改进您的 C++ 风格,您不应该使用#define 来定义常量。改用 const,例如

const unsigned int NUM_BONES

参见,例如,"static const" vs "#define" vs "enum"

【讨论】:

  • 如果取出断言,if(this->parent) 之后的行仍然会出现相同的错误
  • 这不可能是这个错误的原因...问题是父级没有在所有构造函数中初始化
  • @Claire 即使该断言不是您当前的问题,但只要您在没有断言的 Bone 上调用 hasParent() ,它就会变成一个。
【解决方案3】:

由@drescherjm 解决:

我需要在 Bone::Bone(int ID, glm::vec3 T, glm::vec3 R, glm::vec3 S) 中初始化 'parent = NULL'

Bone::Bone(int ID, glm::vec3 T, glm::vec3 R, glm::vec3 S)
{
    parent = NULL;
    boneID = ID;
    isRoot = false;
    pos = T;

    //---------- set boneModel ------------------
    glm::mat4 RotationMatrix = glm::mat4(1.0);
    glm::mat4 TranslationMatrix = translate(glm::mat4(), pos);
    glm::mat4 ScalingMatrix = scale(glm::mat4(), glm::vec3(1.0f, 1.0f, 1.0f));
    boneModel = TranslationMatrix * RotationMatrix * ScalingMatrix;

    std::cout << "bone[" << boneID << "] created.\n";

}

【讨论】:

  • 也初始化子节点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
相关资源
最近更新 更多