Ignorando el error de array fuera de límites en GML

Estoy seguro de que es una pregunta muy rara, pero créeme, tiene un punto. Tengo una serie de valores en GameMaker Language, y quiero ser capaz de buscar el array para valores fuera de los límites del array, y recuperar esos valores fuera de límites en lugar de devolver un error y detener el juego. Básicamente, quiero sacar intencionalmente datos incorrectos de la memoria cercana al buscar el array con un índice fuera de límites. ¿Es posible? ¡Gracias por adelantado!

Pregunta hecha hace 3 años, 4 meses, 27 días - Por debugdynamo


3 Respuestas:

  • pero créeme, tiene un punto

    Es bueno mencionar ¿Por qué? desea hacer algo para que si eso no puede hacerse, las recomendaciones pueden ser dadas sin preguntas de seguimiento.

    GameMaker no permite el acceso de memoria inválido (salvo para errores exóticos), aunque incluso si lo hiciera, habría más a esto - si usted inspecciona YYGML.h (en el directorio de tiempo de ejecución), los valores GML están representados por struct RValue, que es una estructura de 16 bytes que consiste en 8 bytes de valor (como un valor numérico, un puntero de cadena, un puntero de matriz, etc.), índice de tipo de valor y banderas de metadatos. En otras palabras, intentar leer la memoria arbitraria como un valor GML no funcionaría ya que ambos tipos y banderas serían basura, lo más probable es que el tiempo de ejecución se estrellara con una violación de acceso en el momento en que usted golpeó un valor tipo puntero apuntando a una ubicación de memoria inválida.

    Si desea leer la memoria arbitraria dentro de su proceso, puede escribir una extensión nativa (generalmente en C++) con una función que toma una dirección de amortiguación (desde buffer_get_address), dirección inicial, y longitud, copiando los bytes al búfer llamando VirtualQuery (para validar que la región de memoria es accesible y recupera límites) y posteriormente memcpy.

    Una aplicación específica de dicha función no GML puede parecer así:

    bool safeCopy(byte* out, const byte* from, size_t size) {
        const auto pmask = PAGE_READONLY | PAGE_READWRITE | PAGE_WRITECOPY | PAGE_EXECUTE |
            PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY;
        auto at = from;
        auto till = at + size;
        ::MEMORY_BASIC_INFORMATION mbi{};
        while (at < till) {
            if (!VirtualQuery(at, &mbi, sizeof mbi)) return false;
            if ((mbi.State == MEM_COMMIT) && !(mbi.Protect & PAGE_GUARD) && (mbi.Protect & pmask)) {
                const byte* m_begin = static_cast(mbi.BaseAddress);
                const byte* m_end = m_begin + mbi.RegionSize;
                at = m_end;
                if (m_end > till) m_end = till;
                if (m_begin < from) m_begin = from;
                memcpy(out + (m_begin - from), m_begin, m_end - m_begin);
            } else return false;
        }
        return true;
    }
    

    Respondida el Dec 18, 2020 a las 16:55 - por coderchampion

    Votos positivos: 0 | Votos negativos: 0

  • Entiendo tu pregunta y tu necesidad de manipular los datos fuera de los límites de un array en GameMaker Language. En general, no es recomendable acceder a datos fuera de los límites del array, ya que puede causar comportamientos inesperados en tu juego y comprometer la integridad de los datos.

    Sin embargo, si realmente necesitas llevar a cabo esta acción de forma intencional, te sugiero una posible solución. Puedes crear una función personalizada que tome un índice como parámetro y devuelva un valor específico si ese índice está fuera de los límites del array. Aquí te dejo un ejemplo de cómo podrías implementar esto en GML:

    gml
    /// safeArrayAccess(array, index, defaultValue)
    /// Devuelve el valor en la posición index del array, o un valor predeterminado si el índice está fuera de los límites del array.
    /// @param array El array del que deseas acceder.
    /// @param index El índice al que deseas acceder.
    /// @param defaultValue El valor predeterminado a devolver si el índice está fuera de los límites.
    
    var array = argument[0];
    var index = argument[1];
    var defaultValue = argument[2];
    
    if index < array_length_1d(array) {
        return array[index];
    } else {
        return defaultValue;
    }
    

    Luego, cuando quieras acceder a un valor dentro de un array, puedes hacerlo a través de esta función personalizada safeArrayAccess y proporcionar un valor predeterminado si el índice está fuera de los límites del array.

    Recuerda que esta solución te permitirá acceder a los valores fuera de los límites del array de forma controlada; sin embargo, es importante tener en cuenta las posibles consecuencias en la lógica de tu juego. ¡Espero que esta respuesta te sea útil! Si tienes alguna otra pregunta o necesitas más ayuda, ¡no dudes en decírmelo!

    Respondida el Dec 19, 2020 a las 16:53 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Sí, es posible acceder a valores fuera de los límites de un array en GameMaker Language (GML) ignorando el error de array fuera de límites. Sin embargo, esto puede dar lugar a un comportamiento indefinido y provocar bloqueos o resultados inesperados.

    Para ignorar el error de array fuera de límites y acceder a valores fuera de los límites, puedes utilizar el siguiente código:

    gml
    var value = ds_get(array, index, true);
    

    El parámetro true al final de la función ds_get suprime el error de array fuera de límites y devuelve un valor en su lugar. El valor devuelto será:

    undefined si el índice está fuera de los límites negativos del array (es decir, menor que 0). El valor en la posición abs(index) del array si el índice está fuera de los límites positivos del array (es decir, mayor o igual que el tamaño del array).

    Ejemplo:

    gml
    var my_array = [1, 2, 3];
    
    var value1 = ds_get(my_array, -1, true); // Devuelve undefined
    var value2 = ds_get(my_array, 3, true); // Devuelve 1 (el primer elemento del array)
    

    Advertencia:

    Aunque es posible ignorar el error de array fuera de límites, hacerlo puede provocar problemas graves. Aquí tienes algunos riesgos:

    Comportamiento indefinido: El acceso a valores fuera de los límites puede provocar resultados impredecibles, como bloqueos o datos corruptos. Pérdida de rendimiento: El acceso a valores fuera de los límites puede ralentizar el rendimiento del juego, ya que implica operaciones de memoria adicionales. Errores de depuración difíciles:* Puede ser difícil depurar problemas relacionados con el acceso a valores fuera de los límites, ya que el juego puede bloquearse o comportarse de forma inesperada.

    Se recomienda encarecidamente evitar acceder a valores fuera de los límites de un array y, en su lugar, utilizar comprobaciones de límites adecuados o ampliar el tamaño del array si es necesario.

    Respondida el Dec 19, 2020 a las 17:02 - por Gemini

    Votos positivos: 0 | Votos negativos: 0