c string still works when out of boundary? [duplicate] - c

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 9 years ago.
who can tell me why the code below still works? it is obvious that the str[4] is out of boundry:
#include<stdio.h>
int main(){
char str[3];
scanf("%s", str);
printf("%c\n", str[4]);
printf("%s\n", str);
return 0;
}
when it runs, enter abcdefg, it will echo the 5th char and the whole string, nothing
will be wrong, weird?
It has been declared that c/c++ doesn't do the boundary checking, while in the case above,
how should I use printf to print a c-string that the user has entered? or more generally, how to properly use a c-string that comes from users?

str[4] gives you a pointer to the memory address after the last element of your string. You can still convert this to a character, but you never know what you get and your software might crash.

Why does it work?
It doesn't "work". It might appear to be working, though; since your code (accessing an array out of bounds) invokes undefined behavior, you can get literally any result. Undefined behavior doesn't mean "it must crash".

You wrote:
when it runs, enter [abcdefg], it will echo the 5th char and the whole
string, nothing will be wrong, weird?
but I see no input reading in the code you posted:
#include<stdio.h>
int main(){
char str[3];
printf("%c\n", str[4]);
printf("%s\n", str);
return 0;
}
In any case, str[4] points to the 5-th char (byte) starting from str, so it will print any "garbage" that happens to be in that memory location when your program runs.
Accessing array items out of bounds is undefined behavior, so the exact behavior is not specified.
Just pay attention to your array bounds.

Related

Why does passing right values through pointers results in segfault? [duplicate]

This question already has answers here:
Is it possible to modify a string of char in C?
(9 answers)
Closed 3 years ago.
Im currently teaching myself c, and during exercising pointers use I bumped into this problem-
I'm trying to replace a substring in a string that is pointed to (meaning,not a char array), with a substring from another pointed string.
char *str1="I like pizza!";
char *str2="love";
printf("%s\n", str1);
for (int i=2, j=0; j<4; i++, j++) {
*(str1+i)=*(str2+j);
}
printf("%s\n", str1);
Result should be- the way I see it- output of "I like pizza", followed by output of "I love pizza".
Instead, I get a segfault (error 139).
I scraped the web for a solution but couldn't find what is the problem.
(I am aware that the for loop is not perfect, to say the least, but that's not the issue here).
Please help me out :)
Because those are pointers to a read-only part in you're program's binary. You can't change the content. Try this instead:
char str1[] = "I like pizza!";
char str2[] = "love"; // actually, this one can stay as a pointer as we're only reading
Now the strings are copied to the stack and the program works as intended.
The strings pointed to by str1 and str2 are read-only.
The behaviour on attempting to change their contents is undefined.
Use char str1[] = "I like pizza!"; &c. instead, which copies the read-only string to str1[], which you are then free to modify.

Character array initialization in C

