Esta página aún no se ha traducido para esta versión. Puede ver la versión más reciente de esta página en inglés.

Problemas de administración de memoria

Visión general

Nota

Los ejemplos de este tema usan funciones en la API intercalada compleja. Para compilar aplicaciones con estas funciones, llame con la opción específica de la versión.mex-R2018a

Cuando una función MEX devuelve el control a, devuelve los resultados de sus cálculos en los argumentos de salida, la s contenida en los argumentos del lado izquierdo.MATLAB®mxArrayplhs[] Estas matrices deben tener un ámbito temporal, por lo que no pase matrices creadas con la función en. destruye cualquier creado por la función MEX que no está en. también libera cualquier memoria que se asignó en la función MEX utilizando el,, o funciones.mexMakeArrayPersistentplhsMATLABmxArrayplhsMATLABmxCallocmxMallocmxRealloc

En general, recomienda que las funciones MEX destruyan sus propias matrices temporales y liberen su propia memoria asignada dinámicamente.MathWorks® Es más eficaz realizar esta limpieza en el archivo MEX de origen que depender del mecanismo automático. Este enfoque es coherente con otras aplicaciones de API (aplicaciones de archivo MAT, aplicaciones de motor yMATLAB MATLABCompiler™ aplicaciones generadas, que no tienen ningún mecanismo de limpieza automática.)

Sin embargo, no destruya una en un archivo MEX fuente cuando es:mxArray

  • pasa al archivo MEX en la lista lateral derechaprhs[]

  • devueltos en la lista del lado izquierdoplhs[]

  • devueltos pormexGetVariablePtr

  • utiliza para crear una estructura

En esta sección se describen situaciones específicas para la administración de memoria. Se recomienda que revise el código en los archivos MEX de origen para evitar el uso de estas funciones en las siguientes situaciones. Para obtener más información, consulte y.Limpieza automática de matrices temporalesMxArrays persistentes Para obtener orientación sobre problemas de memoria, consulte.Strategies for Efficient Use of Memory

Los posibles problemas de administración de memoria incluyen:

Destruir incorrectamente unamxArray

No usar para destruir un.mxFreemxArray

Ejemplo

En el ejemplo siguiente, no destruye el objeto de matriz.mxFree Esta operación libera el encabezado de estructura asociado con la matriz, pero sigue funcionando como si el objeto de matriz debe destruirse.MATLAB Así intenta destruir el objeto Array, y en el proceso, intenta liberar de nuevo su cabecera de estructura:MATLAB

mxArray *temp = mxCreateDoubleMatrix(1,1,mxREAL);       ... mxFree(temp);  /* INCORRECT */

Solución

Llame en su lugar:mxDestroyArray

mxDestroyArray(temp);  /* CORRECT */

Construir incorrectamente una celda o estructuramxArray

No llame o variantes con como la matriz de miembros.mxSetCellmxSetFieldprhs[]

Ejemplo

En el ejemplo siguiente, cuando el archivo MEX devuelve, destruye toda la matriz de celdas.MATLAB Puesto que esto incluye a los miembros de la celda, esto destruye implícitamente los argumentos de entrada del archivo MEX. Esto puede causar varios resultados extraños, por lo general teniendo que ver con la corrupción del área de trabajo del llamador, si el argumento del lado derecho utilizado es una matriz temporal (por ejemplo, un literal o el resultado de una expresión):

myfunction('hello') /* myfunction is the name of your MEX file and your code /* contains the following:    */      mxArray *temp = mxCreateCellMatrix(1,1);       ...     mxSetCell(temp, 0, prhs[0]);  /* INCORRECT */

Solución

Haga una copia del argumento del lado derecho con y use esa copia como argumento (o variantes).mxDuplicateArraymxSetCellmxSetField Por ejemplo:

mxSetCell(temp, 0, mxDuplicateArray(prhs[0]));  /* CORRECT */

Creación de un temporal con datos incorrectosmxArray

No llame a los cuyos datos no se asignaron por una rutina de API.mxDestroyArraymxArray

Ejemplo

Si llama, o cualquiera de las funciones de acceso a datos con tipo que especifican la memoria que no fue asignada por, o como el bloque de datos previsto (segundo argumento), a continuación, cuando el archivo MEX vuelve, intenta liberar los punteros a datos reales y datos imaginarios (si los hay).mxSetDoublesmxSetComplexDoublesmxCallocmxMallocmxReallocMATLAB Por lo tanto, intenta liberar memoria, en este ejemplo, de la pila del programa:MATLAB

