making char pointer pointing to null causes segmentation fault - c

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.

Related

The printf function in C is not working as intended [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Can someone help me with this issue? For some reason, no matter what I try, doing printf isn't printing in my code. I've been trying to use the flush method, but that seems to just cause other issues. Is there anything else I can do?
int main(void) {
char **line;
size_t bufsize=MAXBUF;
printf("Type your name: ");
getline(&line,&bufsize,stdin);
}
You are trying to pass in an empty pointer, this pointer isn't pointing to any meaningful address at the start of the program. So the problem with this is that even if you were successful, it would overwrite some random address in memory with the input, and this is almost certainly what you don't want as it will cause a segmentation fault or a crash.
However that's not the reason why it's not compiling. It's not compiling because you are trying to pass in char *** to a function that expects char **.
So what I would do is:
#include <stdio.h>
int main(void) {
char *line=NULL;
size_t bufsize=0;
printf("Type your name: ");
if(getline(&line,&bufsize,stdin)==-1){
puts("Error: User cancelled input.");
}
else{
printf("Entered: %s",line);
}
free(line);
return 0;
}
So what this code does is that it creates a pointer to an array of characters but it sets the pointer to point to NULL so that the program can see it's not pointing anywhere, and then its address (&line) is given to the getline function, this turns the char * type into a char ** which is required by the getline function. Whenever you put a & in front of something in C, it adds an extra * to the type.
You probably know this already, but if a function states that it returns something, you should always return something, even if it's nonsense otherwise depending on the type that should be returned, that can sometimes cause a crash.
There was nothing wrong with your use of printf, that was fine. printf doesn't necessarily fflush to stdout, often the \n character will trigger a flush, but it's implementation specific, so if your program crashes before an fflush is written to stdout, then you may never see the last printf. You can try an fflush(stdout); before the getline function, but after the getline function may not work because it may crash before then.
In your case what's happening is that before the printf writes to the screen the getline takes in the address of the pointer (or pointer to a pointer), dereferences it to a pointer, isn't able to, so before you have a chance to enter in any keystrokes it crashes, losing the stdout pipe, so you end up never seeing your prompt.
When i run the altered code, above, i get:
XXXX#dell:~$ gcc Deleteme.c
XXXX#dell:~$ ./a.out
Type your name: test1
Entered: test1
XXXX#dell:~$
And it runs correctly under Linux. The key lesson in all this is that, terminals are slow to update on the screen, so some time in the past, the decision was made to separate out the functionality of printf.
There are two components to printf:
The part that writes the text to stdout.
The part that updates the terminal with stdout (the flush).
This question is interesting because 1) succeeded, but the system crashed before 2) was completed.
The documentation for getline says the first parameter must be a char **, but you pass it the address of line. Since line is a char **, &line is a char ***, which is the wrong type.
getline() allocates and re-allocates memory. The address of the length and the buffer need to reflect that.
int main(void) {
char *line = NULL;
size_t bufsize = 0;
printf("Type your name: ");
fflush(stdout); // Flush output before reading.
ssize_t len = getline(&line, &bufsize, stdin);
if (len < 0) Handle_error_with_code();
...
free(line); // When done, free memory
}
There is no need to allocate any memory before calling getline().
getline() expects line, bufsize to reflect allocated data via malloc() and friends. It is easy enough to start with NULL, 0 here.
First you are passing the address of line to the getline(), the documentation says that the first argument is the address of the first character position where the input string will be stored. It’s not the base address of the buffer, but of the first character in the buffer.
This pointer type (a pointer-pointer or the ** thing) causes massive confusion.
second your line pointer does not point to anything this should fix it:
char *line = (char *)malloc(bufsize * sizeof(char));
now line is pointing to valid memory address which we requested via malloc() function.

need help about string in c program [duplicate]

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.

C read string from std error

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;
}

C Pointers question

I have a small conceptual question about pointers. This may be embarrassing but I need to know the answer.
I was trying to read a line from a file using getline function. getline takes char ** as its first argument and that is where the line pointer is stored. Please see the pasted code below and tell me the difference between them. Notice the declaration and use of readLine pointer.
The second code gave me segmentation fault when it reached printf(). I checked the value at *readLine with gdb(before printf()) and it was correct, but when it goes to printf(), boom SIGSEGV
this code works:
FILE *fp;
char *readLine;
readLine=NULL;
int s=0;
while(getline(&readLine,(size_t *)&s,fp) != -1){
printf("%s\n",readLine);
}
this code does not work:
FILE *fp;
char **readLine;
*readLine=NULL;
int s=0;
while(getline(readLine,(size_t *)&s,fp) != -1){
printf("%s\n",*readLine);
}
cheers...
rv
(size_t *)&s
This will crash a 64-bit machine with 32-bit ints. The solution to this kind of problem is to declare the type which is required (size_t s;), not to cast anything. In x86-64, this assigns 8 bytes to a 4-byte location on the stack, which results in stack corruption. Because the overwrite happens in the called function, it could overwrite the return address, for example.
char **readLine;
*readLine=NULL;
This is also an instant crash. You are assigning a value to the target of an uninitialized pointer, changing the bytes at some unknown point in memory.
In the first case, the variable readLine -- the value of which is stored on the stack, in it's own special reserved area -- is a pointer-to-char. When you pass its address to getline(), you tell getline() to store the real pointer into the memory which is reserved for it. Everything works.
In the second case, readLine is a pointer-to-pointer-to-char, and again, there is space reserved for it on the stack. When you call getline(), though, you're telling getline() that the readLine variable holds the address in which the pointer-to-char should be stored. But readLine points to some random memory somewhere, not to a location which getline() should be allowed to store data. In fact, you've already started corrupting memory when you write
*readLine = NULL;
because as I said, readLine is pointing to memory you don't own. getline() just makes it worse.
Please find example bellow, it is compiled end executed on Ubuntu 18.04.
If you use linux, please type "man getline", man pages are your friend.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
char *readLine;
FILE *fp;
size_t n = 0;
readLine=NULL;
fp = fopen("example.c", "r");
while(getline(&readLine,&n,fp) != EOF){
printf("%s\n",readLine);
}
free(readLine);
}

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