Inicialicé mi puntero a 10 ints usando malloc (). Aún así puedo escribir el elemento en la posición 11 y usarlo. ¿Por qué está pasando esto?

Las computadoras de hoy usan memoria virtual.
La unidad de memoria que el sistema operativo otorga a un proceso es la página (generalmente unos pocos KB, podría ser diferente)
Cuando se realizó su llamada a malloc, la matriz se asignó en la página.
La pregunta importante aquí es, ¿dónde está el final de la matriz wrt el límite de la página?

  1. El final de la matriz y la página no se encuentran. Tienes algo de espacio después del final de la matriz en esa página
  2. Fin de la matriz y la página se encuentran.

Tenga en cuenta que la matriz también puede cruzar muchas páginas.

Como se garantiza que una página se asignará a una ubicación física, cualquier acceso dentro del límite de la página pasará
Si la ubicación a la que accede está fuera y no está asignada a una ubicación física, se bloquea. Principalmente con una señal SIGSEGV enviada por el sistema operativo, también conocido como error de segmentación.

Si el undécimo elemento es una ubicación de memoria asignada a una ubicación física, puede escribir.
De lo contrario, falla.

En C, puede escribir casi cualquier ubicación y acceder a ella. Pero aquí está accediendo a una ubicación en la memoria de almacenamiento dinámico que no ha asignado explícitamente. Es posible que esto no dé ningún error en programas pequeños y que también pueda acceder a las ubicaciones 12th 13th …
Sin embargo, esto causará un problema en programas más grandes donde hay muchos mallocs y terminará corrompiendo la memoria asignada a otro puntero y depurando, lo que será una pesadilla.

Malloc tiene varias implementaciones, pero generalmente descubre un espacio contiguo del tamaño requerido en el montón y le devuelve un puntero. En algunos casos, el tamaño de almacenamiento dinámico puede expandirse o contraerse según el tamaño de memoria asignado.
Ahora el montón es un espacio libre en el segmento de datos, que generalmente es mucho más grande que 10 * sizeof (int) bytes.
C no tiene tal cosa como ArrayIndexOutOfBoundException, lo que significa que C nunca verificará los límites de su matriz. Entonces, cuando está accediendo al undécimo elemento de su matriz, esta es básicamente la ubicación * array [0] + 10 * sizeof (int) -th en el montón, que está perfectamente bien con C hasta que no esté fuera del segmento.
Puede intentar un experimento simple intentando acceder a los elementos posteriores en un bucle y eventualmente llegará a un fallo de segmentación, lo que significa que ahora está tratando de acceder fuera del segmento y el sistema operativo ha restringido el acceso debido a problemas de seguridad.