mxArray *temp = mxCreateDoubleMatrix(0,0,mxREAL); double data[5] = {1,2,3,4,5};       ... mxSetM(temp,1); mxSetN(temp,5); mxSetDoubles(temp, data);  /* INCORRECT */

Solución

En vez de usar para establecer el puntero de datos, en su lugar, cree el con el tamaño correcto y utilice para copiar los datos de la pila en el búfer devuelto por:mxSetDoublesmxArraymemcpymxGetDoubles

mxArray *temp = mxCreateDoubleMatrix(1,5,mxREAL); double data[5] = {1,2,3,4,5};       ... memcpy(mxGetDoubles(temp), data, 5*sizeof(double)); /* CORRECT */

Crear fugas de memoria potenciales

Antes de la versión 5,2, si ha creado una utilizando una de las rutinas de creación de API y, a continuación, ha sobreescrito el puntero a los datos utilizando, todavía liberado la memoria original. ya no libera la memoria.mxArraymxSetDoublesMATLABMATLAB

Por ejemplo:

pr = mxCalloc(5*5, sizeof(double)); ... <load data into pr> plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL); mxSetDoubles(plhs[0], pr);  /* INCORRECT */

ahora fugas 5 * 5 * 8 bytes de memoria, donde 8 bytes es el tamaño de un.double

Puede evitar esa fuga de memoria cambiando el código a:

plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL); pr = mxGetDoubles(plhs[0]); ... <load data into pr> 

o alternativamente:

pr = mxCalloc(5*5, sizeof(double)); ... <load data into pr> plhs[0] = mxCreateDoubleMatrix(5,5,mxREAL); mxFree(mxGetDoubles(plhs[0])); mxSetDoubles(plhs[0], pr);

La primera solución es más eficiente.

También pueden producirse fugas de memoria similares al usar,,, o cualquiera de las funciones numéricas de acceso a datos con tipo.mxSetDoublesmxSetComplexDoublesmxSetIrmxSetJc Puede evitar fugas de memoria cambiando el código como se describe en esta sección.

Destruir incorrectamente una estructura

Para una estructura, debe llamar sólo en la estructura, no en las matrices de datos de campo.mxDestroyArray Un campo de la estructura apunta a los datos de la matriz utilizada por o.mxSetFieldmxSetFieldByNumber Cuando destruye la estructura, intenta atravesar por sí mismo y liberar todos los demás datos, incluida la memoria en las matrices de datos.mxDestroyArray Si se llama en cada matriz de datos, la misma memoria se libera dos veces que puede dañar la memoria.mxDestroyArray

Ejemplo

En el ejemplo siguiente se crean tres matrices: una matriz de estructura y dos matrices de datos, y.aStructmyDataOnemyDataTwo Nombre de campo contiene un puntero a los datos en y nombre de campo contiene un puntero a los datos en.onemyDataOnetwomyDataTwo

mxArray *myDataOne;  mxArray *myDataTwo;  mxArray *aStruct;  const char *fields[] = { "one", "two" };    myDataOne = mxCreateDoubleScalar(1.0);  myDataTwo = mxCreateDoubleScalar(2.0);    aStruct = mxCreateStructMatrix(1,1,2,fields);  mxSetField( aStruct, 0, "one", myDataOne );  mxSetField( aStruct, 1, "two", myDataTwo );  mxDestroyArray(myDataOne);  mxDestroyArray(myDataTwo); mxDestroyArray(aStruct); /* tries to free myDataOne and myDataTwo */ 

Solución

El comando destruye los datos de las tres matrices:mxDestroyArray(aStruct)

      ... aStruct = mxCreateStructMatrix(1,1,2,fields);  mxSetField( aStruct, 0, "one", myDataOne );  mxSetField( aStruct, 1, "two", myDataTwo );  mxDestroyArray(aStruct);  

Destruir memoria en un destructor de clase de C++

No utilice las funciones o en un destructor de C++ de una clase utilizada en una función MEX.mxFreemxDestroyArray Si la función MEX arroja un error, limpia las variables MEX-File, como se describe en.MATLABLimpieza automática de matrices temporales

Si se produce un error que hace que el objeto salga del ámbito, llama al destructor de C++.MATLAB Liberar memoria directamente en el destructor significa que ambos y el destructor liberan la misma memoria, que puede dañar la memoria.MATLAB

Consulte también

|

Temas relacionados