Unable to predict the ouput of the following program [duplicate] - c

This question already has answers here:
Returning an array using C
(8 answers)
Closed 8 years ago.
I have an idea on dangling pointer. I know that the following program will produce a dangling pointer.But I couldnt understand the output of the program
char *getString()
{
char str[] = "Stack Overflow ";
return str;
}
int main()
{
char *s=getString();
printf("%c\n",s[1]);
printf("%s",s); // Statement -1
printf("%s\n",s); // Statement -2
return 0;
}
The output of the following program is
t
if only Statement-1 is there then output is some grabage values
if only Statement-2 is there then output is new line

Your code shows undefined behaviour, as you're returning the address of a local variable.
There is no existence of str once the getString() function has finished execution and returned.
As for the question,
if only Statement-1 is there then output is some grabage values if only Statement-2 is there then output is new line
No explanations. Once your program exhibits undefined behaviour, the output cannot be predicted, that's all. [who knows, it might print your cell phone number, too, or a daemon may fly out of my nose]
For simple logical part, adding a \n in printf() will cause the output buffer to be flushed to the output immediately. [Hint: stdout is line buffered.]
Solution:
You can do your job either of the two ways stated below
Take a pointer, allocate memory dynamically inside getString() and return the pointer. (I'd recommend this). Also, free() it later in main() once you're done.
make the char str[] static so that the scope is not limited to the lifetime of the function. (not so good, but still will do the job)

your str in getString is a local variable, which is allocate on stack, and when the function returns, it doesn't exist anymore.
I suggest you rewrite getString() like this
char *getString()
{
char str[] = "Stack Overflow ";
char *tmp = (char*)malloc(sizeof(char)*strlen(str));
memcpy(tmp, str, strlen(str));
return tmp;
}
and you need to add
free(s);
before return 0;
In my case, pointer tmp points to a block memory on heap, which will exist till your program ends
you need to know more about stack and heap
Besides, there is still another way, use static variable instead
char *getString()
{
static char str[] = "Stack Overflow ";
return str;
}
PS: You get the correct answer for the following statement printf("%c\n",s[1]); is just a coincidence. Opera System didn't have time to do some clean work when you return from function. But it will

Array is returned as a pointer yet the array itself is the garbage after return from function. Just use static modifier.
What's concerning s[1] is OK. The point is, it's the first printf after getting the dangling pointer. So, the stack at this point is still (probably) intact. You should recall that stack is used for function calls and local variables only (in DOS it could be used by system interrupts, but now it's not the case). So, before the first printf (when s[1] is calc'ed), s[] is OK, but after - it's not (printf' code had messed it up). I hope, now it's clear.

Related

Print a string which is returned by a function. I have to two cases here, one it returns pointer to string, other char array [duplicate]

This question already has answers here:
Function returning address of local variable error in C
(3 answers)
Closed 3 years ago.
I have two cases to return the string. One returns a pointer and other returns the char array. The first case works fine while printing the string, but I am getting a segmentation fault error on the second case. I want to know why this is happening?
This is the first case, and it gives the output.
char* voice(void){
return "hey!";
}
int main(){
printf ("%s\n", voice()); //output: hey!
return 0;
}
This is the second case, and it gives a segmentation fault.
char* voice(void){
char str[] = "hey!";
return str;
}
int main(){
printf ("%s\n", voice()); //segmentation fault
return 0;
}
Second case does not work because you are returning address of a local array.
The scope of local array "str" is limited to the function. So the array is valid only within that function. It becomes invalid once you go out of the function. The behavior of the program will be undefined in this case.
In 1st case, you are returning address of a string constant. String constants are allocated in a separate memory space and they will be retained throughout the program. So the address of string will be still valid even after you return from voice().
In C, local arrays (like str in your second example) are by default stored in the stack section of memory. That means that the section of memory that stores str becomes unreachable as soon as voice() returns, thus producing the segmentation error when you are trying to reach unreachable memory.
String literals (like "hey") are stored in the code section of memory. Even when voice() returns, the string is still stored in the code section of memory.

