Function returns pointer to trash, and free locks the terminal

Asked

Viewed 942 times

6

Could someone explain to me the reason when I give free in the pontaux Windows terminal stops responding? And why when I allocate pontmaior my result comes as memory junk?

The function returns a pointer to the highest value of a vector.

Code:

#include <stdio.h>
#include <stdlib.h>

int* retornamaior (int *vetor, int tamanho) {

    int i, maior = vetor[0];

    for (i=0; i<tamanho; i++) {
        if (vetor[i]>=maior)
            maior = vetor[i];   
        }

    int *pontmaior = &maior;

    return pontmaior;
}

int main (int argc, char *argv[]) {

    int *vetor, tamanho, i;

    printf ("Digite o tamanho da sequência: ");
    scanf ("%d", &tamanho);

    vetor = (int*)malloc(tamanho*sizeof(int));

    printf ("Digite a sequência: ");

    for (i=0; i<tamanho; i++)
        scanf ("%d", &vetor[i]);

    int *pontaux = retornamaior (vetor,tamanho);

    printf ("Maior: %d\n", *pontaux);

    free (vetor);

    return 0;   
}
  • Kay, I don’t want to be a fanboy, but C++ does all this in ~12 lines...

  • 4

    hehehe, but I’m learning C for now :D

  • Yeah, kid, I started just like that :).

2 answers

7


The error seems to be here:

int *pontmaior = &maior;

You are returning a pointer to the "larger" stack variable, which no longer exists when used by the main().

You should return a simple integer pointing out which item of the "vector" matrix is the largest. It is safer, avoid this lot of pointer manipulations.

Would something like this:

int retornamaior (int *vetor, int tamanho)
{
        int i, maior = 0;
        for (i=0; i<tamanho; i++) {
                if (vetor[i]>=vetor[maior])
                        maior = i;
        }
        return maior;
}

int main (int argc, char *argv[])
{
        int *vetor, tamanho, i;

        printf ("Digite o tamanho da sequência: ");
        scanf ("%d", &tamanho);

        vetor = (int*)malloc(tamanho*sizeof(int));

        printf ("Digite a sequência: ");

        for (i=0; i<tamanho; i++)
                scanf ("%d", &vetor[i]);

        int pontaux = retornamaior (vetor,tamanho);

        printf ("Maior: %d\n", vetor[pontaux]);

        free (vetor);

        return 0;
}

If you make a point of returning a pointer:

#include <stdio.h>
#include <stdlib.h>

int* retornamaior (int *vetor, int tamanho) {

    int i, *maior = &vetor[0];

    for (i=0; i<tamanho; i++) {
        if (vetor[i]>=*maior)
            maior = &vetor[i];
        }

    return maior;
}

int main (int argc, char *argv[]) {

    int *vetor, tamanho, i;

    printf ("Digite o tamanho da sequência: ");
    scanf ("%d", &tamanho);

    vetor = (int*)malloc(tamanho*sizeof(int));

    printf ("Digite a sequência: ");

    for (i=0; i<tamanho; i++)
        scanf ("%d", &vetor[i]);

    int *pontaux = retornamaior (vetor,tamanho);

    printf ("Maior: %d\n", *pontaux);

    free (vetor);

    return 0;
}
  • I’m sorry my ignorance, but I still don’t know what a stack is. How could I point a pro major pointer? Just got me that shape in mind.

  • Stack variable is that type of "normal" variable that you normally declare at the beginning of the function. I’ll change my answer so you can see how the function would look in the suggested style

  • Understood, but in this case the function would not be returning statically the "highest" number? I need to return a pointer. It is possible to do this without presenting the mistakes they were giving?

  • Yes, you could make the "larger" variable a pointer, and assign it the pointer &vector[i], which does not lose the validate until the free(). The comparison would have to be if (vector[i] >= *higher).

  • int *pontmaior = &maior? Is there another way to do this? Thank you for your patience, but this part is still a little complicated for me.

  • I edited again, adding a second solution that returns pointer.

  • Thank you very much! I understood what I was doing wrong, thanks again for the patience :).

  • Blz, do not forget the +1 in the answer to indicate that the question is properly answered.

  • Well, I’ve tried but it turns out I don’t have enough reputation points to give a +1.

  • You already confirmed the answer, it’s perfect!

  • 2

    Kay, just for the record. I don’t know what your understanding of pointers is, but remember that the returned pointer is only the address for a given position in the array. If the value of that position changes *pontaux changes. But this does not mean that you will always have a pointer to the highest position of the array. I’m saying this because this looks a lot like a classic function pointer exercise (which is another mammoth).

  • Um, but this was for my solution right? And with the second solution there epx also not always return a pointer to higher position? Yeah, I know a little bit about pointers, in case my function is returning the address where the value is stored, right? The only thing I changed was to allocate the larger pointer and then set *larger = vector[0];

  • I think what he meant was that if the contents of the array change after you calculate the largest, it is possible that the pointer is no longer pointing to the largest element, it would have to calculate again.

Show 8 more comments

3

I saw the epx response and I realized that it got a little lost to understand why the following piece of code

int *pontmaior = &maior;

be wrong, what happens is that when you declare int *pointmaior within your function you are declaring a variable that will only exist within the scope of the function int* retornamaior (int *vetor, int tamanho), that is, the memory area intended for this variable will be released by the system at the end of the execution of this function, thus, when executing the line

printf ("Maior: %d\n", *pontaux);

you will already attempt to access an invalid memory area.

  • 1

    Content is relevant enough to be a complementary response.

  • The pontaux will not receive the memory address of the function returns major? In this case I am printing the pontaux and not the dot major.

  • 1

    If I understand your question correctly, the answer is yes, will, the problem is that this memory has already been released to be used in something else when exiting the 'returns major' function and this happens because you are returning a pointer that references the 'largest' variable declared within the 'returns major' function and as a pointer saves the address of a variable and not its value the dot major pointer will receive an invalid memory address.

  • 1

    @Kay, a variable declared within a function is called a variable local. The reason it has this name is simple: it will only exist as long as the function is running; it can only be accessed locally by the function where it is declared (or by functions called by that function). That is, when you call the function retornamaior, before the function runs, the program reserves a memory space for those variables, and when the function finishes running, this memory space is no longer reserved and can be used later by another function, for another functionality.

  • 1

    Therefore, if you return a pointer to a local variable of a function, you cannot handle that pointer afterward function have finished executing. Understood?

  • I think so. For example, if the variable 'higher' was as a function parameter, could the address of this variable be used in main? 'Cause I’ve done examples like this.

  • Kay, it seems to me that you lack a little concept of variable scope in C, basically scope of a variable is the location of the application, where it can be seen and changed (Source: http://www.portaleducacao.com.br/informatica/artigos/6359/escopo-e-vida-util-de-variaveis-vbnet#ixzz2t40N1zH9).

  • 2

    I have separated these 2 links that give a better idea of the scope in C: http://www.di.ufpb.br/liliane/aulas/escopo.html, http://linguagemc.com.br/funcoes-e-escopo-variable/

  • 1

    @Kay, if you declare as parameter without being a pointer, no. In this case, the same thing happens. It is allocated at the beginning of the execution of the function and offset at the end. If your example worked, it was just a coincidence. Because accessing an invalid memory area in C/C++ has an undetermined behavior. That is, not necessarily generates an execution error, but may generate yes.

  • I get it, I’ll try to get a closer look at that part. It’s really a little confusing.

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.