Unexpected String behaviour during printing - c

I am experiencing some unpredictable behaviour in case of strings.Here it goes :
int main()
{
char *str = charfun();
printf("%s",str); // This is printing garbage values
printf("%c%c%c%c",str[0],str[1],str[2],str[3]); /* if I am printing
like this it is printing the result "Helo" why is it so ?
and str[4] is '\0' (checked its ASCII value)*/
return 0;
}
char* charfun()
{
char a[10]="Helo";
return a;
}
EDIT -
The thing which i am concerned about is not the local address which i am returning.I know it can land me into trouble . But i want to understand the printing methodology which the two printf are following and give different results.

It is because a in charfun() is a local array. When charfun() returns, a's address is assigned to str, but the array it pointed to is already invalidated.

The issue here is that when you create the local variable it is allocated on the stack and is therefore unavailable once the function finishes execution. The preferable way would be to use malloc() to reserve non-local memory. the string a is local to the function, you can't return a pointer to it, It's an Undefined Behavior so it must be allocated on heap instead of stack using malloc:
char *charfun(){
char *a = malloc(sizeof(char)*10);
strcpy(a,"Helo");
return a;
}

Related

Why can I return `int` after a function but not `char *`?

I'm a newbie to C. I had extended the question from the previous question: Strange behavior when returning "string" with C (Thanks for all who answered or commented that question, by the way.)
Pretty straight forward:
Why can this work:
#include <stdio.h>
int func() {
int i = 5;
return i;
}
int main() {
printf("%d",func());
}
But not this:
#include <stdio.h>
char * func() {
char c[] = "Hey there!";
return c;
}
int main() {
printf("%s",func());
}
From the previous question, logically the int i should not exist too because the function has returned, but why can it still be returned while char c[] cannot?
(It seems to be duplicated from "Pointers and memory scope" but I would like to know more about what is the difference between returning an int and a char *.)
Problem is not returning char *, it is returning something that is allocated on stack.
If you allocate memory for your string rather than pointing to function stack, there will be no problem. Something like this:
char * func() {
char c[] = "Hey there!";
return strdup(c);
}
int main() {
char* str = func();
printf("%s", str);
free(str);
}
It is important to mention that in both cases, you are copying a value and in both cases copied value is correct, but the meaning of copied value differs.
In first case, your are copying an int value and after your return from function, you are using that int value which will be valid. But in 2nd case, even though you have a valid pointer value, it refers to an invalid address of memory which is stack of called function.
Based on suggestions in comment, I decided to add another better practice in memory allocating for this code:
#define NULL (void*)0
int func(char *buf, int len) {
char c[] = "Hey there!";
int size = strlen(c) + 1;
if (len >= size) {
strcpy(buf, c);
}
return size;
}
int main() {
int size = func(NULL, 0);
char *buf = calloc(size, sizeof(*buf));
func(buf, size);
printf("%s", buf);
free(buf);
return 0;
}
Similar approach is used in a lot of windows API functions. This approach is better, because owner of pointer is more obvious (main in here).
In the first example the return value is copied. In your second example you're returning a pointer, which will point to a memory location which no longer exists.
In the first case, you return the int value 5 from the function. You can then print that value.
In the second case however, you return a value of type char *. That value points to an array that is local to the function func. After that function returns the array goes out of scope, so the pointer points to invalid memory.
The difference between these two cases is a value that you use directly, versus a pointer value that no longer points to valid memory. Had you returned a pointer to memory allocated by malloc, then the pointer would point to valid memory.
You are trying to return pointer to local array, which is very bad. If you want to return a pointer to array, allocate it dynamically using malloc inside your func();
Then you must call free() on caller side to free up memory you allocated when you no longer need it
In the first example, you return an int, and the second you return a pointer to a char. They both return in exactly the same manner, it is just a matter of understanding the stack and how values are returned.
Even though i was declared in the function and is allocated on the stack, when the function returns it returns the value of i (which is basically copied, so when i falls off the stack the value of i is still returned.)
This is the exact same thing that happens to the char * in the second example. It will still be a pointer to a char, and it returns the 'copied' value of c. However, since it was allocated on the stack, the address it points to is effectively invalid. The pointer value itself has not changed, but what it points to has.
You would have to dynamically allocate this to avoid this situation.
The return value of function is returned by copy. In the first example, you get a copy of the integer variable from the function. In the second you get a copy of the char pointer, not a copy of the string.
The pointer references the string data that has automatic storage, so is no longer valid after the function returns. The space becomes available for use by other code and many be modified - any attempt to access it has undefined behaviour.
The point is, it is a pointer that is returned, not a string; in C a strings (and more generally arrays) are not a first-class data types.
Depending on your needs there are a number of valid ways of returning the string data; for example the following is valid:
char* func()
{
static char c[] = "Hey there!";
return c;
}
because here although the local variable goes out of scope the static data is not destroyed or de-allocated, and any reference to it remains valid.
Another alternative is to embed the string in a struct which is a first-class data type:
typedef struct
{
char content[256] ;
} sString ;
sString func()
{
sString c = {"Hey there!"};
return c;
}
Or more conventionally to copy the data to a caller buffer:
char* func( char* buffer )
{
char c[] = "Hey there!";
strcpy( buffer, c ) ;
return buffer ;
}
I have omitted code to mitigate the possibility of buffer overrun above for clarity in this last example, such code is advised.

