Cerrado . Esta pregunta debe estar más
centrada . Actualmente no acepta respuestas.
Comentarios
Respuesta
La recolección de basura requiere estructuras de datos para seguimiento de asignaciones y / o recuento de referencias. Estos crean una sobrecarga en la memoria, el rendimiento y la complejidad del lenguaje. C ++ está diseñado para estar «cerca del metal», en otras palabras, toma el lado del rendimiento más alto de las características de compensación y conveniencia. Otros idiomas hacen esa compensación de manera diferente. Esta es una de las consideraciones a la hora de elegir un idioma, qué énfasis prefiere.
Dicho esto, hay muchos esquemas para el recuento de referencias en C ++ que son bastante livianos y eficaces, pero están en bibliotecas, tanto comerciales como de código abierto, en lugar de ser parte del lenguaje en sí. El recuento de referencias para administrar la vida útil de los objetos no es lo mismo que la recolección de elementos no utilizados, pero aborda muchos de los mismos tipos de problemas y se adapta mejor al enfoque básico de C ++.
Comentarios
Responder
Estrictamente hablando, no hay gestión de memoria en absoluto en el lenguaje C. malloc () y free () no son palabras clave en el idioma, sino solo funciones que se llaman desde una biblioteca.Esta distinción puede ser pedante ahora, porque malloc () y free () son parte de la biblioteca estándar de C, y serán provistas por cualquier implementación compatible con el estándar de C, pero esto no siempre fue así en el pasado.
¿Por qué querrías un lenguaje sin estándar para la administración de memoria? Esto se remonta a los orígenes de C como «ensamblador portátil». Hay muchos casos de hardware y algoritmos que pueden beneficiarse de, o incluso requerir, técnicas especializadas de administración de memoria. Hasta donde yo sé, no hay forma de deshabilitar completamente la administración de memoria nativa de Java y reemplazarla por la suya. Esto simplemente no es aceptable en algunas situaciones de alto rendimiento / recursos mínimos. C proporciona una flexibilidad casi completa para elegir exactamente qué infraestructura su programa va a utilizar. El precio que se paga es que el lenguaje C proporciona muy poca ayuda para escribir código correcto y sin errores.
Comentarios
Respuesta
La respuesta real es que la única forma de hacer Un mecanismo de recolección de basura seguro y eficiente es tener soporte a nivel de idioma para referencias opacas. (O, por el contrario, una falta de soporte a nivel de lenguaje para la manipulación de memoria directa.)
Java y C # pueden hacerlo porque tienen tipos de referencia especiales que no pueden manipularse. Esto le da al tiempo de ejecución la libertad de hacer cosas como mover objetos asignados en la memoria , lo cual es crucial para una implementación de GC de alto rendimiento. .
Para el registro, ninguna implementación de GC moderna usa el conteo de referencias , por lo que es completamente un rojo arenque. Los GC modernos usan la colección generacional, donde las nuevas asignaciones se tratan esencialmente de la misma manera que las asignaciones de pila en un lenguaje como C ++, y luego, periódicamente, los objetos recién asignados que aún están vivos se mueven a un espacio de «sobreviviente» separado, y una generación completa de objetos se desasigna a la vez.
Este enfoque tiene pros y contras: la ventaja es que las asignaciones de montón en un lenguaje que admite GC son tan rápidas como las asignaciones de pila en un lenguaje que no admite GC, y la desventaja es que los objetos que necesitan realizar una limpieza antes de ser destruidos requieren un mecanismo separado (por ejemplo, C #» s using
palabra clave) o su código de limpieza se ejecuta de forma no determinista.
Tenga en cuenta que una clave para un GC de alto rendimiento es que debe haber soporte de lenguaje para una clase especial de referencias. C no tiene este soporte de lenguaje y nunca lo tendrá; debido a que C ++ tiene una sobrecarga de operadores, podría emular un tipo de puntero GC «d, aunque tendría que hacerse con cuidado. De hecho, cuando Microsoft inventó su dialecto de C ++ que se ejecutaría bajo CLR (el tiempo de ejecución de .NET), tuvieron que inventar una nueva sintaxis para las «referencias de estilo C #» (por ejemplo, Foo^
) para distinguirlos de las «referencias de estilo C ++» (por ejemplo, Foo&
).
Lo que C ++ tiene, y lo que utilizan habitualmente los programadores de C ++, es punteros inteligentes , que en realidad son solo un mecanismo de recuento de referencias. No consideraría que el recuento de referencias sea un GC «verdadero», pero proporciona muchos de los mismos beneficios, a costa de un rendimiento más lento que la administración de memoria manual o el GC verdadero, pero con la ventaja de la destrucción determinista.
Al final del día, la respuesta realmente se reduce a una característica de diseño de lenguaje. C tomó una decisión, C ++ tomó una decisión que le permitió ser compatible con versiones anteriores de C y al mismo tiempo ofrecer alternativas que son lo suficientemente buenas para la mayoría de los propósitos, y Java y C # tomaron una decisión diferente que es incompatible con C pero que también es lo suficientemente buena para la mayoría de los propósitos. Desafortunadamente, no existe una fórmula mágica, pero estar familiarizado con las diferentes opciones que existen te ayudará a elegir la correcta. para cualquier programa que esté intentando crear.
Comentarios
Respuesta
Respuesta
«Todo» es un recolector de basura es un proceso que se ejecuta periódicamente para verificar si hay objetos sin referencia en la memoria y si los hay los elimina. (Sí, sé que esto es una simplificación excesiva). Esta no es una propiedad del lenguaje, sino del marco.
Hay recolectores de basura escritos para C y C ++ – este por ejemplo .
Una razón por la que no se ha «agregado» uno al lenguaje podría ser debido al gran volumen de código existente que nunca lo usaría, ya que usan su propio código para administrar la memoria. Otra razón podría sea que los tipos de aplicaciones escritas en C y C ++ no necesitan la sobrecarga asociada con un proceso de recolección de basura.
Comentarios
Respuesta
C fue diseñado en una era en la que la recolección de basura apenas una opción. También se diseñó para usos en los que la recolección de basura no funcionaría en general: entornos bare metal en tiempo real con memoria mínima y soporte de tiempo de ejecución mínimo. Recuerde que C era el lenguaje de implementación para el primer Unix, que se ejecutaba en un pdp-11 con 64 * K * bytes de memoria. C ++ era originalmente una extensión de C – la elección ya se había hecho, y es muy difícil injertar la recolección de basura en un lenguaje existente. Es el tipo de cosas que tienen que construirse desde la planta baja.
Respuesta
No tengo las comillas exactas, pero tanto Bjarne como Herb Sutter dicen algo parecido:
C ++ no necesita un recolector de basura, porque no tiene basura.
En moderno C ++ usas punteros inteligentes y por lo tanto no tienes basura.
Comentarios
Responder
Usted pregunte por qué estos lenguajes no han sido actualizados para incluir un recolector de basura opcional.
El problema con la recolección de basura opcional es que no puede mezclar código que use los diferentes modelos. Es decir, si escribo código que asume que está usando un recolector de basura, no puede usarlo en su programa que tiene la recolección de basura desactivada. Si lo hace, se filtrará por todas partes.
Respuesta
Hay varios problemas, incluidos …
- Aunque GC se inventó antes de C ++, y posiblemente antes de C, tanto C como C ++ se implementaron antes de que las GC fueran ampliamente aceptadas como prácticas.
- No se puede implementar fácilmente una Lenguaje y plataforma GC sin un lenguaje subyacente que no sea GC.
- Aunque GC es demostrablemente más eficiente que no GC para el código de aplicaciones típicas desarrollado en escalas de tiempo típicas, etc., hay problemas en los que un mayor esfuerzo de desarrollo es un buen negocio -off y la gestión de memoria especializada superará a un GC de propósito general. Además, C ++ es típicamente demostrablemente más eficiente que la mayoría de los lenguajes GC incluso sin ningún esfuerzo de desarrollo adicional.
- GC no es universalmente más seguro que C ++ – estilo RAII . RAII permite que otros recursos además de la memoria se limpien automáticamente, básicamente porque admite destructores confiables y oportunos. Estos no se pueden combinar con métodos GC convencionales debido a problemas con los ciclos de referencia.
- Los lenguajes GC tienen sus propias características tipos de memoria fugas, particularmente en relación con la memoria que nunca se volverá a utilizar, pero donde existían referencias existentes que nunca se han anulado o sobrescrito. La necesidad de hacer esto explícitamente no es diferente en principio a la necesidad de
delete
o free
explícitamente. El enfoque de GC todavía tiene una ventaja, sin referencias colgantes, y el análisis estático puede detectar algunos casos, pero nuevamente, no existe una solución perfecta para todos los casos.
Básicamente, en parte » s acerca de la edad de los idiomas, pero siempre habrá un lugar para los idiomas que no son de GC, incluso si es un lugar un poco especializado. Y en serio, en C ++, la falta de GC no es un gran problema: su memoria se administra de manera diferente, pero no está sin administrar.
C ++ administrado por Microsofts tiene al menos alguna capacidad para mezclar GC y no GC en la misma aplicación, lo que permite mezclar y combinar las ventajas de cada uno, pero no tengo la experiencia para decir qué tan bien funciona esto en la práctica.
Enlaces de prostitución de representantes a respuestas relacionadas mío …
Respuesta
¿Te imaginas escribir un controlador de dispositivo en un idioma con recolección de basura? ¿Cuántos bits podrían bajar línea mientras el GC se estaba ejecutando?
¿O un sistema operativo? ¿Cómo podría iniciar la recolección de basura en ejecución incluso antes de iniciar el kernel?
C está diseñado para tareas de bajo nivel cercanas a las de hardware. ¿El problema? ¿Es un lenguaje tan agradable que también es una buena opción para muchas tareas de nivel superior? Los zares del lenguaje son conscientes de estos usos, pero deben cumplir con los requisitos de los controladores de dispositivos, el código integrado y los sistemas operativos como una prioridad.
Comentarios
Respuesta
La respuesta corta y aburrida a esta pregunta es que debe haber un lenguaje que no sea recolector de basura para las personas que escriben a los recolectores de basura. No es conceptualmente fácil tener un lenguaje que al mismo tiempo permita un control muy preciso sobre el diseño de la memoria y tenga un GC ejecutándose en la parte superior.
La otra pregunta es por qué C y C ++ no tienen recolectores de basura.Bueno, sé que C ++ tiene un par de ellos, pero no son muy populares porque se ven obligados a lidiar con un lenguaje que no fue diseñado para ser GC-ed en primer lugar, y las personas que todavía usan C ++ en esta edad no es realmente del tipo que pierde un GC.
Además, en lugar de agregar GC a un lenguaje antiguo sin GC, es más fácil crear un nuevo lenguaje que tenga la mayoría de las la misma sintaxis mientras admite un GC. Java y C # son buenos ejemplos de esto.
Comentarios
Respuesta
La recolección de basura es fundamentalmente incompatible con lenguaje de sistemas utilizado para desarrollar controladores para hardware compatible con DMA.
Es muy posible que el único puntero a un objeto esté almacenado en un registro de hardware en algún periférico. Dado que el recolector de basura no sabría sobre esto, pensaría que el objeto es inalcanzable y lo recopilará.
Este argumento es doble para compactar GC. Incluso si tuviera cuidado de mantener referencias en memoria a objetos utilizados por periféricos de hardware, cuando el GC reubicó el objeto, no sabría cómo actualizar el puntero contenido en el registro de configuración de periféricos.
Entonces ahora necesitaría una combinación de búferes DMA inmóviles y objetos administrados por GC, lo que significa que tiene todas las desventajas de ambos.
Comentarios
Respuesta
Porque, C & C ++ son lenguajes de nivel relativamente bajo destinados a fines generales, incluso, por ejemplo, para ejecutarse en un procesador de 16 bits con 1 MB de memoria en un sistema integrado, que no podía permitirse desperdiciar memoria con gc.
Comentarios
Respuesta
Hay recolectores de basura en C ++ y C. No estoy seguro de cómo funciona esto en C, pero en C ++ puede aprovechar RTTI para descubrir dinámicamente su gráfico de objetos y usarlo para la recolección de basura.
Que yo sepa, no puede escribir Java sin un recolector de basura. Una pequeña búsqueda arrojó esto .
La diferencia clave entre Java y C / C ++ es que en C / C ++ la elección es siempre suya , mientras que en Java a menudo te quedas sin opciones por diseño.
Comentarios
Respuesta
Es un compromiso entre rendimiento y seguridad.
No hay garantía de que su basura se recolecte en Java, así que puede estar rondando ocupando espacio durante mucho tiempo, mientras que el escaneo de objetos sin referencia (es decir, basura) también lleva más tiempo que eliminar o liberar explícitamente un objeto no utilizado.
La ventaja es, por supuesto, que se puede construir un lenguaje sin punteros o sin pérdidas de memoria, por lo que es más probable que se produzca el código correcto.
Puede haber una ligera ventaja «religiosa» en estos debates a veces, ¡tenga cuidado!
Respuesta
Aquí hay una lista de problemas inherentes de GC, que lo hacen inutilizable en un lenguaje de sistema como C:
-
El GC debe ejecutarse por debajo del nivel del código cuyos objetos administra. Simplemente no existe tal nivel en un kernel.
-
Un GC tiene que detener el código administrado de vez en cuando. Ahora piense en lo que sucedería si le hiciera eso a su kernel. Todo el procesamiento en su máquina se detendría por, digamos, un milisegundo, mientras el GC escanea todas las asignaciones de memoria existentes. Esto acabaría con todos los intentos de crear sistemas que operen bajo estrictos requisitos de tiempo real.
-
Un GC necesita poder distinguir entre punteros y no punteros. Es decir, debe poder ver todos los objetos de memoria existentes y poder producir una lista de compensaciones donde se pueden encontrar sus punteros.
Este descubrimiento debe ser perfecto: el GC debe poder para perseguir todos los indicadores que descubre. Si eliminara la referencia a un falso positivo, probablemente colapsaría. Si no detecta un falso negativo, probablemente destruiría un objeto que todavía está en uso, bloqueando el código administrado o corrompiendo silenciosamente sus datos.
Esto requiere absolutamente que la información de tipo se almacene en cada objeto existente. Sin embargo, tanto C como C ++ permiten objetos de datos antiguos simples que no contienen información de tipo.
-
GC es un negocio inherentemente lento. Los programadores que se han socializado con Java Puede que no se den cuenta de esto, pero los programas pueden ser mucho más rápidos cuando no se implementan en Java. Y uno de los factores que hacen que Java sea lento es GC. Esto es lo que impide que los lenguajes GCed como Java se utilicen en supercomputación. Si su máquina cuesta un millón al año en consumo de energía, no desea pagar ni el 10% de eso por la recolección de basura.
C y C ++ son lenguajes que se crean para admitir todos los posibles casos de uso. Y, como puede ver, muchos de estos casos de uso están excluidos por la recolección de basura. Por lo tanto, para admitir estos casos de uso, C / C ++ no puede recolectarse basura.