2012-05-17 19 views
7

Tengo un buffer y quiero hacer una prueba para ver si el buffer tiene suficiente capacidad, es decir Encontrar la cantidad de elementos que puedo agregar al buffer.¿Cómo determinar el tamaño de un búfer C asignado?

char *buffer = (char *)malloc(sizeof(char) * 10); 

Haciendo un

int numElements = sizeof(buffer); 

no devuelve 10, cualquier idea sobre cómo puedo lograr esto?

Respuesta

3

buffer es solo un puntero sin información de tamaño. Sin embargo, la rutina malloc() mantendrá el tamaño de la asignación que hizo para que cuando la libere(), libere la cantidad correcta de espacio. Por lo tanto, a menos que desee sumergirse en la funcionalidad malloc(), le recomiendo que solo guarde el tamaño de la asignación usted mismo. (para una posible implementación, vea el ejemplo en la otra respuesta de la API).

11

No puede hacer esa prueba. Es su responsabilidad recordar cuánta memoria asignó. Si alguien más le da el buffer, exija que también ellos pasen la información de tamaño y asuma la responsabilidad de pasar el valor correcto o hacer que el programa muera.

6

Dado que buffer es un puntero (no una matriz), el operador sizeof devuelve el tamaño de un puntero, no el tamaño del búfer al que apunta. No hay manera estándar para determinar este tamaño, por lo que tiene que hacer la contabilidad usted mismo (es decir, recuerde cuánto asignado.)

Por cierto, es el mismo para

char *p = "hello, world\n"; /* sizeof p is not 13. */ 

Curiosamente,

sizeof "hello, world\n" 

es 14. ¿Puedes adivinar por qué?

+12

¿De verdad le está haciendo una pregunta al interlocutor? Eso no es realmente por qué estamos aquí ... – Evert

+0

@Jens Bueno, sé que sizeof() devuelve el tamaño correcto para literales y matrices de cadenas, pero ¿por qué? ¿Dónde está almacenada la información de tamaño? Por ejemplo, char * p = "hello" da el tamaño del puntero, char p [10] da el tamaño de diez. – Zebrafish

+0

@Evert Estamos aquí para obtener respuestas, y él dio una respuesta. Plantear preguntas de seguimiento es un dispositivo educativo legítimo.Además, no creo que su pregunta merezca críticas porque la respuesta a su pregunta es la respuesta que acaba de dar, por lo que no está ocultando información. Supongo que se podría debatir la eficacia o el valor dejando "un ejercicio para el lector", etc., pero en este caso es bastante conciso y relevante. –

0
struct buffer 
{ 
    void 
    *memory 

    size_t 
    length; 
}; 

void *buffer_allocate(struct buffer *b, size_t length) 
{ 
    assert(b != NULL); 

    b->memory = malloc(length) 
    b->length = length; 

     // TRD : NULL on malloc() fail 
     return(b->memory); 
} 

int buffer_valid(struct buffer *b, size_t length) 
{ 
    assert(b != NULL); 

    if(b->memory == NULL or length > b->length) 
    return(0); 

    return(1); 
} 

void *buffer_get(struct buffer *b) 
{ 
    assert(b != NULL); 

    return(b->memory); 
} 

Utilice la API y no malloc/libre y no puede salir mal.

+0

Si realmente quisiera ser inteligente, podría escribir su propio 'malloc' que utilizaba el sistema' malloc' para asignar cuatro bytes adicionales, almacenar la longitud asignada allí y devolver un puntero después de esta longitud. Entonces podrías tener un método 'getSize' que usara la aritmética del puntero para tomar esto de nuevo. Te permite usar llamadas que parecen 'malloc' y' free'. –

+0

No estoy seguro de que sea inteligente, significa que su malloc personal ahora difiere en su comportamiento para todos los demás. He llegado a la vista de que ajustar el comportamiento de la función central es arriesgado. Es la base de todo lo demás. –

+1

Conocía una compañía, sobrepasaba a malloc para que todo lo que asignaba se asignara a los freelistas y simplemente devolvía el elemento al librero. Impresionante, tanto en lo que hace como en la forma en que fue implementado (lo cual no es sorprendente, dado lo malo que es la idea) y tan profundamente incrustado en el código, nunca pudo ser eliminado. –

0

sizeof se usa para calcular el tamaño de objetos reales, no punteros para objetos en la memoria. Devuelve el tamaño de las estructuras o primitivas. Quiero decir que funcionará, pero le dará el tamaño del puntero, no la estructura a la que apunta. Para obtener la longitud de cualquier tipo de uso array:

strlen (tampón)

+0

El uso de strlen() solo funciona en cadenas (es decir, termina con un byte NUL). En general, no puede esperar que 'strlen' le proporcione" la longitud de ningún tipo de matriz ". De hecho, es al revés: 'sizeof' ** does ** le da el tamaño de cualquier clase de matriz. – Jens

+0

entonces, la forma correcta sería: sizeof (* buffer)? – SpaceBear

+0

No, ya que la declaración es 'char * buffer',' sizeof * buffer' es 'sizeof char' que es 1. No hay forma de determinar el tamaño de un buffer asignado dinámicamente que no sea recordar cómo se llamó malloc/calloc/realloc. Pero para ** arrays ** declarado como 'charla foo [N]' el 'sizeof foo' es' N'. – Jens

19

Para glibc GNU:

SYNOPSIS 

#include <malloc.h> 
size_t malloc_usable_size (void *ptr); 

DESCRIPCIÓN

El malloc_usable_size función() devuelve el número de bytes utilizables en el bloque apuntado por ptr, un puntero a un bloque de memoria asignado por malloc (3) o una función relacionada.

+0

Nota: Esto puede ocasionar una sobrecarga importante porque depende de la implementación de malloc. Y devuelve los bytes asignados. Para obtener la cantidad de elementos disponibles, necesita una división adicional. El hombre dice claramente "El valor devuelto por malloc_usable_size() puede ser mayor que el tamaño solicitado de la asignación debido a la alineación y restricciones de tamaño mínimo. Aunque la aplicación puede sobrescribir los bytes en exceso sin efectos negativos, ** esto no es bueno práctica de programación **: la cantidad de bytes sobrantes en una asignación depende de la implementación subyacente ". – Stargateur

Cuestiones relacionadas