I don't know why this code shows Segmentation Fault.Below is the code
int main()
{
char *str;
printf("\nEnter a string - \n");
scanf("%s",str);
printf("%s\n",str);
}
What can be the reasons for the segmentation fault?
Also I would like to know why using gets()function is dangerous in Linux?
Firstly, you may need to know that you could have used char str[40] = {0}; (compile time memory allocation).
Since you have asked a question which queries about dynamic memory allocation, you should allocate memory to a pointer before trying to store anything. Beacuse the pointer may be pointing to any random locations (wild pointer) and hence you may try to access memory which is not meant for accessing, this results in a segfault.
int main()
{
char *str;
str = malloc(sizeof(char) * 40); // allocate memory where str will be pointing,here i allocate 40 bytes
printf("\nEnter a string - \n");
scanf("%39s",str);
printf("%s\n",str);
free(str); //important to release the memory!
}
To answer your second question, gets() is dangerous on any platform because it may cause buffer overflow.
Consider a scenario where you try to fill a buffer beyond it’s capacity :
char *buff = malloc(sizeof(char)*10);
strcpy(buff, "This String Will Definitely Overflow the Buffer Because It Is Tooo Large");
As you can see that the strcpy() function will write the complete string in the ‘buff’ but as the size of ‘buff’ is less than the size of string so the data will get written past the right boundary of array ‘buff’. Now, depending on the compiler you are using, chances are high that this will get unnoticed during compilation and would not crash during execution. The simple reason being that memory belongs to program so any buffer overflow in this memory could get unnoticed.
So in these kind of scenarios, buffer over flow quietly corrupts the neighbouring memory and if the corrupted memory is being used by the program then it can cause unexpected results.
Workaround for safety :
char *buf=NULL;
size_t siz= 30;
ssize_t len = getline(&buf,&siz,stdin);
How is this a workaround?? Well, you should read about the getline() more.
Related
A little more than 20 years ago I had some grasp of writing something small in C , but even at that time, I probably didn't really do things right all the time. Now I'm trying to learn C again, so I'm really a newbie.
Based on this article:
Using realloc to shrink the allocated memory
, I made this test, which works, but troubles me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int test (char *param) {
char *s = malloc(strlen(param));
strcpy(s, param);
printf("original string : [%4d] %s \n", strlen(s), s);
// reduce size
char *tmp = realloc(s, 5);
if (tmp == NULL) {
printf("Failed\n");
free(s);
exit(1);
} else {
tmp[4] = 0;
}
s = tmp;
printf("the reduced string : [%4d] %s\n", strlen(s), s );
free(s);
}
void main(void){
test("This is a string with a certain length!");
}
If I leave out "tmp[4] = 0", then I still get back the whole string. Does this mean the rest of the string is still in memory, but not allocated anymore?
how does c free memory anyway? Does it keep track of memory by itself or is it something that is handled by the OS?
I free the s string "free(s)", do I also need to free the tmp str (it does point to the same memory block, yet the (same) address it holds is probably stored on another memory location?
These are most likely just basics, but none of what I have read so far has given me a clear answer (including mentioned article).
If I leave out "tmp[4] = 0", then I still get back the whole string.
You've invoked undefined behavior. All the string operations require the argument to be a null-terminated array of characters. If you reduce the size of the allocation so it doesn't include the null terminator, you're accessing outside the allocation when it tries to find it.
Does this mean the rest of the string is still in memory, but not allocated anymore?
In practice, many implementations don't actually re-allocate anything when you shrink the size. They simply update the bookkeeping information to say that the allocated length is shorter, and return the original pointer. So the remainder of the string stays the same unless you do another allocation that happens to use that memory.
This can even happen when you grow the size. Some designs always allocate memory in specific granularities (e.g. powers of 2), so if you grow the allocation but it doesn't exceed the granularity, it doesn't need to copy the data.
how does c free memory anyway? Does it keep track of memory by itself or is it something that is handled by the OS?
Heap management is part of the C runtime library. It can use a variety of strategies.
I free the s string "free(s)", do I also need to free the tmp str (it does point to the same memory block, yet the (same) address it holds is probably stored on another memory location?
After s = tmp;, both s and tmp point to the same allocated memory block. You only need to free one of them.
BTW, the initial allocation should be:
char *s = malloc(strlen(param)+1);
You need to add 1 for the null terminator, since strlen() doesn't count this.
#include <stdio.h>
int main ()
{
char str[40];
printf("Enter a string : \n");
gets(str);
printf("You entered: %s\n", str);
return 0;
};
in above code, if replace str to a pointer, char *str. Then NULL is out. Suppose gets defined by char *gets(char *str), it should use a pointer instead of array. All examples I saw are array not pointers. Thanks.
function gets() is depracted your libc/compiler might ignore it. try use fgets() instead.
#include <stdio.h>
int main ()
{
char str[40];
printf("Enter a string : \n");
if (fgets(str, sizeof(str), stdin) != NULL)
{
printf("You entered: %s\n", str);
}
return 0;
};
also if you want to don't use stack you need to give pointer that points allocated space. in code str also can be char *str = malloc(40); then change sizeof(str) to 40 since str is no longer stack.
Really interesting question, I have been asked this question a lot!
you should have a bit background of pointers and memory to understand what is happening.
first let's have a brief review about pointers and memory:
our computer have some memory and we can use it in programming, anything that we store (in runtime) for example an int, array of doubles, some complex struct and strings(that they are array of characters) should be somewhere in memory.
pointers contain address of somewhere in memory, some of them know about that memory (how to read/write value) some of them don't.
there is a special value for pointers (NULL) that means nowhere, if pointer is pointing to NULL, that pointer is pointing not nowhere (obviously nowhere is not a valid address in memory)
array is specific type of pointer, a const pointer that is pointing to already allocated memory in stack.
and about gets function: let's think we want to re-implement such function (namely my_gets) , how we suppose to do that? how to return a string (array of characters)?
these are options (as far as i know):
creating a local array in our function and fill it. then we should return it? no we cant! because that array is in stack of our function and after ending the function, our function data including this array will be popped automatically (handled by compiler).
although nobody forbid us from returning that array, but that would cause dangling pointer problem.
allocating some space rather than stack (heap) and fill that. this is perfectly fine and there is methods and do this! for example readline (not in ansi c, you can find it here) will do this. the drawback of this method is that you should take care of that memory and free it later, it also may be not to optimum way and you may should copy that string to your already allocated memory
the last way (and way that gets use) is getting a pointer that is already pointing to a valid memory and fill that memory. you already know that gets want a pointer as input, I add that, that pointer should point to a valid and accessible memory that gets can fill it. if pointer is pointing to NULL (or maybe uninitialized and pointing to some where random) gets will fail writing and cause undefined behavior (segmentation fault for example)
some final points:
array solution work because array name is pointer that pointing to valid memory (array in stack) so it's OK and easy to understand.
If we don't want to use array, we can point our pointer to a valid memory, we need to use malloc/calloc to allocate a block of memory. see this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int size = 40 * sizeof(char);
char* p = malloc(size);
printf("Enter a string : \n");
if (fgets(p, size, stdin) != NULL) {
printf("You entered: %s\n", p);
}
free(p);
return 0;
}
gets is not secure because it doesn't care how much memory we have, it writes until and string ends and it may cause buffer overflow, better option (as people said) is fgets because it care memory size and will not exceed that. but my answer doesn't care it's fgets or gets.
in linux, I am trying the below code which is causing segmentation fault error:
int main(int arg_count,char *args[]){
char *buffer;
if(arg_count>1)
buffer = args[1];
else
*buffer = 0;
}
I know that pointers point to read only part of the memory, so I changed my first try buffer[0]=0; to above. But I don't understand why this one is not working either?!
The final line of your function, *buffer = 0, is attempting to set the value referred to by the pointer buffer.
As buffer has never been initialised and therefore contains an indeterminate value, dereferencing buffer is very likely to cause a segfault.
For most projects you should never write argument parsing code yourself. There are many robust and efficient libraries that will do a much better job than you (or I) could. As you are writing C on Linux GNU getopt is a good option.
if you go through your program line by line you'll see that if the user doesn't pass any arguments then buffer is just a random value. As another comment said you need to initialize it. In your case I don't think you literally want to put the value 0 in the memory address that buffer points to. Here is code that shows how to handle arguments
int main(int argc, char **argv){
char *buffer = NULL;
if(argc > 1){
buffer = argv[1];
}
else{
buffer = malloc(1024);
puts("please enter an argument");
fgets(buffer, 1024, stdin);
//do stuff with buffer
free(buffer)
}
return 0;
}
in the code above the program checks if any arguments were passed to the program, if no arguments were passed then the program allocated 1024 bytes and points buffer to that memory location and then asks the user for input. From this point you can do what ever you want with buffer.
buffer character pointer is not initialised. Since buffer is declared with auto storage class it will have a garbage value. You are trying to access a uninitialized pointer which is a memory access exception hence it gave a seg fault. Before accessing buffer allocate a memory using calloc or malloc.
I have already written a couple of C programs and consider this awkward to ask. But why do I receive a segmentation fault for the following code being supposed to replace "test" by "aaaa"?
#include <stdio.h>
int main(int argc, char* argv[])
{
char* s = "test\0";
printf("old: %s \n", s);
int x = 0;
while(s[x] != 0)
{
s[x++] = 'a'; // segmentation fault here
}
printf("new: %s \n", s); // expecting aaaa
return 0;
}
This assignment is writing to a string literal, which is stored in a read-only section of your executable when it is loaded in memory.
Also, note that the \0 in the literal is redundant.
One way to fix this (as suggested in comments) without copying the string: declare your variable as an array:
char s[] = "test";
This will cause the function to allocate at least 5 bytes of space for the string on the stack, which is normally writeable memory.
Also, you should generally declare a pointer to a string literal as const char*. This will cause the compiler to complain if you try to write to it, which is good, since the system loader will often mark the memory it points to as read-only.
Answering the OP's question in the comment posted to #antron.
What you need is to allocate a character array, then use strcpy() to initialize it with your text, then overwrite with a-s.
Allocation can be done statically (i.e., char s[10];) but make sure the space is enough to store the length of your init string (including the terminating \0).
Alternatively, you can dynamically allocate memory using malloc() and free it using free(). This enables you to allocate exactly enough space to hold your init string (figure it out in run-time using strlen()).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Segmentation Fault - C
#include<stdio.h>
#include<string.h>
int main()
{
char *p;
printf("enter some thing:");
gets(p);
printf("you have typed:%s\n",p);
}
Why doesn't this program work?
i can't use pointer as a string.
Output is:
enter some thing:raihan
Segmentation fault (core dumped)
I get this error every time when I use a char pointer.
How can I solve this problem?
I am using code-blocks on Linux mint13 KDE.
You have not allocated memory. You just declared a pointer, p, but didn't make it point at anything. That explains the segmentation fault. You will need to allocate memory for your buffer.
What's more, gets does not allow you to specify how big the buffer is. So you are at risk of running over the end of the buffer. So use fgets instead.
int main(void)
{
char buffer[1024];//allocates a buffer to receive the input
printf("enter some thing: ");
fgets(buffer, sizeof(buffer), stdin);
printf("you have typed: %s\n", buffer);
return 0;
}
I also corrected your declaration of main and made sure that it returns a value.
You haven't allocated any memory for p. Also, use fgets instead of gets which may overflow the input buffer.
char *p;
printf("enter some thing:");
gets(p);
Wrong. Gets() tries to fill in the array pointed to by the supplied pointer - and it segfaults, because that pointer hasn't been initialized, so it might (and does) point to some garbage/invalid memory location. Use
char p[256];
or something like this instead - you still have to worry about a buffer overflow in if the user enters a string longer than 255 characters. You can solve that one using
fgets(p, sizeof(p), stdin);
Your pointer is declared but you have not initialised it and so its value will be some arbitrary memory location that you may not have access to write to. Thus anytime you read or write to this you run the risk of segfault. Allocate some heap memory for the pointer using a call to malloc then you wont get segfaults when writing to it.
You have just defined a pointer - no memory for the characters have been allocated!
Use either an array or malloc.
A pointer is just a memory address. It says "you have some data here". But it doesn't actually reserve that data.
In your case the problem was two-fold. The pointer didn't point to valid memory and you never even set it to anything (so it pointed to somewhere random).
You can fix this in different ways. The easiest is to just use an array (it's sort of implicitly a pointer):
char something[100];
printf("enter some thing:");
gets(something);
That gives you 100 chars on the stack. You can also point to it if you want, but in this case it's a bit redundant:
char *p = something;
The other way is dynamic allocation, where you ask the operating system at runtime to give you some number of bytes. This way you have to give it back when you're finished using it.
char *something = (char*)malloc( 100 * sizeof(char) ); // Ask for 100 chars
printf("enter some thing:");
gets(something);
free(something); // Do this when you don't need that memory anymore.
PS: Remember when you have strings, you always need one extra byte than the number of characters you intend to store. That byte is for the string terminator, and the value of it is 0.