3

私は 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;
}

_modified を含む .cpp ファイルの 3 行すべてにブレークポイントを設定して、設定/変更/読み取りが行われている場所を正確に確認できるようにしました。シーケンスは次のようになります。

  1. コンストラクターのブレークポイントがトリガーされます。_modified 変数が true に設定されていることを確認
  2. アクセサーのブレークポイントがトリガーされます。_modified 変数は FALSE です!

これは、PageTableEntry のすべてのインスタンスで発生します。クラス自体は変数を変更していません-何か他のものです。残念ながら、私は何を知りません。クラスは new を使用して動的に作成され、ベクトルやマップを含むさまざまな STL 構造に (ポインターとして) 渡されます。ミューテーターは自分のコードから呼び出されることはありません (私はまだその時点に到達していません)。また、STL 構造が呼び出されることはありません。ミューテーターでブレークポイントが呼び出されることはないため、それらが呼び出されていないと想定することしかできません。 .

明らかに、特定の状況下で、誰が何を知っているかによって引き起こされる、クラスのミューテーターを介さずにプライベート変数を変更できる「落とし穴」がありますが、それが何であるかは想像できません。何かご意見は?

更新:各段階でのこの
値: コンストラクター 1: 0x100100210
コンストラクター 2: 0x100100400 アクセサー
1: 0x1001003f0 アクセサー
2: 0x100100440

UPDATE2:
(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));
    }

これらは、問題を引き起こすために PageTableEntry オブジェクトが保存され、STL 構造から取得される唯一のポイントです。他のすべての関数は、testAddr() 関数を使用してエントリを取得します。

UNRELATED: C++ には現在 65663 の質問があり、今日これまでに 164 が質問されているため、今日だけで C++ タグ付きの質問の数が 16 ビットの符号なし整数を超えたことを意味します。使える?いいえ、面白いですか?はい。:)

4

5 に答える 5

9

デバッガーが値を正しく報告していないか (前代未聞ではなく、最適化されたビルドで予想されることさえあります)、プログラムの他の場所でメモリが破損しています。あなたが示したコードは多かれ少なかれ問題なく、期待どおりに動作するはずです。


「UPDATE2」に対応する編集:
問題は次の行にあります:

return (PageTableEntry *)&(*it);

の型は*itisstd::pair<unsigned const, PageTableEntry*>&であるため、 a を a に効果的に再解釈キャストしstd::pair<unsigned const, PageTableEntry*>*ていPageTableEntry*ます。その行を次のように変更します。

return it->second;

コードベース内の他のキャストに注意してください。そもそもキャストが必要なのはコードの匂いであり、キャストを誤って行うと、ここで見られるようにメモリの破損として現れるなど、未定義の動作になる可能性があります。C スタイルのキャストの代わりにC++スタイルのキャストを使用すると、コードベースでキャストが発生する場所を簡単に見つけることができるため、簡単に確認できます (ヒント、ヒント)。

于 2011-04-11T17:02:45.047 に答える
4

std::map<>::find()iterator逆参照されたときに を返す を返しますstd::map<>::value_type。このvalue_type場合の はstd::pair<>です。pairではなく、そのアドレスを返しています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 (*it).second;

PS: C スタイルのキャストは悪です。コンパイラは、C++ キャストを配置して診断を発行します。:)

于 2011-04-11T18:05:49.930 に答える
3

this各ブレークポイントで の値を調べてみてください。

于 2011-04-11T17:01:42.910 に答える
0

STLコンテナーを使用している場合は、そのコピーコンストラクターと代入演算子の両方が頻繁に使用されます。たぶん、あなたがそれらのコードを私たちに見せたら、私たちは何かが間違っているのを見るでしょう。

于 2011-04-11T17:04:23.300 に答える
0

PageTableEntryを追跡するために、クラスに別の一意の値を追加できますか?このような問題が発生したことはわかっています。実際の問題は、同じように見える複数のエントリがあり、ブレークポイントが気付かないうちにPageTableEntryを切り替える可能性があることです。

于 2011-04-11T17:44:07.617 に答える