I got these test code and just curious, why passing pointer to gets() results in a runtime error?
void main()
{
char *value="gogo";
puts(value);
value="11";
puts(value);
gets(value);
}
Because char *value="gogo"; is more likely than not allocated to READ ONLY MEMORY!
Better:
#include <stdio.h>
#include <string.h>
#define MAX_LINE 80
int main()
{
char value[MAX_LINE] ="gogo";
puts(value);
strcpy (value, "11");
puts(value);
fgets(value, MAX_LINE, stdin);
puts(value);
return 0;
}
Here is a good link with more details: Storage for Strings in C
PS:
gets() is Evil. Avoid it if at all possible: Why gets() is bad
The pointer value points to (the static array associated with) a string literal.
Attempting to modify a string literal has undefined behavior. In this case, your compiler stores the string "gogo" in memory marked as read-only by the operating system, and attempting to modify it causes your program to crash.
If you declare a pointer to a string literal, you should define it as const:
const char *value = "gogo";
so the compiler will diagnose any attempt to modify it. Or, if you really want to modify the string, define it as an array:
char value[] = "gogo";
which the means that you can't assign a value to value, but you can use strcpy to update it.
Some more problems:
void main() is wrong [*]; the correct definition is int main(void). If you're using a book that told you to use void main(), please get a better one; its author does not know C very well.
Never use the gets function; it is inherently unsafe, and has been removed from the language. (It cannot guard against input longer than the array into which the value is stored.) You can use fgets instead; it's a bit more complicated to use, but it can be used safely.
You need to add
#include <stdio.h>
to the top of your source file to make these functions visible. If your compiler didn't complain about calls to undeclared functions, find out how to increase its warning level.
[*] Saying that void main() is wrong slightly overstates the case. A conforming compiler may permit it, and no compiler is required to complain about it, but there is no good reason to take advantage of that. int main(void) is always correct. Any C book or tutorial that advocates using void main() was almost certainly written by someone who does not know C well enough to be writing books or tutorials about it.
Here, your pointer points to a string literal ("gogo"). String literals are not guaranteed to be writable. You need to allocate your own memory:
char value[50] = "gogo";
...
gets(value);
However, this is not safe, as gets does not take the size of the buffer, and thus might overflow your buffer. (Which could also lead to a runtime error). NEVER use gets, as the manpage states:
BUGS
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
Much better to allocate your own memory:
char user_input[200];
fgets(user_input, 200, stdin);
You might need to check user_input, to see if it ends with a newline. If it does, then fgets read a whole line. If it doesn't, then the the user typed more than ~200 characters into the line, and you'll need to read more to get the whole line. I've used 200 here. Choose a size that makes sense for your data. You can also use malloc to allocate memory on-the-fly, and put fgets into a loop in order to read an entire line into a buffer.
Related
If I am correct, doing something like:
char *line;
Then I must allocate some memory and assign it to line, is that right? If I am right, the question is the following:
In a line like
while (fscanf(fp,"%[^\n]", line) == 1) { ... }
without assigning any memory to line I am still getting the correct lines and the correct strlen counts on such lines.
So, does fscanf assign that memory for me and it also places the '\0'?
I saw no mention about these 2 things on the spec for fscanf.
The POSIX scanf() family of functions will allocate memory if you use the m (a on some older pre-POSIX versions) format modifier. Note: when fscanf allocates, it expects a char ** pointer. (see man scanf) E.g.:
while(fscanf(fp,"%m[^\n]", &line) == 1) { ... }
I would also suggest consuming the newline with "%m[^\n]%*c". I agree with the other answers that suggest using line-oriented input instead of fscanf. (e.g. getline -- see: Basile's answer)
See the C FAQ:
Q: I just tried the code
char *p;
strcpy(p, "abc");
and it worked. How? Why didn't it crash?
A: You got lucky, I guess. The memory randomly pointed to by the uninitialized pointer p happened to be writable by you, and apparently was not already in use for anything vital. See also question 11.35.
And, here is a longer explanation, and another longer explanation.
To read entire lines with a recent C library on POSIX systems, you should use getline(3). It allocates (and reallocates) the buffer holding the line as needed. See the example on the man page.
If you have a non-POSIX system without getline you might use fgets(3) but then you have to take the pain to allocate the line itself, test that you did not read a full newline terminated line, and repeat. Then you need to pre-allocate some line buffer (using e.g. malloc) before calling fgets (and you might realloc it if a line does not fit and call fgets again). Something like:
//// UNTESTED CODE
size_t linsiz=64;
char* linbuf= malloc(linsiz);
if (!linbuf) { perror("malloc"); exit(EXIT_FAILURE); };
memset(linbuf, 0, sizeof(linbuf));
bool gotentireline= false;
char* linptr= linbuf;
do {
if (!fgets(linptr, linbuf+linsiz-linptr-1, stdin))
break;
if (strchr(linptr, '\n'))
gotentireline= true;
else {
size_t newlinsiz= 3*linsiz/2+16;
char* newlinbuf= malloc(newlinsiz);
int oldlen= strlen(linbuf);
if (!newlinbuf) { perror("malloc"); exit(EXIT_FAILURE); };
memset (newlinbuf, 0, newlinsiz); // might be not needed
strncpy(newlinbuf, linbuf, linsiz);
free (linbuf);
linbuf= newlinbuf;
linsiz= newlinsiz;
linptr= newlinbuf+oldlen;
);
} while(!gotentireline);
/// here, use the linbuf, and free it later
A general rule would be to always initialize pointers (e.g. declare char *line=NULL; in your case), and always test for failure of malloc, calloc, realloc). Also, compile with all warnings and debug info (gcc -Wall -Wextra -g). It could have give a useful warning to you.
BTW, I love to clear every dynamically allocated memory, even when it is not very useful (because the behavior is then more deterministic, making programs easier to debug).
Some systems also have valgrind to help detecting memory leaks, buffer overflows, etc..
line is uninitialized and doen't point to any valid memory location so what you see is undefined behavior.
You need to allocate memory for your pointer before writing something to it.
PS: If you are trying to read the whole line then fgets() is a better option.Note that fgets() comes with a newline character .
Nope. You're just getting lucky undefined behavior. It's completely possible that an hour from now, the program will segfault instead of run as expected or that a different compiler or even the same compiler on a different machine will produce a program that behaves differently. You can't expect things that aren't specified to happen, and if you do, you can't expect it to be any form of reliable.
How can I write gets(???);
Thank you.
void getStr(**temp){
gets(???);
}
void main(){
char *ch;
printf("Enter a string: \n");
getStr(&ch);
printf("main: %s\n", ch);
}
------ Output ------
Enter a string:
abc
main: abc
Never use the gets function. It is inherently unsafe, since there's no way to guard against overruns (the user entering more data than you're prepared to accept). In fact, it was removed from the language by the 2011 ISO C standard.
You should probably use fgets() instead. It's a bit more complicated to use (for one thing, it leaves the '\n' line terminator in the string), but it lets you specify the maximum number of characters to be read.
Your getStr function probably doesn't need to take a char** argument; a char* would do, since it's not going to be modifying the pointer, just reading data into an array to which the pointer points.
You'll need to allocate a char array to read the data into. You can either declare an array object:
char line[200]; // for example
or use malloc to allocate the space.
One more thing: void main() is incorrect. (Compilers are allowed to accept it, but there is no good reason to use it.) The correct definition is int main(void). If you have a book that's telling you to use void main(), it was written by someone who doesn't know the C language very well, and it's likely to have more serious errors.
Take a look at the comp.lang.c FAQ.
I defined an array for strings. It works fine if I define it in such a way the first element is not an empty string. When its an empty string, the next scanf() for the other string stops reading the input string and program stops execution.
Now I don't understand how can defining the array of strings affect reading of input by scanf().
char *str_arr[] = {"","abc","","","b","c","","",""}; // if first element is "abc" instead of "" then works fine
int size = sizeof(str_arr)/sizeof(str_arr[0]);
int i;
printf("give string to be found %d\n",size);
char *str;
scanf("%s",str);
printf("OK\n");
Actually, you are getting it wrong my brother. The initialization of str_arr doesn't affect the working of scanf() , it may however seem to you like that but it ain't actually. As described in other answers too this is called undefined behavior. An undefined behavior in C itself is very vaguely defined .
The C FAQ defines “undefined behavior” like this:
Anything at all can happen; the Standard imposes no requirements. The
program may fail to compile, or it may execute incorrectly (either
crashing or silently generating incorrect results), or it may
fortuitously do exactly what the programmer intended.
It basically means anything can happen. When you do it like this :
char *str;
scanf("%s",str);
Its an UB. Sometimes you get results which you are not supposed to and you think its working.That's where debuggers come in handy.Use them almost every time, especially in the beginning. Other recommendation w.r.t your program:
Instead of scanf() use fgets() to read strings. If you want to use scanf then use it like scanf("%ws",name); where name is character array and w is the field width.
Compile using -Wall option to get all the warnings, if you would have used it, you might have got the warning that you are using str uninitialized.
Go on reading THIS ARTICLE, it has sufficient information to clear your doubts.
Declaring a pointer does not allocate a buffer for it in memory and does not initialize it, so you are trying to dereference an uninitialized pointer (str) which results in an undefined behavior.
Note that scanf will cause a potential buffer overflow if not used carefully when reading strings. I recommend you read this page for some ideas on how to avoid it.
You are passing to scanf a pointer that is not initialized to anything particular, so scanf will try to write the characters provided by the user in some random memory location; whether this results in a crash or something else depends mostly by luck (and by how the compiler decides to set up the stack, that we may also see as "luck"). Technically, that's called "undefined behavior" - i.e. as far as the C standard is concerned, anything can happen.
To fix your problem, you have to pass to scanf a buffer big enough for the string you plan to receive:
char str[101];
scanf("%100s",str); /* the "100" bit tells to scanf to avoid reading more than 100 chars, which would result in a buffer overflow */
printf("OK\n");
And remember that char * in C is not the equivalent of string in other languages - char * is just a pointer to char, that knows nothing about allocation.
I have following code and the out put:-
#include<stdio.h>
int main()
{
char pal_tmp[4];
printf("Size of String Variable %d\n",sizeof(pal_tmp));
strcpy(pal_tmp,"123456789");
printf("Printing Extended Ascii: %s\n",pal_tmp);
printf("Size of String Variable %d\n",sizeof(pal_tmp));
}
Out put:-
Size of String Variable 4
Printing Extended Ascii: 123456789
Size of String Variable 4
My questions is Why String variable (character array) accepts characters more than what its capacity is? Should not it just print 1234 instead of 123456789 ?
Am I doing something wrong?
Well yes. You are doing something wrong. You're putting more characters into the string than you are supposed to. According to the C specification, that is wrong and referred to as "undefined behaviour".
However, that very same C specification does not require the compiler (nor runtime) to actually flag that as an error. "Undefined behaviour" means that anything could happen, including getting an error, random data corruption or the program actually working.
In this particular case, your call to strcpy simply writes outside the reserved memory and will overwrite whatever happens to be stored after the array. There is probably nothing of importance there, which is why nothing bad seems to happen.
As an example of what would happen if you do have something relevant after the array, let's add a variable to see what happens to it:
#include <stdio.h>
int main( void )
{
char foo[4];
int bar = 0;
strcpy( foo, "a long string here" );
printf( "%d\n", bar );
return 0;
}
When run, I get the result 1701322855 on my machine (the results on yours will likely be different).
The call to strcpy clobbered the content of the bar variable, resulting in the random output that you saw.
Well yes, you are overwriting memory that doesn't belong to that buffer (pal_tmp). In some cases this might work, in others you might get a segfault and your program will crash. In the case you showed, it looks like you happened to not overwrite anything "useful". If you tried to write more, you'll be more likely to overwrite something useful and crash the program.
C arrays of char don't have a predefined size, as far as the string handling functions are concerned. The functions will happily write off the end of the array into other variables (bad), or malloc's bookkeeping data (worse), or the call stack's bookkeeping data (even worse). The C standard makes this undefined behaviour, and for good reason.
If a version of a particular function accepts a size argument to limit how much data it writes, use it. It protects you against this stuff.
C does not keep track of the size of strings (or arrays, or allocated memory, etc.), so that is your job. If you create a string, you must be careful to always make sure it never gets longer than the amount of memory you've allocated to it.
In C language Strings are defined as an array of characters or a pointer to a portion of memory containing ASCII characters. A string in C is a sequence of zero or more characters followed by a NULL '\0' character. It is important to preserve the NULL terminating character as it is how C defines and manages variable length strings. All the C standard library functions require this for successful operation.
For complete reference refer this
Function strcpy doesn't have knowledge about the length of the character array - this function is considered as unsecure.
You may use strncpy, where you tell the size of the buffer and if longer argument is provided, only the memory of the buffer is used and nothing else is changed.
This may be a very basic question for some. I was trying to understand how strcpy works actually behind the scenes. for example, in this code
#include <stdio.h>
#include <string.h>
int main ()
{
char s[6] = "Hello";
char a[20] = "world isnsadsdas";
strcpy(s,a);
printf("%s\n",s);
printf("%d\n", sizeof(s));
return 0;
}
As I am declaring s to be a static array with size less than that of source. I thought it wont print the whole word, but it did print world isnsadsdas .. So, I thought that this strcpy function might be allocating new size if destination is less than the source. But now, when I check sizeof(s), it is still 6, but it is printing out more than that. Hows that working actually?
You've just caused undefined behaviour, so anything can happen. In your case, you're getting lucky and it's not crashing, but you shouldn't rely on that happening. Here's a simplified strcpy implementation (but it's not too far off from many real ones):
char *strcpy(char *d, const char *s)
{
char *saved = d;
while (*s)
{
*d++ = *s++;
}
*d = 0;
return saved;
}
sizeof is just returning you the size of your array from compile time. If you use strlen, I think you'll see what you expect. But as I mentioned above, relying on undefined behaviour is a bad idea.
http://natashenka.ca/wp-content/uploads/2014/01/strcpy8x11.png
strcpy is considered dangerous for reasons like the one you are demonstrating. The two buffers you created are local variables stored in the stack frame of the function. Here is roughly what the stack frame looks like:
http://upload.wikimedia.org/wikipedia/commons/thumb/d/d3/Call_stack_layout.svg/342px-Call_stack_layout.svg.png
FYI things are put on top of the stack meaning it grows backwards through memory (This does not mean the variables in memory are read backwards, just that newer ones are put 'behind' older ones). So that means if you write far enough into the locals section of your function's stack frame, you will write forward over every other stack variable after the variable you are copying to and break into other sections, and eventually overwrite the return pointer. The result is that if you are clever, you have full control of where the function returns. You could make it do anything really, but it isn't YOU that is the concern.
As you seem to know by making your first buffer 6 chars long for a 5 character string, C strings end in a null byte \x00. The strcpy function copies bytes until the source byte is 0, but it does not check that the destination is that long, which is why it can copy over the boundary of the array. This is also why your print is reading the buffer past its size, it reads till \x00. Interestingly, the strcpy may have written into the data of s depending on the order the compiler gave it in the stack, so a fun exercise could be to also print a and see if you get something like 'snsadsdas', but I can't be sure what it would look like even if it is polluting s because there are sometimes bytes in between the stack entries for various reasons).
If this buffer holds say, a password to check in code with a hashing function, and you copy it to a buffer in the stack from wherever you get it (a network packet if a server, or a text box, etc) you very well may copy more data from the source than the destination buffer can hold and give return control of your program to whatever user was able to send a packet to you or try a password. They just have to type the right number of characters, and then the correct characters that represent an address to somewhere in ram to jump to.
You can use strcpy if you check the bounds and maybe trim the source string, but it is considered bad practice. There are more modern functions that take a max length like http://www.cplusplus.com/reference/cstring/strncpy/
Oh and lastly, this is all called a buffer overflow. Some compilers add a nice little blob of bytes randomly chosen by the OS before and after every stack entry. After every copy the OS checks these bytes against its copy and terminates the program if they differ. This solves a lot of security problems, but it is still possible to copy bytes far enough into the stack to overwrite the pointer to the function to handle what happens when those bytes have been changed thus letting you do the same thing. It just becomes a lot harder to do right.
In C there is no bounds checking of arrays, its a trade off in order to have better performance at the risk of shooting yourself in the foot.
strcpy() doesn't care whether the target buffer is big enough so copying too many bytes will cause undefined behavior.
that is one of the reasons that a new version of strcpy were introduced where you can specify the target buffer size strcpy_s()
Note that sizeof(s) is determined at run time. Use strlen() to find the number of characters s occupied. When you perform strcpy() source string will be replaced by destination string so your output wont be "Helloworld isnsadsdas"
#include <stdio.h>
#include <string.h>
main ()
{
char s[6] = "Hello";
char a[20] = "world isnsadsdas";
strcpy(s,a);
printf("%s\n",s);
printf("%d\n", strlen(s));
}
You are relying on undefined behaviour in as much as that the compiler has chose to place the two arrays where your code happens to work. This may not work in future.
As to the sizeof operator, this is figured out at compile time.
Once you use adequate array sizes you need to use strlen to fetch the length of the strings.
The best way to understand how strcpy works behind the scene is...reading its source code!
You can read the source for GLibC : http://fossies.org/dox/glibc-2.17/strcpy_8c_source.html . I hope it helps!
At the end of every string/character array there is a null terminator character '\0' which marks the end of the string/character array.
strcpy() preforms its task until it sees the '\0' character.
printf() also preforms its task until it sees the '\0' character.
sizeof() on the other hand is not interested in the content of the array, only its allocated size (how big it is supposed to be), thus not taking into consideration where the string/character array actually ends (how big it actually is).
As opposed to sizeof(), there is strlen() that is interested in how long the string actually is (not how long it was supposed to be) and thus counts the number of characters until it reaches the end ('\0' character) where it stops (it doesn't include the '\0' character).
Better Solution is
char *strcpy(char *p,char const *q)
{
char *saved=p;
while(*p++=*q++);
return saved;
}