I am trying to understand the array concept in string.
char a[5]="hello";
Here, array a is an character array of size 5. "hello" occupies the array index from 0 to 4. Since, we have declared the array size as 5, there is no space to store the null character at the end of the string.
So my understanding is when we try to print a, it should print until a null character is encountered. Otherwise it may also run into segmentation fault.
But, when I ran it in my system it always prints "hello" and terminates.
So can anyone clarify whether my understanding is correct. Or does it depends upon the system that we execute.
As ever so often, the answer is:
Undefined behavior is undefined.
What this means is, trying to feed this character array to a function handling strings is wrong. It's wrong because it isn't a string. A string in C is a sequence of characters that ends with a \0 character.
The C standard will tell you that this is undefined behavior. So, anything can happen. In C, you don't have runtime checks, the code just executes. If the code has undefined behavior, you have to be prepared for any effect. This includes working like you expected, just by accident.
It's very well possible that the byte following in memory after your array happens to be a \0 byte. In this case, it will look to any function processing this "string" as if you passed it a valid string. A crash is just waiting to happen on some seemingly unrelated change to the code.
You could try to add some char foo = 42; before or after the array definition, it's quite likely that you will see that in the output. But of course, there's no guarantee, because, again, undefined behavior is undefined :)
What you have done is undefined behavior. Apparently whatever compiler you used happened to initialize memory after your array to 0.
Here, array a is an character array of size 5. "hello" occupies the array index from 0 to 4. Since, we have declared the array size as 5, there is no space to store the null character at the end of the string.
So my understanding is when we try to print a, it should print until a null character is encountered.
Yes, when you use printf("%s", a), it prints characters until it hits a '\0' character (or segfaults or something else bad happens - undefined behavior). I can demonstrate that with a simple program:
#include <stdio.h>
int main()
{
char a[5] = "hello";
char b[5] = "world";
int c = 5;
printf("%s%s%d\n", a, b, c);
return 0;
}
Output:
$ ./a.out
helloworldworld5
You can see the printf function continuing to read characters after it has already read all the characters in array a. I don't know when it will stop reading characters, however.
I've slightly modified my program to demonstrate how this undefined behavior can create bad problems.
#include <stdio.h>
#include <string.h>
int main()
{
char a[5] = "hello";
char b[5] = "world";
int c = 5;
printf("%s%s%d\n", a, b, c);
char d[5];
strcpy(d, a);
printf("%s", d);
return 0;
}
Here's the result:
$ ./a.out
helloworld��world��5
*** stack smashing detected ***: <unknown> terminated
helloworldhell�p��UAborted (core dumped)
This is a classic case of stack overflow (pun intended) due to undefined behavior.
Edit:
I need to emphasize: this is UNDEFINED BEHAVIOR. What happened in this example may or may not happen to you, depending on your compiler, architecture, libraries, etc. You can make guesses to what will happen based on your understanding of different implementations of various libraries and compilers on different platforms, but you can NEVER say for certain what will happen. My example was on Ubuntu 17.10 with gcc version 7. My guess is that something very different could happen if I tried this on an embedded platform with a different compiler, but I cannot say for certain. In fact, something different could happen if I had this example inside of a larger program on the same machine.

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

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.

String size is equal to number of characters

I was making a basic program of strings and did this. There is a string in this way:
#include<stdio.h>
int main()
{
char str[7]="network";
printf("%s",str);
return 0;
}
It prints network.In my view, it should not print network. Some garbage value should be printed because '\0' does not end this character array. So how it got printed? There were no warning or errors too.
That's because
char str[7]="network";
is the same as
char str[7]={'n','e','t','w','o','r','k'};
str is a valid char array, but not a string, because it's no null-terminated. So it's undefined behavior to use %s to print it.
Reference: C FAQ: Is char a[3] = "abc"; legal? What does it mean?
char str[7]="network";
This Invokes Undefined behavior.
You did not declared array with enough space
This should be
char str[8]="network";
char str[7]="network";
you did not provide enough space for the string
char str[8]="network";
It's possible that stack pages start off completely zeroed in your system, so the string is actually null-terminated in memory, but not thanks to your code.
Try looking at the program in memory using a debugger, reading your platform documentation or printing out the contents of str[7] to get some clues. Doing so invokes undefined behavior but it's irrelevant when you're trying to figure out what your specific compiler and OS are doing at one given point in time.

Why is this wrong? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why does this Seg Fault?
What is the difference between char a[] = “string”; and char *p = “string”;
Trying to understand why s[0]='H' fails. I'm guessing this has something to do with the data segment in the process memory but maybe someone better explain this?
void str2 (void)
{
char *s = "hello";
printf("%s\n", s);
s[0] = 'H'; //maybe this is a problem because content in s is constant?
printf("%s\n", s);
}
int main()
{
str2();
return 0;
}
It's wrong because the C standard says that attempting to modify a string literal gives undefined behavior.
Exactly what will happen can and will vary. In some cases it'll "work" -- the content of the string literal will change to what you've asked (e.g., back in the MS-DOS days, it usually did). In other cases, the compiler will merge identical string literals, so something like:
char *a = "1234";
char *b = "1234";
a[1] = 'a';
printf("%s\n", b);
...would print out 1a34, even though you never explicitly modified b at all.
In still other cases (including most modern systems) you can expect the attempted write to fail completely and some sort of exception/signal to be thrown instead.
You are trying to modify a string literal, which resides in implementation defined read only memory thereby causing an Undefined Behavior. Note that the undefined behavior does not warrant that your program crashes but it might show you any behavior.
Good Read:
What is the difference between char a[] = ?string?; and char *p = ?string?;?
I think this behavior, a good or stern compiler should not allow since this is (char *s = "hello") pointer to constant i.e. modifying the contents will lead to undefined behavior if the compiler will not throw any error on this

Resources