Devolviendo este puntero desde una función

5 minutos de lectura

avatar de usuario de user567879
usuario567879

Estoy tratando de devolver un puntero de una función. Pero estoy recibiendo una falla de segmentación. Alguien por favor diga qué está mal con el código

#include <stdio.h>

int *fun();

main()
{
    int *ptr;
    ptr = fun();
    printf("%d", *ptr);
}

int *fun()
{
    int *point;
    *point = 12;
    return point;
}

  • La pregunta más importante cuando se trata de punteros es: Puntero a ¿qué? ¿Un objeto local? Kabum. ¿Un objeto asignado dinámicamente? ¿Liberado por quién? ¿Algún objeto almacenado en otro lugar? Entonces, ¿cuánto tiempo vive ese objeto y cuánto tiempo es válido mi puntero? Devolver un puntero desde una función está especialmente lleno de riesgos, porque el puntero se inicializa en una pieza de código totalmente diferente (que a menudo ni siquiera es visible para la persona que llama), y las personas que llaman no saben cómo tratar el resultado. Una buena documentación para tales funciones es muy importante.

    – sbi

    13 de octubre de 2011 a las 13:47

  • Solo recuerde siempre malloc cualquier objeto, puntero y estructura de datos. si no lo hace, siempre obtendrá una falla de segmentación porque simplemente dice que no le estamos asignando ningún espacio.

    –Kevin

    13 de octubre de 2011 a las 14:07

  • Cuando “cambia el error en el código”, hace que la respuesta (parcialmente) no esté relacionada con la pregunta. El código en cuestión no es perfecto, ese es el motivo de la pregunta. Recomiendo encarecidamente evitar corregir cualquier código en las preguntas.

    – arpista

    30 de mayo de 2014 a las 17:29

  • Hola, cual es la diferencia entre hacerlo a traves de malloc y hacerlo como *ptr = 12? ¿Por qué el primero devuelve un puntero válido a la persona que llama incluso cuando se declara localmente dentro del remitente, mientras que el último no lo hace?

    – Bestia Sexy

    03/10/2015 a las 12:30

  • @ActitudMonger Porque malloc dice “Quiero algo de memoria para almacenar cosas”, pero simple y llanamente *ptr = 12 dice “Quiero algo de memoria para hacer un cálculo, que pueda usarse para otras cosas más adelante”.

    – wizzwizz4

    09/04/2016 a las 10:46

Asigne memoria antes de usar el puntero. Si no asigna memoria *point = 12 es un comportamiento indefinido.

int *fun()
{
    int *point = malloc(sizeof *point); /* Mandatory. */
    *point=12;  
    return point;
}

También tu printf Está Mal. Necesita desreferenciar (*) el puntero.

printf("%d", *ptr);
             ^

  • Si tengo más de un valor para almacenar, ¿qué haría? ¿Si necesito asignar todo o simplemente puedo incrementar el puntero?

    – usuario567879

    15 de octubre de 2011 a las 1:42

  • @user567879 Necesitas malloc más espacio. Algo como int *point = malloc(num_values * sizeof *point);

    – cnicutar

    15 de octubre de 2011 a las 6:30

  • También int *point = calloc(num_values,sizeof(int)) será útil. Más información en thinkage.ca/english/gcos/expl/c/lib/calloc.html

    – tremendos

    6 de agosto de 2013 a las 8:42


  • ¿Es una buena práctica devolver el puntero de una función y hacer que el programa principal libere la memoria? ¿Alguna otra alternativa a esta? (solo en caso de que no sea una buena práctica)

    – Mahesha Padyana

    27 de julio de 2015 a las 17:32

  • @cnicutar: Sería mejor si lanzas el resultado de malloc (to int*) aunque no es necesario en C,

    – Destructor

    19 de agosto de 2015 a las 13:06

Aunque devolver un puntero a un objeto local es una mala práctica, no causó el kaboom aquí. He aquí por qué tienes una falla de segmento:

int *fun()
{
    int *point;
    *point=12;  <<<<<<  your program crashed here.
    return point;
}

El puntero local queda fuera del alcance, pero el verdadero problema es quitar la referencia a un puntero que nunca se inicializó. ¿Cuál es el valor del punto? Quién sabe. Si el valor no se asignó a una ubicación de memoria válida, obtendrá un SEGFAULT. Si por suerte se asignó a algo válido, entonces simplemente corrompiste la memoria al sobrescribir ese lugar con tu asignación a 12.

Dado que el puntero devuelto se usó de inmediato, en este caso podría salirse con la suya devolviendo un puntero local. Sin embargo, es una mala práctica porque si ese puntero se reutilizó después de que otra llamada de función reutilizó esa memoria en la pila, el comportamiento del programa no estaría definido.

int *fun()
{
    int point;
    point = 12;
    return (&point);
}

o casi idénticamente:

int *fun()
{
    int point;
    int *point_ptr;
    point_ptr = &point;
    *point_ptr = 12;
    return (point_ptr);
}

Otra mala práctica pero un método más seguro sería declarar el valor entero como una variable estática, y luego no estaría en la pila y estaría a salvo de ser utilizado por otra función:

int *fun()
{
    static int point;
    int *point_ptr;
    point_ptr = &point;
    *point_ptr = 12;
    return (point_ptr);
}

o

int *fun()
{
    static int point;
    point = 12;
    return (&point);
}

Como han mencionado otros, la forma “correcta” de hacer esto sería asignar memoria en el montón, a través de malloc.

  • Y free() después de su uso.

    – C–

    3 de octubre de 2018 a las 6:38

  • usará static causar advertencias de compilación?

    usuario12211554

    14 de julio de 2019 a las 21:46

Avatar de usuario de Varun Changani
Varun Changani

No está asignando memoria en la asignación del valor 12 al puntero entero. Por lo tanto, se bloquea, porque no encuentra ninguna memoria.

Puedes probar esto:

#include<stdio.h>
#include<stdlib.h>
int *fun();

int main()
{
    int *ptr;
    ptr=fun();
    printf("\n\t\t%d\n",*ptr);
}

int *fun()
{
    int ptr;
    ptr=12;
    return(&ptr);
}

  • ¿No existe 12 solo en la pila de esa llamada de función? Eso parece que produciría un comportamiento indefinido.

    – escapar

    3 de noviembre de 2017 a las 20:22

avatar de usuario de idleHands_94
manos inactivas_94

Que yo sepa, el uso de la palabra clave new hace relativamente lo mismo que malloc (tamaño del identificador). El siguiente código demuestra cómo usar la palabra clave new.

    void main(void){
        int* test;
        test = tester();
        printf("%d",*test);
        system("pause");
    return;
}
    int* tester(void){
        int *retMe;
        retMe = new int;//<----Here retMe is getting malloc for integer type
        *retMe = 12;<---- Initializes retMe... Note * dereferences retMe 
    return retMe;
}

¿Ha sido útil esta solución?