gpt4 book ai didi

c++ - 调用成员函数时更改此指针

转载 作者:行者123 更新时间:2023-11-30 03:48:56 27 4
gpt4 key购买 nike

首先,对于这个不清楚的问题,我们事先表示歉意-如果我知道要问什么,我可能会知道如何解决。
...尽管有七年的C++经验,但我什至没有模糊的理论。任何有用的指针(hè)都将不胜感激。

  • 可能与this question有关。 (相同的症状)
  • that one不相关。 (此处没有显式函数指针)

  • 问题:具有某些属性的对象计数(本身由其类的成员函数检查)显示错误的结果。来源是,检查是使用乱码进行的。其来源是指针“this”在调用函数和进入函数体之间改变。一旦离开 body ,指针再次正确。

    可悲的是,相关问题的解决方案在这里不起作用。

    我无法提供此问题的最小示例。
    而且,据我所知,实际上在同一个程序中正确地调用了数百个成员函数,而没有表现出这种行为。
  • 我该怎么办?
    作为创可贴,用函数主体的副本替换函数调用是可行的,但这不是适当的解决方案。

  • 我对如何进行诊断完全不知所措。

    简洁: 我可以采取哪些步骤来深入了解问题的本质?

    一份简短的 list ,说明已经处理的事情:
  • 所涉及的对象在调用时已正确初始化。
  • 关闭所有优化。没有内联。这是具有适当设置有效的调试版本。
  • 清洁和重建项目没有产生不同的结果。
  • 成功测试了创可贴解决方案后,使用原始(但已重新键入)功能调用进行重新编译导致问题返回。
  • 涉及的编译单元中没有编译器警告(警告级别3),特别是在整个项目范围内,禁用以下警告:
  • C4005(宏重新定义,由于出于兼容性原因使用自定义/被入侵的Windows SDK-最初是Win95程序)
  • C4244(由于等待重构的遗留代码,隐式转换为较小的类型-都是缺少显式转换的float-to-int转换,它们全部有800多个实例)
  • C4995(不推荐使用带有#pragma标记的调用函数,因为在没有下划线的情况下调用了C-lib函数-希望最终切换到GCC)
  • “控制流防护”和“基本运行时检查”已启用,但不触发。

  • 还有一个提示可能相关或不相关,但我目前无法解释:
  • 对于第一个十六进制,通常会调用IsSea,即:内部的“this”与外部的
  • 相同。
  • 仅在随后的所有十六进制中都会发生此错误。
  • 更改后的“this”指针虽然未指向第一个十六进制,但似乎命中了未分配的空间。

  • 以下是其外观的摘录:

    header :
    // These three are actually included from other files.
    constexpr unsigned int AREA_none = 0u;
    constexpr unsigned int AREA_Lake = 1u;
    enum Terrain
    {
    OCEAN = 8,
    TERRA_INCOGNITA = 10
    };

    class CHex
    {
    public:
    CHex(); // initialises ALL members with defined error values
    bool ReadHex(); // Init-type function calling the problematic one
    bool IsSea() const // problematic function
    { return this->_Area != AREA_none && this->_Area != AREA_LAKE && this->_nTerrain == Terrain::OCEAN; }
    // The body does the right thing - just WITH the wrong thing.
    protected:
    unsigned int _Area;
    int _nNavalIndex;
    Terrain _nTerrain;

    static int _nNavalCount = 0;

    // There are a lot more functions in here, both public and protected.
    // The class also inherits a bunch from three other classes, but no virtual functions and no overlaps are involved.
    }

    资源:
    CHex::CHex() : _Area{0u}, _nNavalIndex{0}, _nTerrain{Terrain::TERRA_INCOGNITA}
    {}
    bool CHex::ReadHex()
    {
    // Calls a lexer/parser pair to procure values from several files.
    // _Area and _nTerrain are being initialised in this process.
    // All functions called here work as expected and produce data matching the source files.

    // _Area and _nTerrain have the correct values seen in the source files at this point.
    if(this->IsSea()) // but inside that it looks as if they were uninitialised
    // This ALWAYS happens because the function always returns true.
    _nNavalIndex = _nNavalCount++;
    // Stopping at the next instruction, all values are again correct
    // - with the notable exception of the two modified by the instruction that should not have happened.

    // If I replace that with the following, I receive the correct result:
    /*
    // direct copy of the function's body
    if(this->_Area != AREA_none && this->_Area != AREA_Lake && this->_nTerrain == Terrain::OCEAN)
    _nNavalIndex = _nNavalCount++; // only happens when it should; at the end, the count is correct
    */

    // Sanity checks follow here.
    // They too work correctly and produce results appropriate for the data.

    return true; // earlier returns exist in the commented-out parts
    }

    再次抱歉造成这么大的困惑,但是好吧,现在 很烂。就像看到物理学的基本定律发生变化一样。

    -

    在@Ben Voigt的建议下,我侵入了一个诊断程序,该诊断程序将指针转储到文件中。看哪:
    Before ReadHex: 20A30050 (direct array access) On ReadHex:  20A30050    On IsSea:   20A30050 (with members: 0, 8) After ReadHex:    20A30050 
    Before ReadHex: 20A33EAC (direct array access) On ReadHex: 20A33EAC On IsSea: 20A33EAC (with members: 2, 0) After ReadHex: 20A33EAC
    Before ReadHex: 20A37D08 (direct array access) On ReadHex: 20A37D08 On IsSea: 20A37D08 (with members: 2, 0) After ReadHex: 20A37D08
    Before ReadHex: 20A3BB64 (direct array access) On ReadHex: 20A3BB64 On IsSea: 20A3BB64 (with members: 3, 0) After ReadHex: 20A3BB64
    Before ReadHex: 20A3F9C0 (direct array access) On ReadHex: 20A3F9C0 On IsSea: 20A3F9C0 (with members: 4, 3) After ReadHex: 20A3F9C0
    Before ReadHex: 20A4381C (direct array access) On ReadHex: 20A4381C On IsSea: 20A4381C (with members: 3, 0) After ReadHex: 20A4381C
    [...]

    他们都是正确的。他们每个人。 甚至更好:该函数现在可以正确评估!
    这是更改的来源(这次我省略了评论):

    header :
    // These three are actually included from other files.
    constexpr unsigned int AREA_none = 0u;
    constexpr unsigned int AREA_Lake = 1u;
    enum Terrain
    {
    OCEAN = 8,
    TERRA_INCOGNITA = 10
    };

    extern FILE * dump;
    class CHex
    {
    public:
    CHex();
    bool ReadHex();
    bool IsSea() const {
    fprintf(dump, "\tOn IsSea:\t%p (with members: %u, %i) ", (void*)this, this->_Area, this->_nTerrain);
    return this->_Area != AREA_none && this->_Area != AREA_LAKE && this->_nTerrain == Terrain::OCEAN; }
    protected:
    unsigned int _Area;
    int _nNavalIndex;
    Terrain _nTerrain;

    static int _nNavalCount = 0;

    // lots more functions and attributes
    }

    资源:
    CHex::CHex() : _Area{0u}, _nNavalIndex{0}, _nTerrain{Terrain::TERRA_INCOGNITA}
    {}
    bool CHex::ReadHex()
    {
    fprintf(dump, "On ReadHex:\t%p ", (void*)this);

    // Calls a lexer/parser pair to procure values from several files.
    // _Area and _nTerrain are being initialised in this process.

    if(this->IsSea()) // Suddenly works!?
    _nNavalIndex = _nNavalCount++;

    // Sanity checks follow here.

    fprintf(dump, "After ReadHex:\t%p ", (void*)this);
    return true;
    }

    额外的输出(以及转储的初始化和关闭)来自控制流中的下一个更高级别,另一个类中的另一个函数,所有十六进制的循环都位于其中。我暂时省略了它,但是如果有人认为它很重要,将添加它。

    还有那个。现在,在我看来,该错误是由工具(而非代码)中的错误导致的。实际上,即使函数现在可以正确评估,调试器 仍然仍显示以前的错误指针及其无意义的成员。

    最佳答案

    编辑OP编辑:

    现在,这闻起来更像是违反了ODR。更改内联函数并更改程序行为,正是由违反ODR引起的未定义行为可能发生的情况。您在任何地方都使用模板吗?另外,请尝试在原始版本中取消内联IsSea()以查看是否有帮助。

    (原始答案):
    这闻起来对我来说就像三件事之一。

    首先,它可能是有关功能违反一定义规则的情况。绝对确定在不同的翻译单元中没有多个版本,在不同的单元中没有不同的编译设置。

    其次,由于使用了保留名称_Area,编译器可能正在做某些事情。无论采取任何其他措施,都应解决此问题。

    第三,VC++可以对成员函数指针使用不同的机制,并且其中一种可能会影响您的情况(即使假设您未显示成员函数指针的使用)。有关更多信息,请参见https://msdn.microsoft.com/en-us/library/83cch5a6.aspx?f=255&MSPPError=-2147217396。另一种可能性是,跨翻译单元,此类指针的编译器选项会有所不同。

    关于c++ - 调用成员函数时更改此指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32897902/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com