Click here to Skip to main content
15,891,704 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi guys, I've been knocked down with this pretty simple example that seems at first but it's been giving me a lot of headaches lately. Can someone tell me what's wrong with these function?

Note: I am working with C. It is a requirement.

C++
#include "stdafx.h"
#include <string.h>
#include <stdio.h>

char* telegram_input()
{
	char message[100];

    printf("Write down the telegram: ");
	gets(message);

    return message;
}


int _tmain(int argc, _TCHAR* argv[])
}

        printf("Write your message:\n\n");
	char * myMessage; 

	myMessage = telegram_input();

        //HERE's the problem!!!!! -->
        printf("The written message is: %s.", myMessage);


	return 0;
}


The problem is that when I return the the value of the array to the char* pointer, this only holds the first value of the array and it is an incorrect one.
When I print it with 'printf' it shows a smile face character. How is that?
Why does this happen? If I hadn't use the above functions I wouldn't have this problem.
Posted
Updated 28-Feb-13 8:33am
v2

The problem is that when you allocate memory in a function, it goes on the stack, and is removed and reused by the next function to be called.
So, you allocate an array of 100 characters on the stack, fill it, and return a pointer to it. Then you exit the function, which releases all the items on the stack, and goes back to your calling function. The pointer is perfectly valid (in the sense that it's in memory, and won't cause a access violation) but it is pointing to memory that is no longer assigned. When you call printf to show the string content, the same pointer goes over to the function, which is then free to use the stack for it's own variables. Since these share the same memory, it overwrites the content of your string data in the process of printing it!


Image it's a pile of coins: there are five coins in a pile, and you enter the telegram_input function. It needs space, so it adds 100 coins to the pile, and remembers where the first one is. it then writes a letter on each of the new 100 coins, and returns to the calling function. As part of the return, the pile of coins is returned to it's state before the function was called - 5 coins - and the printf function is called, which puts some coins of it's own on the pile. because the pointer you are passing about remembers the location of the coins in the pile - "they start at the sixth coin" - you end up not reading the right info, because your coins are long gone!

Hopefully this makes some sense - it's a lot easier with pictures and being able to see when your eyes glaze over...:laugh:

This is called a "hanging reference" and really has to be avoided. The best way to avoid it is to pass the buffer into the telegram-input function as a parameter, along with it's length if you are going to use it (and you should) so that the memory is always correct and available.
C++
char* telegram_input(char* message)
{
    printf("Write down the telegram: ");
    gets(message);
    return message;
}


int _tmain(int argc, _TCHAR* argv[])
}

        printf("Write your message:\n\n");
    char message[100];

    telegram_input(message);
    printf("The written message is: %s.", message);
    return 0;
}
The other solution is to use the malloc function to allocate the memory within the telegram_input function - but then you must be sure to free the memory when you have finished with it. malloc allocates memory that is not on the stack (it is on a "heap" instead) so it does not have this problem.
 
Share this answer
 
Comments
unscathed18 28-Feb-13 17:19pm    
Wonderful!! Thanks a lot!! This has clarified how it works on the backstage. Good answer.
OriginalGriff 28-Feb-13 17:26pm    
You're welcome!
The char array message in telegram_input goes out of scope when the function returns. Dynamically allocate memory using malloc and return that char*. Remember to call free on it when done.
 
Share this answer
 
Comments
H.Brydon 28-Feb-13 15:05pm    
Correct (+5) - or else you could also move the "char message[200];" to the _tmain() and pass a pointer to it
Sergey Alexandrovich Kryukov 28-Feb-13 15:15pm    
Hi Nish, how it's going?
I voted 4. In my opinion, it's all perfectly correct, but needs a big practical warning: such approach is somewhat dangerous, because it violates encapsulation in the following sense: the called should be aware of allocation method. For example, it would be very bad to export such function in a shared library, because the caller's system may use different allocation mechanism. The really portable code design should use the principle: the user allocates and deallocates. Or, the user can call a method of allocations and deallocation, but again symmetrically; in this case, implementation of allocation and deallocation is hidden from the caller and still implemented on the same side.
—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900