C++布尔变量变化
我有一门C++课程;这个类如下:
首先,标题:
class PageTableEntry {
public:
PageTableEntry(bool modified = true);
virtual ~PageTableEntry();
bool modified();
void setModified(bool modified);
private:
PageTableEntry(PageTableEntry &existing);
PageTableEntry &operator=(PageTableEntry &rhs);
bool _modified;
};
对于 .cpp 文件,
#include "PageTableEntry.h"
PageTableEntry::PageTableEntry(bool modified) {
_modified = modified;
}
PageTableEntry::~PageTableEntry() {}
bool PageTableEntry::modified() {
return _modified;
}
void PageTableEntry::setModified(bool modified) {
_modified = modified;
}
我在 .cpp 文件中涉及 _modified 的所有 3 行上设置了一个断点,这样我就可以准确地看到它们被设置/更改/读取的位置。顺序如下:
- 构造函数中的断点被触发。 _modified 变量被确认设置为 true
- 访问器中的断点被触发。 _modified 变量为 FALSE!
PageTableEntry 的每个实例都会发生这种情况。类本身并没有改变变量——而是其他东西。不幸的是,我不知道是什么。该类是使用 new 动态创建的,并(作为指针)传递到各种 STL 结构,包括向量和映射。我自己的代码从未调用过该变元(我还没有达到这一点),并且 STL 结构不应该能够调用该变元,并且由于变元上从未调用过断点,因此我只能假设它们没有。
显然,存在一些“陷阱”,在某些情况下,私有变量可以在不通过类的变异器的情况下进行更改,由谁知道什么情况触发,但我无法想象它会是什么。有什么想法吗?
更新: 每个阶段this的值:
构造函数1:0x100100210
构造函数2:0x100100400
访问器 1:0x1001003f0
访问器 2:0x100100440
更新 2:
(代码显示访问 PageTableEntry 的位置)
// In constructor:
_tableEntries = std::map<unsigned int, PageTableEntry *>();
// To get an entry in the table (body of testAddr() function, address is an unsigned int:
std::map<unsigned int, PageTableEntry *>::iterator it;
it = _tableEntries.find(address);
if (it == _tableEntries.end()) {
return NULL;
}
return (PageTableEntry *)&(*it);
// To create a new entry:
PageTableEntry *entry = testAddr(address);
if (!entry) {
entry = new PageTableEntry(_currentProcessID, 0, true, kStorageTypeDoesNotExist);
_tableEntries.insert(std::pair<unsigned int, PageTableEntry *>(address, entry));
}
这些是从 STL 结构中存储和检索 PageTableEntry 对象的唯一点,从而导致问题。所有其他函数都使用 testAddr() 函数来检索条目。
无关:由于 C++ 现在有 65663 个问题,并且到目前为止今天已提出 164 个问题,这意味着仅在今天 C++ 标记问题的数量超过了 16 位无符号整数。有用?不,有趣吗?是的。 :)
I have a C++ class; this class is as follows:
First, the header:
class PageTableEntry {
public:
PageTableEntry(bool modified = true);
virtual ~PageTableEntry();
bool modified();
void setModified(bool modified);
private:
PageTableEntry(PageTableEntry &existing);
PageTableEntry &operator=(PageTableEntry &rhs);
bool _modified;
};
And the .cpp file
#include "PageTableEntry.h"
PageTableEntry::PageTableEntry(bool modified) {
_modified = modified;
}
PageTableEntry::~PageTableEntry() {}
bool PageTableEntry::modified() {
return _modified;
}
void PageTableEntry::setModified(bool modified) {
_modified = modified;
}
I set a breakpoint on all 3 lines in the .cpp file involving _modified so I can see exactly where they are being set/changed/read. The sequence goes as follows:
- Breakpoint in constructor is triggered. _modified variable is confirmed to be set to true
- Breakpoint in accessor is triggered. _modified variable is FALSE!
This occurs with every instance of PageTableEntry. The class itself is not changing the variable - something else is. Unfortunately, I don't know what. The class is created dynamically using new and is passed around (as pointers) to various STL structures, including a vector and a map. The mutator is never called by my own code (I haven't gotten to that point yet) and the STL structures shouldn't be able to, and since the breakpoint is never called on the mutator I can only assume that they aren't.
Clearly there's some "gotcha" where private variables can, under certain circumstances, be changed without going through the class's mutator, triggered by who-knows-what situation, but I can't imagine what it could be. Any thoughts?
UPDATE:
The value of this at each stage:
Constructor 1: 0x100100210
Constructor 2: 0x100100400
Accessor 1: 0x1001003f0
Accessor 2: 0x100100440
UPDATE2:
(code showing where PageTableEntry is accessed)
// In constructor:
_tableEntries = std::map<unsigned int, PageTableEntry *>();
// To get an entry in the table (body of testAddr() function, address is an unsigned int:
std::map<unsigned int, PageTableEntry *>::iterator it;
it = _tableEntries.find(address);
if (it == _tableEntries.end()) {
return NULL;
}
return (PageTableEntry *)&(*it);
// To create a new entry:
PageTableEntry *entry = testAddr(address);
if (!entry) {
entry = new PageTableEntry(_currentProcessID, 0, true, kStorageTypeDoesNotExist);
_tableEntries.insert(std::pair<unsigned int, PageTableEntry *>(address, entry));
}
Those are the only points at which PageTableEntry objects are stored and retrieved from STL structures in order to cause the issue. All other functions utilize the testAddr() function to retrieve entries.
UNRELATED: Since C++ now has 65663 questions, and so far 164 have been asked today, that means that only just today the number of C++ tagged questions exceeded a 16-bit unsigned integer. Useful? No. Interesting? Yes. :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
要么您的调试器没有正确报告该值(并非闻所未闻,甚至在优化构建中也是预期的),要么您的程序中其他地方出现了内存损坏。您所展示的代码或多或少都很好,并且应该按照您的预期运行。
与您的“UPDATE2”相对应的编辑:
问题出在这一行:
*it
的类型是std::pair&
,因此您实际上是在重新解释转换std::pair*
到PageTableEntry*
。将该行更改为:留意代码库中的其他转换。首先需要进行强制转换是一种代码味道,并且错误地执行强制转换的结果可能是未定义的行为,包括表现为您在此处看到的内存损坏。使用C++风格的转换而不是C风格的转换,可以轻松地找到代码库中发生转换的位置,以便可以轻松地检查它们(提示,提示< /强>)。
Either your debugger isn't reporting the value correctly (not unheard of, and even expected in optimized builds) or you have memory corruption elsewhere in your program. The code you've shown is more-or-less fine and should behave as you expect.
EDIT corresponding to your 'UPDATE2':
The problem is in this line:
The type of
*it
isstd::pair<unsigned const, PageTableEntry*>&
, so you're effectively reinterpret-casting astd::pair<unsigned const, PageTableEntry*>*
to aPageTableEntry*
. Change that line to:Keep an eye out for other casts in your codebase. Needing a cast in the first place is a code smell, and the result of doing a cast incorrectly can be undefined behavior, including manifesting as memory corruption as you're seeing here. Using C++-style casts instead of C-style casts makes it trivial to find where casts occur in your codebase so they can be reviewed easily (hint, hint).
std::map<>::find()
返回一个iterator
,当取消引用时,它返回一个std::map<>::value_type
>。本例中的value_type
是一个std::pair
。您将返回该对
的地址,而不是PageTableEntry
。我相信你想要以下内容:PS:C 风格的强制转换是邪恶的。编译器将发出带有 C++ 强制转换的诊断信息。 :)
std::map<>::find()
returns aniterator
which when dereferenced returns astd::map<>::value_type
. Thevalue_type
in this case is astd::pair<>
. You're returning the address of thatpair
rather than thePageTableEntry
. I believe you want the following:P.S.: C-style casts are evil. The compiler would have issued a diagnostic with a C++ cast in place. :)
尝试在每个断点处查看
this
的值。Try looking at the value of
this
at each breakpoint.如果您使用 STL 容器,复制构造函数和赋值运算符都会被大量使用。也许如果你向我们展示这些代码,我们会发现一些问题。
That copy constructor and assignment operator are both going to be used a lot if you're using STL containers. Maybe if you show us the code for those, we would see something wrong.
您可以向类添加另一个唯一值来跟踪 PageTableEntry 吗?
我知道我遇到过这样的问题,真正的问题是有多个条目看起来相同,并且断点可能会在我没有意识到的情况下切换 PageTableEntry 。
Could you add another unique value to the class to track the PageTableEntry s?
I know that I've had problems like this where the real problem was that there were multiple entries that looked the same and the breakpoints might switch PageTableEntry s without me realizing it.