Can I use values of array declared as local variable outside of its scope?

Suppose the following simple code:
int main(void){
char *p;
int i = 1;
while(i){
char str[] = "string";
p = str;
i = 0;
}
/* Can I use above string by using `p` in here? */
return 0;
}
I declared a string (char array) as local variable only valid in while{}. But I saved its array address to the pointer p which is also valid outside while{}. Is it okay use the string outside while{} by using p?
If it is okay, why does it work?
Is it okay use the string outside while{} by using p?
No. In the scope of while p is pointing to first character of str. Outside of while there is no str and hence there is no valid memory location where p is pointing to.
You can achieve the desired effect by using static storage class specifier in str declaration
static char str[] = "string";
Outside the while you can use p
printf("%s\n", p);
This is because static variables declared within a block resides at the same storage location throughout program execution.
No, this is not OK. This is what is known as a dangling pointer. If you manage to use the memory before the program attempts to reuse this address, you may still get your expected result. However, if the memory is used again, you will get unexpected results and bugs that are very hard to locate.
Try this as an example, it may not work with all compilers but in Xcode on OS X I get this result:
pa: apples
pa: orange
po: orange
#include <stdio.h>
char *pa;
char *po;
void apples(void)
{
char sa[]="apples";
pa = sa;
printf("pa: %s\n", pa);
}
void orange(void)
{
char so[]="orange";
po = so;
printf("pa: %s\n", pa);
printf("po: %s\n", po);
}
int main(void)
{
apples();
orange();
return 0;
}
Each function call to apples() and orange() subsequently grows and then shrinks the stack and you can see how the string (either apples or orange) ends up in the same memory location on the stack. But there are zero guarantees that string will be there once it is out of scope. This trick "works" here, but it is very dangerous.
As an additional exercise, try printing the contents of po in main() after the call to orange(), in most cases the string will be gone as the call to printf() overwrites that space on the stack.
str points to the read-only (data) area of the process. You can access (read) that data with p, as well. However, attempting to write to that location will result in segmentation fault.

Passing array of string pointers to function and reading value of the strings

I have an assignment where I am required to pass an array of string pointers to a function, assign strings and then read back these strings. Here is what I am doing:
void getStr(char *str[])
{
char temp[256];
strcpy (temp,"Apple");
*str = temp;
printf("\ngetStr Str= %s",*str);
str++;
strcpy (temp,"Mango");
*str = temp;
printf("\ngetStr Str= %s",*str);
str++;
}
int main()
{
char *str[2] ;
int i=0;
getStr (str);
for(i =0 ;i<2;i++)
printf("\nstr addr =%x, str= %s\n",&str[i],str[i]);
return 1 ;
}
Here is my output:
getStr Str= Apple
getStr Str= Mango
str addr =28d623b0, str=
str addr =28d623b8, str=
So str gets the strings assigned correctly in getStr(), but when I print them in main() it is blank. What am I doing wrong here?
You stored into str the address of the first element of the local variable temp (the array decayed into a pointer), but that array's lifetime ends once getStr() returns. Hence you are accessing a local variable after its lifetime ended, and undefined behavior results.
This sort question seems to be coming up constantly.
void getStr(char *str[])
{
char temp[256];
...
}
That temp array is a block of memory whose lifetime is tied to the duration of the getStr function.
Also, when you overwrite it from "Apple" to "Mango", then the pointer you had stored that used to point to temp in str[0] will point to "Mango". str[0] and str[1] hold the same pointer! And that pointer is no longer pointing to valid memory as soon as you return from the function. :-/
For these kinds of problems, C programmers use things like strdup. That does a memory allocation for each string and is a little bit more ergonomic than having to do strlen/malloc/strcpy. Either way, remember to free() each string when you're done with them.
This is very old post, but I must update it because I have similar problem, and I found out, that in side of function, I need use pointer only once, and array is restored like I am using this original from outside.
void getStr(char *str)
{
str[1] = (temp,"Apple");
str[2] = (temp,"Mango");
}
int main()
{
char str[2] ;
int i=0;
getStr (str);
for(i =0 ;i<2;i++)
printf(str[i]);
return 1 ;
}
That's why I hate use pointers, is to much mist-confusion and pointers it self are used in wrong way. They should be used only in special cases, like passing some arrays to function, to prevent making copy of this same twice. And Function it self don't need output set of values.
But that's is only in special case. Using pointers on each line in program don't have sense if compiler is doing it anyway, From what I learned, pointers was design only because there was to much problems with functions and passing big sort of data.

