Pregunta

He intentado construir una biblioteca de lectura de memoria muy minimalista para leer algunos unsigned ints fuera de él. Sin embargo, me encuentro con un mensaje de "daños en el montón DETECTADO" error cuando el método ReadUnsignedInt quiere volver.

  

daños en el montón detectado. CRT detecta que la aplicación escribe a la memoria después del final del búfer.

Como he leído, esto puede ser la causa cuando se trata de duplicar borrar algo. Esto puede ser causado por algún uso incorrecto de la std::tr1::shared_ptr pero no puede determinar lo que estoy haciendo mal con ellos. Código es el siguiente (manejo de errores omite):

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;
}
¿Fue útil?

Solución

Michael y Naveen tienen ambos se encuentran la misma falla importante en su código, pero no el único defecto.

shared_ptr se delete al cual apunta al objeto cuando su recuento de referencias llega a cero.

Esto significa que sólo puede darle objetos asignados por new -. No new[]

Es posible que desee utilizar shared_ptr<vector<byte> > o boost::shared_array<byte> lugar.

Otros consejos

La cuestión es:

new byte(numberOfBytes)

Esto asigna un único byte con un valor de numberOfBytes.

¿Quieres hacer:

new byte[numberOfBytes]    

Lo que asigna un conjunto de numberOfBytes bytes de longitud.

Pero ya sabes que sólo leyendo 4 bytes, ¿por qué preocuparse de asignar memoria en absoluto? Sólo tiene que pasar la dirección de un entero sin signo en la pila.

Los problemas básicos con su código se han señalado ya. En cuanto a ella, me quedo preguntando qué debería usar un shared_ptr aquí en absoluto, sin embargo. Si lo estuviera haciendo, probablemente usar algo como esto:

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

Por otra parte, en lugar de readUnsignedInt, estaría tentado de usar una plantilla:

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

Ya que no pasa un parámetro a partir del cual se puede deducir el tipo para el parámetro de plantilla, usted siempre tiene que especificar explícitamente:

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

La alternativa sería pasar el destino como un parámetro:

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

, que tendrá que utilizar como:

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

y así sucesivamente.

Si usted está preocupado acerca de la ineficiencia de devolver un vector de carbón, probablemente no debería - VC ++ (como la mayoría de otros compiladores razonablemente actuales) tiene lo que se llama un "valor de retorno optimización llamado", lo que significa que en una situación de esta manera, se pasa una referencia oculta al vector se asigna el resultado a, y readBytes que utilizará para depositar los datos directamente por dónde se va a terminar de todos modos. Para el caso, con cualquier optimización razonable enciende en absoluto, readBytes es casi seguro que terminará como una función en línea, por lo que nada implicada realmente se pone "pasado" o "devuelto" en absoluto.

Por otro lado, este código no funcionará especialmente bien con los compiladores de más edad - y con suficientes compiladores de edad, las versiones que utilizan las funciones de plantilla miembro probablemente ni siquiera compilar. Como siempre y cuando utilice un compilador razonablemente actual, sin embargo, la vida debe ser bueno.

Creo new byte(numberOfBytes) debe new byte[numberOfBytes]. De lo contrario se habría asignado sólo un byte. Sólo para completar la respuesta, como @ephemient indica que no se puede utilizar shared_ptr aquí, ya que va a hacer un delete donde como usted debe hacer delete[]. Si no se hace así, el comportamiento será indefinido.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top