-1

I am wondering why the output is garbage? And how can I solve this problem?

#include<stdio.h>

char *Func(void);
int main()
{
    char *string1;

    string1 = Func();
    puts(string1);

    return 0;
}

char *Func(void)
{
    char string2[10]="medo";
    return string2;
}
Pablo
  • 13,271
  • 4
  • 39
  • 59
  • 1
    You need to explain your question a little better. – M.Qasim Jan 22 '18 at 00:47
  • 3
    `string2` is allocated on the stack, not heap, so as soon as `Func()` exits, the standard does not guarantee that those bytes won't immediately be overwritten by something else. – Patrick Roberts Jan 22 '18 at 00:47
  • If you want to change the contents of the string inside the function pass a char* (with enough memory allocated) to the function and change it there – Mitch Jan 22 '18 at 00:55

2 Answers2

2

Because string2 is only valid in the scope of Func.

An array decays into a pointer when assigning it to a pointer, passing it to a function or when used with return in a function returning a pointer.

An array decaying into a pointer means that it is converted to a pointer and the pointer points to the first element of the array.

With an array like this:

int arr[] = { 1, 2, 3 };

These are equivalent:

int *p1 = arr;
int *p2 = &arr[0];

The problem with Func is that it is returning a pointer that points to a memory location that is only valid while Func is running. Once Func returns, it is no longer valid and the program flow might replace these values immediately.

In your main function you pass this pointer to printf and because the location where string1 is pointing to isn't valid in main (it was only valid in Func), you get garbage. Actually that is undefined behaviour, and medo could have been printed as well.

How to fix it: declare an array in main, pass it to Func, let Func use the passed array and return:

#include<stdio.h>
#include<string.h>

Func(char* string2);
int main()
{
    char string1[20];

    Func(string1);
    puts(string1);

    return 0;
}

void Func(char *string2)
{
    strcpy(string2, "medo");
}
Pablo
  • 13,271
  • 4
  • 39
  • 59
1

Because the lifetime of the string has already ended by the time you print it.

Local variables, such as string2 in Func, are often stored in the stack, which is a very dynamic structure that changes every time a function is called or returned. (The actual behavior of the program stack is a bit too complex to elaborate here, but keep in mind that stuff in the stack doesn't survive the function that puts it there.)

By the time the function returns, string2 is no longer necessary, and thus it might be overwritten with garbage data. Nevertheless, Func returns a pointer to string2 (remember that the name of an array is a pointer to its contents) — thus returning a pointer to the stack-allocated string that is being overwritten with garbage data. Printing the data referenced by this pointer (in main, via string1) just prints that garbage.

There are two ways of solving this issue. One is to let the caller handle memory allocation, and pass the allocated area to the callee, like so:

#include <stdio.h>
#include <string.h>

void Func(char *);

int main (void) {
  char string[10];
  Func(string);
  puts(string);
  return 0;
}

void Func (char * string) {
  strcpy(string, "test");
}

...and another way is to let the callee handle the allocation, but remembering that the caller must free it, like so:

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

char * Func(void);

int main (void) {
  char * string = Func();
  puts(string);
  free(string);
  return 0;
}

char * Func (void) {
  char * string = malloc(10);
  strcpy(string, "test");
  return string;
}

Either way would solve your issue, and which one you choose is a matter of design.

aaaaaa123456789
  • 5,541
  • 1
  • 20
  • 33