C read string from std error - c

I want to read string from standart input and output it in on console. I use this way:
char* cmdline;
do{
scanf("%s\n", &cmdline);
printf("%s\n", cmdline);
}while(cmdline != "quit");
But this doesn't work. I have this error Segmentation fault (core dumped)

char* cmdline
is a pointer. You are not allocating space for storing the string.
You should do:
cmdline = malloc(size_of_string);
for allocating dynamic memory for storing the string.
Otherwise use an array of char instead of a pointer:
char cmdline[size_of_string];

cmdline is just a pointer -- you need to actually allocate space for it using malloc or a fixed-size array.

char cmdline[80];
do {
scanf("%79s\n", cmdline);
printf("%s\n", cmdline);
} while(strcmp(cmdline, "quit"));
I spotted three errors with your code:
Not allocating memory for the input buffer
Not passing a buffer to scanf
Not using strcmp to compare strings

You have defined char *cmdline but not allocated the cmdline pointer
do
cmdline = malloc (sizeof (char) * n);
first
Adjust the string length n as per your need.
EDIT1:
In your version when you use cmdline without allocation it, then actually cmdline contains a value which can be anything, and using that for memory access is an attempt to access some memory area which you do not know where and is not permitted in OSes with memory protection (all the OSes nowadays). So when you store something in cmdline it will go in an invalid location, which is not permitted and the OS will issue segmentation fault for illegal memory access.
After you have allocated the memory from the OS (heap) with the malloc call the cmdline will contain a value which will have a memory location address which was issued by the OS for your code and is reserved for you, in which you have permission to write. So referring the location with the variable makes a proper memory reference and you can you it as normal. Also note if you try to go beyond the allocated memory block, ie access beyond the n th location (if you have allocated n bytes), then you can also get a segfault, as the memory locations beyond that limit is not registered/allocated for you. Although you might not get a segfault in this case, but writing in such location can be unpredective.
The sole cause for an attempt to elaborate this is that this is a very common malpractice to define a char * and without allocating it use it in codes, because the old Turbo C++ 3.1 does not complain, which is used by a LOT of people out there. Then they call me and tell that the GCC compiler is broken as the code does not run in it and runs perfect in TC++ 3.1.
EDIT2:
Or simply use static array
char cmdline[MAX_SIZE];
where MAX_SIZE is set as per your need
EDIT3: OMG
You have done cmdline != "quit" this will never work. The solution is
while (strcmp (cmdline, "quit") != 0);
in your code. This will match the cmdline string character by character with the static string "quit"
Your solution will never work because when you do cmdline != "quit" then simply two addresses are being compared. First, the cmdline represents the address which you allocated with the malloc call, Second the address of the string "quit" which lies inside the data section of the executable, or simply in some area inside the memory where your program is loaded, which you have no idea. Comparing these two values will not compare the contents of these addresses, ie will not compare the strings inside it.
EDIT4:
Also scanf ("%s", &cmdline); is incorrect as cmdline itself represents the address of the location where you want to store the string. The correct code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void)
{
char *cmdline;
cmdline = malloc (sizeof (char) * 128); /* or whatever size */
do
{
scanf ("%s", cmdline);
printf ("%s\n", cmdline);
}
while (strcmp (cmdline, "quit") != 0);
return 0;
}

Related

making char pointer pointing to null causes segmentation fault

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.

What's the difference between a string and a user entered string in C

