سؤال

لقد حاولت بناء مكتبة قراءة ذاكرة للغاية لقراءة بعض unsigned intS خارجها. ومع ذلك ، واجهت رسالة خطأ "الكشف المكتشف" عندما تكون ReadUnsignedInt الطريقة تريد العودة.

اكتشاف فساد كومة. اكتشف CRT أن التطبيق كتب إلى الذاكرة بعد نهاية المخزن المؤقت.

كما قرأت ، قد يكون هذا هو السبب عند محاولة حذف شيء ما. قد يكون هذا سبب بعض الاستخدام غير الصحيح لـ std::tr1::shared_ptr لكن لا يمكنني تحديد ما أفعله خطأ معهم. الكود كما يلي (تم حذف معالجة الأخطاء):

unsigned int Memory::ReadUnsignedInt (unsigned int address) const {
    std::tr1::shared_ptr<byte> bytes = 
        this->ReadBytes(address, sizeof(unsigned int));
    return *((int*)bytes.get());
    // correct value (how to improve this ugly piece of code?)
}

std::tr1::shared_ptr<byte> Memory::ReadBytes (
    unsigned int address, int numberOfBytes) const
{
    std::tr1::shared_ptr<byte> pBuffer(new byte(numberOfBytes));
    ReadProcessMemory(m_hProcess.get(), (LPCVOID)address, 
        pBuffer.get(), numberOfBytes * sizeof(byte), NULL))
    return pBuffer;
}
هل كانت مفيدة؟

المحلول

وجد كل من مايكل ونافين نفس العيب الرئيسي في الكود الخاص بك ، ولكن ليس العيب الوحيد.

shared_ptr إرادة delete كائن مدبب AT عندما يذهب عدد المرجع إلى الصفر.

هذا يعني أنه يمكنك فقط إعطائها كائنات مخصصة من قبل new -- ليس new[].

قد ترغب في استخدام shared_ptr<vector<byte> > أو boost::shared_array<byte> في حين أن.

نصائح أخرى

والقضية هي:

new byte(numberOfBytes)

هذا يخصص بايت واحد مع قيمة numberOfbytes.

تريد ان تفعل:

new byte[numberOfBytes]    

الذي يخصص مجموعة من bytes numberofbytes طويلة.

ولكن بما أنك تعلم أنك تقرأ فقط 4 بايت ، فلماذا تهتم بتخصيص الذاكرة على الإطلاق؟ فقط تمرير عنوان int غير موقعة على المكدس.

تمت الإشارة إلى المشكلات الأساسية في الكود الخاص بك بالفعل. بالنظر إلى ذلك ، تركت أتساءل عن سبب استخدامك لـ shared_ptr هنا على الإطلاق. إذا كنت أفعل ذلك ، فربما أستخدم شيئًا كهذا:

unsigned Memory::ReadUnsignedInt(unsigned address) { 
    unsigned ret;
    ReadProcessMemory(m_hProcess.get(), (void *)address, &ret, sizeof(ret), NULL);
    return ret;
}

std::vector<char> Memory::ReadBytes(unsigned address, int num) { 
    std::vector<char> ret(num);
    ReadProcessMemory(m_hProcess.get(), (void *)address, &ret[0], num, NULL);
    return ret;
}

ثم مرة أخرى ، بدلاً من ReadUnsignedInt ، سأغري استخدام قالب:

template <class T>
T Memory::Read(unsigned address) { 
    T ret;
    ReadProcessMemory(m_hProcess.get(), (void*)address, &ret, sizeof(ret), NULL);
    return ret;
}

نظرًا لأنك لا تمرر معلمة يمكنها من خلالها استنتاج النوع لمعلمة القالب ، يجب عليك دائمًا تحديد صراحة:

int x = Read<int>(wherever);
char a = Read<char>(wherever);

سيكون البديل هو تمرير الوجهة كمعلمة:

template <class T>
Memory::Read(unsigned address, T &t) { 
    ReadProcessMemory(my_hProcess.get(), (void *)address, &t, sizeof(t), NULL);
};

ما الذي تستخدمه مثل:

Read(wherever, some_int);
Read(somewhere, some_long);

وهلم جرا.

إذا كنت قلقًا بشأن عدم كفاءة إرجاع ناقل char ، فمن المحتمل ألا يكون ذلك - VC ++ (مثل معظم المترجمين الحاليين المعقولين) لديه ما يسمى "تحسين قيمة الإرجاع المسماة" ، مما يعني في مثل هذا الموقف ، ، إنه يمرر مرجعًا خفيًا إلى المتجه الذي تقوم بتعيينه للنتيجة ، وسوف تستخدم ReadBytes ذلك لإيداع البيانات مباشرة حيث سينتهي الأمر على أي حال. لهذه المسألة ، مع تشغيل أي تحسين معقول على الإطلاق ، سينتهي ReadBytes تقريبًا كدالة مضمونة ، لذلك لا يتم إرجاع أي شيء متورط حقًا أو "يتم إرجاعه" على الإطلاق.

من ناحية أخرى ، لن يعمل هذا الرمز بشكل جيد بشكل خاص مع المترجمين الأكبر سناً - ومع المترجمين القدامى بما فيه الكفاية ، فإن الإصدارات التي تستخدم وظائف قالب الأعضاء ربما لن يتم تجميعها. طالما أنك تستخدم برنامج التحويل البرمجي الحالي بشكل معقول ، يجب أن تكون الحياة جيدة.

أعتقد new byte(numberOfBytes) يجب ان يكون new byte[numberOfBytes]. وإلا فإنك قد خصصت بايت واحد فقط. فقط لإكمال الإجابة ، كما أشار ephemient أنه لا يمكنك استخدام shared_ptr هنا لأنها ستفعل delete حيث يجب أن تفعل delete[]. إذا لم يتم القيام بذلك ، فلن يكون السلوك غير محدد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top