Pregunta

Siempre estoy confundido acerca de devolver una cadena literal o una cadena de una función.Me dijeron que podría ser la pérdida de memoria, porque no sé cuando la memoria serán borrados?

Por ejemplo, en el código de abajo, cómo implementar foo() así como para hacer que la salida de el código es "Hola Mundo"?

void foo (       )              // you can add parameters here.
{

}

int main ()
{
    char *c;
    foo (    );
    printf ("%s",c);
    return 0;
}

También, si el tipo de retorno de foo() no es nula, pero se puede devolver char*, lo que debería ser?

¿Fue útil?

Solución

Estoy asumiendo que no podemos modificar principal. Para obtener su trabajo programa sin una fuga, es necesario tener algo de almacenamiento estático:

void foo(char*& pC)  // reference
{
    static char theString[] = "thingadongdong";

    pC = theString;
}

Pero, en realidad, esto no es muy convencional código C ++. Usted se utiliza std::string y std::cout, por lo que no lo hace Tienes que preocuparse acerca de la memoria:

std::string foo(void)
{
    return "better thingadongdong";
}

int main(void)
{
    // memory management is done
    std::cout << foo() << std::endl;
}

Si usted se pregunta si algo necesita ser desasignado manualmente, se está haciendo mal.

Otros consejos

Dado que se está obsoleto el uso antiguo de char *, puede que no basta con utilizar una cadena?

const char* func1 () {return "string literal";}

string func2 () {return "another string literal";}

Ambos funcionan bien, sin advertencias del compilador.

Sin embargo

char* func3 () {return "yet another string literal";}

No se compilará en absoluto. Tampoco lo hará

char* func4 () {return &"a ref to a string literal?";}

BS dice en "The C ++ Programming Language" (Tercera Edición):

"Un literal de cadena se asigna de forma estática por lo que es seguro volver algún partir de una función.

const char* error_message (int i)`
{
//...
return "range error";
}

celebración de la memoria error de rango no va a desaparecer después de una llamada de error_messages (). "

Así que cada cadena literal en un programa se le asigna en su propio pequeño pedazo de memoria que tiene una duración de la duración del programa (es decir, se asigna de forma estática). Poner la const delante de la char * permite que el compilador sabe que no tiene intención (y no puede) alteran de literal que la cadena pedacito de memoria que podría ser peligroso, por lo que deja esta diapositiva asignación a pesar de que la conversión de la cadena literal a char * está en desuso.

Volviendo lugar a una cadena debe copiar la cadena literal en un objeto de tipo cadena, la memoria que la persona que llama es responsable.

De cualquier manera no hay pérdidas de memoria: cada cadena literal obtiene su propio trozo de memoria que se limpió en la terminación del programa; regresa a const char * devuelve un puntero a una pieza de literal de la memoria (sabiendo que no puede alterarlo); y el retorno a una cadena hace una copia en un objeto de cadena existente en el código de la persona que llama que está limpiado por la persona que llama.

A pesar de que parece un poco feo notación se refiere, no supongo que salieron de la const char * para mantener la alternativa barata (que implica no copias).

Siempre estoy confundido acerca de devolver una cadena literal o una cadena de una función.

Inmutable, el literal de cadena

Como yo lo entiendo, usted está seguro de volver de un literal de cadena directamente si el tipo de retorno es declarado const, para declarar que la cadena no es la intención de ser alterado.Esto significa que usted no tiene que preocuparse acerca de la vida útil de la cadena / pérdidas de memoria.

Mutable, no literal de cadena

Sin embargo, si usted necesita una cadena que puede cambiar en su lugar, usted debe considerar la vida útil de la cadena y el tamaño de la asignación de memoria en la que se almacena.Esto se convierte en un problema, ya que usted no puede alegremente a devolver la misma memoria que contiene la cadena para cada invocación de la función, ya que el uso anterior podría haber alterado el contenido de esa memoria, y/o puede estar todavía en uso.Por lo tanto, una nueva pieza de la memoria que debe ser asignado para mantener la cadena devuelta.

Aquí es donde el potencial se produce una fuga, y donde la elección debe hacerse acerca de que la asignación y desasignación de que debe ocurrir.Usted podría tener la función de asignar la memoria y el estado en la documentación de que esto suceda y se estipula en el mismo que la persona que llama tiene que liberar la memoria cuando ya no es requerido (prevención de fuga).Esto significa que la función puede devolver simplemente un char *.

La otra opción es pasar algo de memoria para la función que les fue asignado por la persona que llama, y tiene la función de colocar la cadena en el interior de esa memoria.En este caso, la persona que llama tanto asigna y es responsable de liberar la memoria.

Por último, he mencionado que el tamaño de la memoria y de la cadena deben ser administrados cuando se utiliza una variable de cadena.La asignación debe ser tanto lo suficientemente grande para que la cadena establecida inicialmente por la función y también para toda modificación que se hizo después de la función, antes de que se libera la memoria.Si no lo hace correctamente puede causar un desbordamiento de búfer al escribir una cadena larga para caber en la memoria inicialmente asignado;esto es extremadamente peligroso para la salud y la seguridad de su programa.Puede causar bugs y agujeros de seguridad que son extremadamente difíciles de detectar (desde la fuente del error - el desbordamiento - puede estar muy lejos de los síntomas que se observan cuando el programa falla).

Algo como esto:

void foo(char ** pChar)
{
    // Make sure the string is shorter
    // than the buffer
    *pChar = new char[256];
    strcpy(*pChar,"Hello World!");
}

A continuación, llamar de esta manera:

foo(&c);

Como se ha mencionado en el comentario, tenga cuidado de la cadena que se está almacenando es menor que el búfer o se obtendrá un desbordamiento de pila ...! (Juego de palabras)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top