I'm using with a smaller piece of code to test functionality for a larger (beginner) program, but I don't understand the difference between two strings.
I found and used:
#include <stdio.h>
#include <string.h>
int main()
{
char *string, *found;
string = strdup ("1/2/3");
printf("Orig: '%s'\n",string);
while ((found = strsep(&string,"/")) != NULL )
printf ("%s\n",found);
return (0);
}
and this print the tokens one at a time.
Then when I try and move to a user entered string:
#include <stdio.h>
#include <string.h>
int main()
{
char string[13],
char *found, *cp = string;
fprintf(stderr, "\nEnter string: ");
scanf("%12s",string);
printf("Original string: '%s'\n",string);
while((found = strsep(&cp,"/,-")) != NULL )
printf("%s\n",found);
return(0);
}
I get a seg fault. I understand the basics of pointers, arrays and strings, but clearly I'm missing something, and would love for someone to tell me what it is!
Also - if I change printf("%s\n",found); to printf("%i\n",found); I get some junk integers returned, but always the correct amount, e.g. If I enter 1/2/3 I get three lines of integers, 1111/2222 I get two lines.
Thanks!
-Edit-
There was an adittional problem with strsep, detailed here. Thanks all.
In the first piece of code, string is assigned the return value of strdup, which allocates space for the string to duplicate and returns a pointer to that allocated space.
In the second piece of code, string uninitialized when it is passed to scanf, so scanf is reading the invalid value in that pointer and attempting to dereference it. This invokes undefined behavior which in this case manifests as a crash.
You need to set aside space for the user's string. A simple way to do this is to create an array of a given size:
char string[80];
Then tell scanf how many characters it can read in:
scanf("%79s",string);
Differences between the two cases:
In the first case string points to valid memory that was allocated by strdup while in the second case you are trying to read into invalid memory.
The first case is well behaved while the second case is cause for undefined behavior.
The second case can be fixed by allocating memory for it using malloc or using a fixed size array.
char *string,*found;
string = malloc(100); // Make it large enough for your need.
fprintf(stderr, "\nEnter string: ");
scanf("%99s",string);
or
char string[100], *found;
fprintf(stderr, "\nEnter string: ");
scanf("%99s",string);
Make sure you deallocate dynamically allocated memory. Otherwise, your program leaks memory.
You should allocate memory for the user input string.
First option is statically
char string[256];
and second option is dynamically using malloc() function
char *string;
string = (char*) malloc(256 * sizeof(char));
if (string == NULL)
{
//error
}
Don't forget at the end to release the allocated memory
free(string);
In user enter string case you do not have memory allocated to the pointer string.In the first case, strdup is allocating memory for string pointer while in the second case you do not have any memory associated with string pointer leading to segfault. first, allocate memory using malloc and then use scanf.
You didn't allocate the space needed !
You have to have a memory space to write to.
You can have it statically "char string[256]", or dynamically with allocation.
In your first example, you use "strdup" that does a malloc, but scanf will not allocate memory for you.
If you want all the user input, you usually wrap the scanf in a while loop in order to retrieve the user input chunk by chunk. Then you have to reallocate each time your buffer is insuffisante to add the chunk.
If you just want to retrieve a string from stdin without doing any format-checking, I strongly recommand fgets.
char string[13]
char cp=string
Here cp is a variable of type char and as 1 byte of memory allocated
It won't be able to store a char array of 13 character which would be 13 bytes, and it's because of this you are getting segmentation fault
The reason is very simple. Your string variable is a char pointer and you need to allocate memory to it to store a string.Probably in your first case strdup ("1/2/3"); returns a string and your char pointer *string points to the string return by strdup function and that is the reason why you are not getting the segmentation error in the first case. Even in your first case also you might get a segmentation error if enter a very long string.
so allocate enough memory to the string pointer like below in your second example and that will fix your problem:-
char *string = malloc(50);// here malloc will allocate 50 bytes from heap

Char Pointers and malloc

