Ver Mensaje Individual
  #2 (permalink)  
Antiguo 17/03/2016, 10:24
eferion
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 10 años, 1 mes
Puntos: 204
Respuesta: Usar malloc dentro de una funcion

Vamos a empezar por lo sencillo:

Código C++:
Ver original
  1. void func(int var)
  2. {
  3.   var = 5;
  4. }
  5.  
  6. int main()
  7. {
  8.   int numero= 0;
  9.   func(numero);
  10.   std::cout << numero;
  11. }

¿Qué se imprime por pantalla? Pues hombre, teniendo en cuenta que var es una variable local sus cambios no van a afectar en nada a numero, luego std::cout imprimirá 0.

Ahora complicamos un poco más el código:

Código C++:
Ver original
  1. void func(int* var)
  2. {
  3.   *var = 5;
  4. }
  5.  
  6. void func2(int* var)
  7. {
  8.   var = 0;
  9. }
  10. int main()
  11. {
  12.   int numero;
  13.   int* ptr = &numero;
  14.   func(numero);
  15.   std::cout << (void*)ptr << " " << *ptr << std::endl;
  16.   func2(ptr);
  17.   std::cout << (void*)ptr << " " << *ptr << std::endl;
  18. }

El programa ahora imprime la dirección de memoria apuntada por el puntero y el valor almacenado en dicha posición de memoria.

func intenta modificar el valor apuntado por el puntero var. Al ser var un puntero y apuntar a numero es capaz de modificar su valor correctamente, luego el primer cout imprimirá una dirección de memoria y el número 5.

Le llega el turno a func2. Esta función intenta modificar la dirección de memoria apuntada por var, pero claro, si modificas la dirección a la que apunta var estás modificando la memoria local de var, luego el cambio no se queda reflejado fuera de func2. Esto implica que el cambio no tiene efectos en ptr. Con todo esto lo que sucede es que el programa imprime dos líneas iguales.

Una vez comprendido esto pasamos a tu código:

Código C++:
Ver original
  1. int myfunc(char * obj) {
  2.   obj = (char*)calloc(140,sizeof(char));
  3.   strcpy(obj, "cadena de texto");
  4.   return 69; // por ejemplo
  5. }

Como has visto antes, si quieres modificar la dirección apuntada no puedes tirar de un puntero sino en tal caso necesitas un puntero doble (un puntero permite modificar el valor apuntado, un puntero doble permite modificar la dirección apuntada por el puntero simple, etc).

Código C++:
Ver original
  1. int myfunc(char ** obj) {
  2.   // modificar obj implicaría cambios locales
  3.   // mientras que modificar *obj implica que los cambios se verán fuera de la función
  4.  
  5.   // Si después usa strcpy puedes usar malloc o, mejor aún new
  6.   // ya que strcpy finaliza la cadena con '\0'
  7.   *obj = (char*)calloc(140,sizeof(char));
  8.   // opción 2. Si usas new libera la memoria con delete
  9.   //*obj = new char[140];
  10.   strcpy(*obj, "cadena de texto");
  11.   return 69; // por ejemplo
  12. }

Vale, ya tenemos la función terminada... ¿Qué tal si revisamos el uso?

Código C++:
Ver original
  1. char obj;
  2. int num = myfunc(&obj);
  3. // ahora en num tengo un numero que para mi pregunta es irrelevante, aunque ahora seria 69
  4. // me gustaria usar 'obj'
  5. std::cout << obj;

Fallo gordo en la primera línea. La definición de obj es de tipo char a secas, es decir, no es un puntero. Esto implica por un lado que no va a ser capaz de almacenar nada más que un sólo caracter (olvidate de almacenar cadenas) y por otro que cualquier intento por cambiar su dirección de memoria va a provocar un casque de la aplicación:

Código C++:
Ver original
  1. char obj;
  2. char* ptr = &obj;
  3. delete ptr; // error

Si queremos que obj pueda manejar memoria dinámica tiene que ser un puntero. Así de simple.

Y no nos debemos olvidar de liberar la memoria reservada cuando ya no la necesitamos. Las buenas costumbres hay que cogerlas desde el principio.

Con todo esto tenemos lo siguiente:

Código C++:
Ver original
  1. char *obj;
  2. int num = myfunc(&obj); // myfunc espera un puntero doble, por eso usamos el &
  3. std::cout << *obj;
  4. free(obj); // Si has usado malloc/calloc
  5. delete obj; // Si has usado new
  6. obj = 0; // obj=nullptr si prefieres usar el último estándar de C++

Que sería más acorde a lo que tú necesitas.

El código no está ni compilado ni mucho menos probado. He escrito la respuesta sobre la marcha así que no puedo garantizar que esté libre de errores... pero a grandes rasgos parece estar bien.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.