function returning pointer to string not working [duplicate]

This question already has an answer here:
Returning Local Variable Pointers - C [duplicate]
(1 answer)
Closed 7 years ago.
I want to know why doesn't the following work correctly? Though I have tried the other ways that work, but for the sake of more clarity I would like to know the problem occurring here.
char *fuc(char *s)
{
char t[10];
int r=0;
while(s[r] != '\0')
{
t[r] = s[r];
r++;
}
t[r]='\0';
return &t[0];
}
main()
{
char s[]="abcde";
char *p;
p=func(s);
puts(p);
}
In your fuc(), char t[10]; is a local variable. Once your function finishes execution, there is no existence of t. So, in the caller, the returned pointer becomes invalid.
Using that returned pointer further leads to undefined behaviour.
If you want to return the pointer from fuc(), you need to make use of dynamic memory allocation function , like malloc() and family. In that case, inside the caller function, once you're done using the memory, you need to take care for free()-ing the allocated memory, too.
That said, from the logical point of view, inside your fuc(), you're iterating over t without any check on the bounds. You should check for the size of t before using the index.
Furthermore, main() is not a proper form of the function. At Least, it should be int main(void).
Array t is local to function func() so once you exit the function you can't access array t which will lead to undefined behavior.
You should allocate memory on heap.
char *t = malloc(10);
Now you can return a pointer from the function func()

Modifying a char array inside a function in C [duplicate]

This question already has an answer here:
Is modification of string literals undefined behaviour according to the C89 standard?
(1 answer)
Closed 7 years ago.
So I've been playing around with C lately and have been trying to understand the intricacies of passing by value/reference and the ability to manipulate a passed-in variable inside a function. I've hit a road block, however, with the following:
void modifyCharArray(char *input)
{
//change input[0] to 'D'
input[0] = 'D';
}
int main()
{
char *test = "Bad";
modifyCharArray(test);
printf("Bad --> %s\n", test);
}
So the idea was to just modify a char array inside a function, and then print out said array after the modification completed. However, this fails, since all I'm doing is modifying the value of input that is passed in and not the actual memory address.
In short, is there any way I can take in a char *input into a function and modify its original memory address without using something like memcpy from string.h?
In short, is there any way I can take in a char *input into a function and modify its original memory address without using something like memcpy from string.h?
Yes, you can. Your function modifyCharArray is doing the right thing. What you are seeing is caused by that fact that
char *test = "Bad";
creates "Bad" in read only memory of the program and test points to that memory. Changing it is cause for undefined behavior.
If you want to create a modifiable string, use:
char test[] = "Bad";

Abort instead of segfault with clear memory violation