I was a bit confused with the concept of char pointers so I made a simple code just printing my name provided by user (me). I also wanted to practice malloc so I referenced the pointer to a certain memory in RAM, but I really didn't know what to put after "sizeof(char) *" because that is the user input, which is not yet decided.
Also, after doing that, I freed the memory, but I got an error message on command line saying:
*** Error in `./char': double free or corruption (fasttop): 0x00000000017fe030 ***
Aborted
It seems like I freed the same memory twice or something, but I don't know what to delete or add. Please help!
#include <stdio.h>
#include <cs50.h>
int main (void)
{
char *strings = malloc(sizeof(char) * 10);
printf("What is your name?\n");
//wait for use to type his/her name
strings = get_string();
printf("Hello %s\n", strings);
free (strings);
return 0;
}
The line strings = get_string(); actually assigns the value returned by get_string() to strings. It doesn't write it into the memory you allocated.
So the value returne by malloc() has been overwritten (and lost in this case).
The free(strings) is releasing whatever get_string() returned. The question doesn't provide the code for that but presumably it isn't valid to free() it.
Because the run-time told you it was freed twice I'm guessing you have allocated memory in get_string() then freed it and returned an invalid pointer.
If you want to use the memory you allocated you need to change get_string() to accept a pointer:
void get_string(char *str){
//Do whatever writing you value into str[] as an array of char..
}
Good practice would have:
void get_string(char *str, size_t max){
//Do whatever writing you value into str[] as an array of char..
//Use max to avoid writing beyond the end of the space allocated...
}
Then call as get_string(strings,10);.
EDIT: After a bit of research the flaw has been identified. get_string() doesn't directly free() the string it returns but adds it to a list of allocations made by the library which are freed on exit (in a function called teardown() registered with atexit() or other compiler dependent features).
That is poor design because consumer code is provided no safe way of itself freeing the memory which in a typical use case will not be required for the whole application execution. get_double() is worse because it never returns the allocated data but never reuses it and amounts to a straight memory leak.
The code should either:
Conform to the documentation and require consumer code to free() the string (maybe rename it as say get_string_alloc() for clarity).
Offer a library routine to free the string (get_new_string() and release_string())
There is no very nice way to shift ownership of allocated memory in C but holding onto it for the remainder of execution is definitely not the answer.
Many libraries go round the houses to push allocation onto consumer code but that is onerous when the full size of the space required can't be known such as here.
I'd suggest putting _alloc() at the end of any function that returns objects that consumer code must later free().
So the answer for the question posed is remove the malloc() and the free() because the library handles both. However beware if your program makes many calls to that function and others that internally rely on it (like get_double()) you may run out of memory because the library is sitting on dead space.
The problem is your get_strings overrides your initial malloc. A pointer value is a value. By equating it with something else, you replaced your malloc value.
Memory is allocated at the statement:
strings = get_string();
You dont have to malloc it ( char *strings = malloc(sizeof(char) * 10);
)
Without malloc it will work fine
First You have created a dynamic memory which will be pointed by *strings. But then you are pointing to the local string (from get_string() function) using *strings pointer. when you call free, program is trying delete local (stack) reference and throwing error.
To solve that error, the program should be
#include <stdio.h>
#include <cs50.h>
int main (void)
{
char *strings = malloc(sizeof(char) * 10);
printf("What is your name?\n");
//wait for use to type his/her name
strcpy(strings, get_string()); // Use strcpy instead of assigning
printf("Hello %s\n", strings);
free (strings);
return 0;
}
You don't include the code for get_string(), but you're overwriting strings with its return value which is wrong. The address you pass to free() must come from malloc(), and it seems you're violating that (in addition to losing the original returned address for your 10 bytes).
Assuming get_string() returns static storage (i.e. you don't need to free it) you can do this without involving malloc().
If you really want to, something like this might work:
printf("What is your name?\n");
const char *name = get_string();
const size_t nlen = strlen(name);
char * const name_copy = malloc(nlen + 1);
if(name_copy != NULL)
{
memcpy(name_copy, name, nlen + 1);
printf("Hello %s (from my own memory!)\n", name_copy);
free(name_copy);
}
This is rather convoluted but you get the idea.
char *strings;
No need for new malloc as string returned from get_string() function is already on the heap, you just need to pick up pointer to first character. (get_string() function reference)
strings = get_string();
printf("Hello %s\n", strings);
After printing string you should free memory allocated for it, as it is stated in get_string() function reference
Stores string on heap (via malloc); memory must be freed by caller to
avoid leak.
I think everything else is fine, try this code:
#include <stdio.h>
#include <cs50.h>
int main (void)
{
char *strings;
printf("What is your name?\n");
//wait for use to type his/her name
strings = get_string();
printf("Hello %s\n", strings);
free (strings);
return 0;
}

Assigning character to char[x] results in segmentation fault

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()).

passing integer arguments when using execve

I am a beginner at programming using system calls in C. I am trying to use the execve call in one of my programs. I have to pass an integer as an argument to the program that is being invoked through execve.
However, reading on the internet and seeing sample code, I can see that we can pass only strings as arguments. So, I tried converting the integer to a string using 'sprintf' and then using 'strcpy' to copy that string into one of the elements of the array of strings that has to be passed through execve.
But using strcpy leads to a segmentation fault. I checked this out by debugging and if I don't use strcpy but simply write something like -
myargv[1]="123";
then the entire program works fine.
But since I have to pass a variable integer as a parameter and not a constant, I cannot use the above method.
This problem has been bugging me for some time. Kindly help me out as to what I should do.
It's almost certainly because you haven't allocated space for your string.
The reason myargv[1]="123"; works is because you set the pointer to point to a string that already exists (the compiler generally puts that "123" into pre-initialised memory and it just gets loaded). By using something like:
char *myargv[10];
strcpy (myargv[1], "anything");
you'll generally run into problems because there's no allocated backing storage for the myargv[1] pointer.
What you can do is to simply set myargv[1] directly to the buffer where you sprintf-ed the string:
char sprintf_buffer[whatever];
sprintf (sprintf_buffer, "%d", myInteger);
myargv[1] = sprintf_buffer;
Or, if you're re-using that buffer (so that the value gets overwritten for multiple integer arguments), use strdup.
char sprintf_buffer[whatever];
sprintf (sprintf_buffer, "%d", myInteger1);
myargv[1] = strdup (sprintf_buffer);
sprintf (sprintf_buffer, "%d", myInteger2);
myargv[2] = strdup (sprintf_buffer);
And if, for some reason, your platform doesn't have a strdup, here's one for you:
char *strdup (const char *s) {
char *d = (char *)(malloc (strlen (s) + 1));
if (d != NULL)
strcpy (d,s);
return d;
}
Keep in mind you should always check the return value from strdup to make sure the memory allocation worked. I've left it out here since it's not relevant to the question at hand.
You can avoid memory allocation with multiple buffers (provided you know the absolute number of buffers you'll need in advance):
char sprintf_buffer1[whatever];
char sprintf_buffer2[whatever];
sprintf (sprintf_buffer1, "%d", myInteger1);
myargv[1] = sprintf_buffer1;
sprintf (sprintf_buffer2, "%d", myInteger2);
myargv[2] = sprintf_buffer2;
I'm unclear as to why you are using strcpy at all. Just snprintf the number into a string and make that one of the arguments.
e.g.
char numberArgBuffer[20]; // more than big enough for a 32 bit integer
snprintf(numberArgBuffer, 20, "%d", numberArg);
char* argv[3];
char* envp[1];
argv[0] = exeName; // could be same as path
argv[1] = numberArgBuffer;
argv[2] = NULL;
envp[0] = NULL;
int ret = execve(path, argv, envp);
// if you get here execve failed, so handle the error
Your strcpy is probably seg faulting because you haven't allocated a buffer for the destination, but as the above example shows, it's an unnecessary step anyway.

Resources