solucionar solucion segmentation generado error dumped c++ linux memory-management out-of-memory

c++ - solucion - segmentation faults



Malloc optimista para Linux: ¿siempre se lanzará nuevo cuando esté fuera de la memoria? (5)

Creo que el malloc aún puede devolver NULL. La razón es que hay una diferencia entre la memoria del sistema disponible (RAM + intercambio) y la cantidad en el espacio de direcciones de su proceso.

Por ejemplo, si solicita 3 GB de memoria de malloc en un x86 linux estándar, seguramente devolverá NULL ya que esto es imposible dada la cantidad de memoria otorgada a las aplicaciones de espacio de usuario.

He estado leyendo sobre las condiciones de falta de memoria en Linux, y el siguiente párrafo de las páginas man me hizo pensar:

Por defecto, Linux sigue una estrategia de asignación de memoria optimista. Esto significa que cuando malloc () devuelve un valor no nulo, no hay garantía de que la memoria esté realmente disponible. Este es un error realmente malo. En caso de que el sistema se quede sin memoria, el infame asesino OOM matará uno o más procesos. [...]

Teniendo en cuenta que la nueva implementación del operador terminará llamando malloc en algún momento, ¿hay alguna garantía de que lo nuevo arroje realmente en Linux? Si no hay, ¿cómo se maneja esta situación de error aparentemente indetectable?


Depende; puedes configurar los valores de overcommit del kernel usando vm.overcommit_memory.

Herb Sutter discutió hace unos años cómo este comportamiento en realidad no cumple con el estándar de C ++ :

"En algunos sistemas operativos, incluido específicamente Linux, la asignación de memoria siempre tiene éxito. Punto final. ¿Cómo puede la asignación siempre tener éxito, incluso cuando la memoria solicitada realmente no está disponible? La razón es que la asignación misma simplemente registra una solicitud de la memoria; debajo de las cubiertas, la memoria (física o virtual) no está realmente comprometida con el proceso de solicitud, con un almacén de respaldo real, hasta que la memoria se use realmente.

"Tenga en cuenta que, si el nuevo utiliza directamente las instalaciones del sistema operativo, las nuevas siempre tendrán éxito, pero cualquier código inocente posterior como buf [100] = ''c''; puede arrojar o fallar o detenerse. Desde un punto de vista estándar de C ++, ambos efectos no son conformes, porque el estándar de C ++ requiere que si el nuevo no puede comprometer suficiente memoria debe fallar (esto no), y ese código como buf [100] = ''c'' no debería arrojar una excepción o de lo contrario fallar (esto podría)."


No puedes manejarlo en tu software, puro y simple.

Para su aplicación, recibirá un puntero perfectamente válido. Una vez que intente acceder, generará un error de página en el kernel, el kernel intentará asignarle una página física y si no puede ... boom.

Pero como ve, todo esto sucede dentro del kernel, su aplicación no puede ver eso. Si se trata de un sistema crítico, puede deshabilitar el overcommit alltogether en el sistema.


Perdóneme si me equivoco, pero ¿no sería suficiente tratar de poner a cero la memoria asignada para garantizar que tiene todos los bytes que ha solicitado? O incluso escribiendo en el último byte, arrojaría una excepción si el recuerdo no era realmente suyo, ¿verdad?

Si eso es cierto, podría intentar escribir en el último (¿y el primero?) Byte de la memoria y ver si funciona bien, y si no puede devolver nulo desde malloc.


Sí, hay una garantía de que lo nuevo finalmente arrojará. Independientemente del exceso de compromiso, la cantidad de espacio de direcciones es limitada. Por lo tanto, si sigue asignando memoria, tarde o temprano se le agotará el espacio de direcciones y se forzará a lanzar algo nuevo.