Why do these programs (that differ only in one printf statement) have such different output?

Program #1:
#include<stdio.h>
#include<stdlib.h>
char *getString()
{
char str[] = "GfG";
printf("%s \n", str);
return str;
}
int main()
{
printf("%s", getString());
return 0;
}
Output:
GfG
GfG
Program #2:
#include<stdio.h>
#include<stdlib.h>
char *getString()
{
char str[] = "GfG";
return str;
}
int main()
{
printf("%s", getString());
return 0;
}
Output:
(garbage value)
Please explain why because of only a printf statement output differs. What is exact description?
Because both programs show undefined behavior.
When the getString function returns the str array object is destroyed and trying to access it after its lifetime is undefined behavior.
You can fix your program using a string literal, as string literals have static storage duration and their lifetime is the entire duration of the program:
char *getString(void)
{
char *str = "GfG";
return str;
}
char str[] = "GfG";
declares an automatic variable. It is only valid to access this inside the scope it was declared in (the function getString). Attempting to use it anywhere else results in undefined behaviour. You've been unlucky that the first version appeared to work.
When getString returns, the stack region used to store str may be reused. If this happens, printf will end up reading further through memory until it finds either a '\0' byte or crashes.
You must either allocate the memory with malloc or try with static.
Just remember that arrays are not passed by value in C, they are passed by address. Since str is defined in getstring(), after the control returns to main() it is not valid to access that specific address.If you do happen to access the address, the result will be unpredictable. Just remember that the C compiler does not check for incorrect memory access requests in the program.
Local variable char str[] = "GfG"; scope is limited to the function. So when you try to print that in function scope, it works. But when you try to access that from outside of that function its undefined behavior.
#include<stdio.h>
#include<stdlib.h>
char *getString()
{
char str[] = "GfG"; // Local variable, so once you try to return that it is undefined
return str;
}
int main()
{
printf("%s", getString());
return 0;
}
Go through the below link you will get some more example.
Does local variable be deleted from memory when this function is called in main
In both cases, char str[] = "GfG"; is put on the stack inside the first function. It returns a pointer to that. The caller tries to use it and give it to printf(), but in the mean time, the "old" stack content was already overwritten.
There may be a difference between them which makes the first one keep the old content a bit longer, but there is no guarantee for that and therefore it is undefined behaviour.

How char[] and char* are different in this case?

When we run this piece of code, it works normally and prints string constant on the screen:
char *someFun(){
char *temp = "string constant";
return temp;
}
int main(){
puts(someFun());
}
But when we run the following similar code, it won't work and print some garbage on screen:
char *someFun1(){
char temp[ ] = "string";
return temp;
}
int main(){
puts(someFun1());
}
What is the reason behind it? Essentially, both functions do similar things (i.e. return a "string"), but still they behave differently. Why is that?
char *temp = "string constant";
string constant literal resides on read only segment. It gets deallocated at program termination. So, you can have a reference pointing to it.
char temp[ ] = "string";
string is copied to temp which resides on stack. As the function returns, unwinding of stack begins which de-allocates the variables in the function scope. But you are returning a reference to it which no longer exists on stack and hence you are getting garbage. But sometimes you may still get the correct result but you should not rely on it.
In the first case, the pointer temp will point to a global constant storing "string constant". Therefore, when you return the pointer, it's valid.
In the second case, '"string"' is just a char array on the stack - which dies after you return from the function.

Resources