I came upon this weird behaviour when dealing with C strings. This is an exercise from the K&R book where I was supposed to write a function that appends one string onto the end of another string. This obviously requires the destination string to have enough memory allocated so that the source string fits. Here is the code:
/* strcat: Copies contents of source at the end of dest */
char *strcat(char *dest, const char* source) {
char *d = dest;
// Move to the end of dest
while (*dest != '\0') {
dest++;
} // *dest is now '\0'
while (*source != '\0') {
*dest++ = *source++;
}
*dest = '\0';
return d;
}
During testing I wrote the following, expecting a segfault to happen while the program is running:
int main() {
char s1[] = "hello";
char s2[] = "eheheheheheh";
printf("%s\n", strcat(s1, s2));
}
As far as I understand s1 gets an array of 6 chars allocated and s2 an array of 13 chars. I thought that when strcat tries to write to s1 at indexes higher than 6 the program would segfault. Instead everything works fine, but the program doesn't exit cleanly, instead it does:
helloeheheheheheh
zsh: abort ./a.out
and exits with code 134, which I think just means abort.
Why am I not getting a segfault (or overwriting s2 if the strings are allocated on the stack)? Where are these strings in memory (the stack, or the heap)?
Thanks for your help.
I thought that when strcat tries to write to s1 at indexes higher than 6 the program would segfault.
Writing outside the bounds of memory you have allocated on the stack is undefined behaviour. Invoking this undefined behaviour usually (but not always) results in a segfault. However, you can't be sure that a segfault will happen.
The wikipedia link explains it quite nicely:
When an instance of undefined behavior occurs, so far as the language specification is concerned anything could happen, maybe nothing at all.
So, in this case, you could get a segfault, the program could abort, or sometimes it could just run fine. Or, anything. There is no way of guaranteeing the result.
Where are these strings in memory (the stack, or the heap)?
Since you've declared them as char [] inside main(), they are arrays that have automatic storage, which for practical purposes means they're on the stack.
Edit 1:
I'm going to try and explain how you might go about discovering the answer for yourself. I'm not sure what actually happens as this is not defined behavior (as others have stated), but you can do some simple debugging to figure out what your compiler is actually doing.
Original Answer
My guess would be that they are both on the stack. You can check this by modifying your code with:
int main() {
char c1 = 'X';
char s1[] = "hello";
char s2[] = "eheheheheheh";
char c2 = '3';
printf("%s\n", strcat(s1, s2));
}
c1 and c2 are going to be on the stack. Knowing that you can check if s1 and s2 are as well.
If the address of c1 is less than s1 and the address of s1 is less than c2 then it is on the stack. Otherwise it is probably in your .bss section (which would be the smart thing to do but would break recursion).
The reason I'm banking on the strings being on the stack is that if you are modifying them in the function, and that function calls itself, then the second call would not have its own copy of the strings and hence would not be valid... However, the compiler still knows that this function isn't recursive and can put the strings in the .bss so I could be wrong.
Assuming my guess that it is on the stack is right, in your code
int main() {
char s1[] = "hello";
char s2[] = "eheheheheheh";
printf("%s\n", strcat(s1, s2));
}
"hello" (with the null terminator) is pushed onto the stack, followed by "eheheheheheh" (with the null terminator).
They are both located one after the other (thanks to plain luck of the order in which you wrote them) forming a single memory block that you can write to (but shouldn't!)... That's why there is no seg fault, you can see this by breaking before printf and looking at the addresses.
s2 == (uintptr_t)s1 + (strlen(s1) + 1) should be true if I'm right.
Modifying your code with
int main() {
char s1[] = "hello";
char c = '3';
char s2[] = "eheheheheheh";
printf("%s\n", strcat(s1, s2));
}
Should see c overwritten if I'm right...
However, if I'm wrong and it is in the .bss section then they could still be adjacent and you would be overwriting them without a seg fault.
If you really want to know, disassemble it:
Unfortunately I only know how to do it on Linux. Try using the nm <binary> > <text file>.txt command or objdump -t <your_binary> > <text file>.sym command to dump all the symbols from your program. The commands should also give you the section in which each symbol resides.
Search the file for the s1 and s2 symbols, if you don't find them it should mean that they are on the stack but we will check that in the next step.
Use the objdump -S your_binary > text_file.S command (make sure you built your binary with debug symbols) and then open the .S file in a text editor.
Again search for the s1 and s2 symbols, (hopefully there aren't any others, I suspect not but I'm not sure).
If you find their definitions followed by a push or sub %esp command, then they are on the stack. If you're unsure about what their definitions mean, post it back here and let us have a look.
There's no seg fault or even an overwrite because it can use the memory of the second string and still function. Even give the correct answer. The abort is a sign that the program realized something was wrong. Try reversing the order in which you declare the strings and try again. It probably won't be as pleasant.
int main() {
char s1[] = "hello";
char s2[] = "eheheheheheh";
printf("%s\n", strcat(s1, s2));
}
instead use:
int main() {
char s1[20] = "hello";
char s2[] = "eheheheheheh";
printf("%s\n", strcat(s1, s2));
}
Here is the reason why your program didn't crash:
Your strings are declared as array (s1[] and s2[]). So they're on the stack. And just so happens that memory for s2[] is right after s1[]. So when strcat() is called, all it does is moving each character in s2[] one byte forward. Stack as stack is readable and writable. So there is no restriction what you'e doing.
But I believe the compiler is free to locate s1[] and s2[] where it see fits so this is just a happy accident.
Now to get your program to crash is relatively easy
Swap s1 and s2 in your call: instead of strcat(s1, s2), do strcat(s2, s1). This should cause stack smashing exception.
Change s1[] and s2[] to *s1 and *s2. This should cause segfault when you're writing to readonly segment.
hmm.... the strings are in stack all right since heap is used only for dynamic allocation of memory and stuff..
segfault is for invalid memory access, but with this array you are just writing stuff which is going out of bound (outside the boundry) for the array , so while writing i dont think you will have a issue .... Since in C its actually left to the programer to ensure things are kept in bound for arrays.
Also while reading if you use pointers - I dont think there will be a issue either since you can just continue to read till where ever you want and using the sum of previous lengths. But if you use functions that are mentioned in string.h they relay on the presence of the null character "\0" to decide where to halt the operation -- hence i think your function worked !!
but the termination could also indicate that any other variable / something that might have been present next to the location of the strings might have got over written with char value .... accessing those might have caused the program to exit !!
hope this helps .... good question by the way !

Pointer and Function ambiguity in C

Please look at the following code:
char* test ( )
{
char word[20];
printf ("Type a word: ");
scanf ("%s", word);
return word;
}
void main()
{
printf("%s",test());
}
When the function returns, the variable word is destroyed and it prints some garbage value. But when I replace
char word[20];
by char *word;
it prints the correct value. According to me, the pointer variable should have been destroyed similar to the character array and the output should be some garbage value. Can anyone please explain the ambiguity?
Undefined behavior is just that - undefined. Sometimes it will appear to work, but that is just coincidence. In this case, it's possible that the uninitialized pointer just happens to point to valid writeable memory, and that memory is not used for anything else, so it successfully wrote and read the value. This is obviously not something you should count on.
You have undefined behavior either way, but purely from a "what's going on here" viewpoint, there's still some difference between the two.
When you use an array, the data it holds is allocated on the stack. When the function returns, that memory will no longer be part of the stack, and almost certainly will be overwritten in the process of calling printf.
When you use the pointer, your data is going to be written to whatever random location that pointer happens to have pointed at. Though writing there is undefined behavior, simple statistics says that if you have (for example) a 32-bit address space of ~4 billion locations, the chances of hitting one that will be overwritten in the new few instructions is fairly low.
You obviously shouldn't do either one, but the result you got isn't particularly surprising either.
Because the char array is defined and declared in the function, it is a local variable and no longer exists after the function returns. If you use a char pointer and ALLOCATE MEMORY FOR IT then it will remain, and all you need is the pointer (aka a number).
int main(int argc, char* argv[]) {
printf("%s", test());
return 0;
}
char* test(void) {
char* str = (char*)malloc(20 * sizeof(char));
scanf("%19s", str);
return str;
}
Notice how I used %19s instead of %s. Your current function can easily lead to a buffer overflow if a user enters 20 or more characters.
During program execution first it will create activation records for the function main in stack segment of the process memory. In that main activation records it will allocate memory for the local variable of that function(main) and some more memory for internal purpose. In your program main doesn't has any local variable, so it will not allocate any memory for local variables in main activation records.
Then while executing the statement for calling the function test, it will create one more activation records for the calling function(test) and it will allocate 20 bytes for the local variable word.
Once the control exits the function test, activation record created for that function will be poped out of that stack. Then it will continue to execute the remaining statment (printf) of the called function main. Here printf is trying to print the characters in the test function's local variable which is already poped out of the stack. So this behaviour is undefined, sometimes it may print the proper string or else it will print some junk strings.
So in this situation only dynamic memory comes into picture. With the help of dynamic memory we can control the lifetime(or scope) of a variable. So use dynamic memory like below.
char *word = NULL:
word = (char *) malloc(sizeof(char) * 20);
Note : Take care of NULL check for the malloc return value and also dont forget to free the allocated memory after printf in main function.

Resources