Segmentation fault with argv[1] - c

So I have a program which takes a command line argument from the user and uses atoi to convert it to a number. It all works fine until the number that is passed from the command line is more than 2048.
Here is the simple program:
int no_of_elements_per_thread = 0;
int main(int argc, char* argv[])
{
int status;
void* thread_arg;
void* res;
int i = 0;
//initialize
no_of_elements_per_thread = atoi(argv[1]);
return 0;
}
When I run the program for different values the output is as follows:
[adeb1][open-19][~/pre2] ./pre2 2098
Segmentation fault
with smaller values:
[adeb1][open-19][~/pre2] ./pre2 210
[adeb1][open-19][~/pre2]
Interestingly if I try to do a printf with %s without doing atoi I still get segmentation fault as well with argv[1]. So it seems argv[1] is giving problem with values higher than 2048.
I am using gcc in linux if that matters.

Where is your declaration of atoi? Without #include <stdlib.h>, I would assume there is none.
You may also want to ensure argc > 1 before using argv[1].

Related

Segmentation Fault (core dumped) printing string from argv

I'm just trying to check the commandline arguments and see if it works in the command line. It works fine if I execute './a.out hello' but when I do './a.out' I get the error.
#include <stdio.h>
int main(int argc, char * argv[]){
printf("Test");
printf("\n%s",argv[0]);
printf("\n%s",argv[1]);
return 0;
}
The reason why I'm doing this is because I'm going to take that string and compare it later on. I don't understand why something this simple is causing an error.
You're not checking the length of argv before dereferencing the second argument. If argv only has one element argv[1] is a null reference, which causes your fault.
With C everything needs to be done carefully. To answer your question, yes, an if statement is the right approach if you want to handle the command line yourself. The argc parameter to main() is provided for exactly this purpose.
#include <stdio.h>
int main(int argc, char * argv[]){
printf("Test");
if (argc > 0) {
printf("\n%s", argv[0]);
if (argc > 1) {
printf("\n%s", argv[1]);
}
}
return 0;
}
Theoretically argv[0] is always populated with the application name so the first if is redundant but with C caution is your friend.
However, don't take this path. For everything except trivial applications you should use a parameter parsing library such as http://www.gnu.org/software/libc/manual/html_node/Getopt.html, check Christian's excellent answer here https://stackoverflow.com/a/24479532/2381157 for more options.

Segmentation fault in C when trying to run

So I am new to the C language, I am attempting to write a program that outputs text in either upper or lower case, by inputting either -u or -l. The program compiles, however when I run it, it gives me a segmentation fault. Why?
#include <stdio.h>
#include <string.h>
int main(int argc, char*argv[]){
int i;
int j;
int k;
if(strcmp(argv[1],"-u")){
for(i=0;i<argc;i++){
printf("%s ",toupper(argv[i]));
}
}
else if(strcmp(argv[1],"-l")){
for(j=0;j<argc;j++){
printf("%s ",tolower(argv[j]));
}
}
else{
for(k=0;k<argc;k++){
printf("%s ",argv[k]);
}
}
}
toupper & tolower take an int representing a character and returning an int representing that character as upper or lower case (respectively).
You're doing 2 things wrong with that:
You're passing in the address of a char array (not a single character)
You're using the returned value (int) as if it was a char array (passing it as an input to printf with "%s")
So you're getting some garbage out of the function, and then sending printf into unmapped memory address -> that's your seg-fault.
To make life easy, also consider using the getopt command.
Here you will find an example: http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html#Example-of-Getopt

Get a segmentation fault through argv on purpose

I want to write a small program, which, by user input through argv, gets a segmentation error. I am quite new to C but I think the following code does the job:
int main(int argc, char *argv[])
{
int bufferSize;
char * buffer[100];
unsigned int i;
if (argc > 1) {
bufferSize = atoi(argv[1]);
for (i = 0; i < bufferSize; ++i)
*( buffer + i ) = i;
}
return 0;
}
My idea is that the program intialize (?) a pointer to a buffer of a specific size. If the user then input a number larger then the buffer size it will write to uninitialized memory, hence get a seg. fault. Is this reasoning correct whatsoever?
Ps. When compiling,I get a assignment makes pointer from integer without a castwarning, can someone maybe tell me why that happens? Thanks
The most traditional way to purposely get a segmentation fault, that I've seen, is to write to NULL, e.g. something like:
*((char *) NULL) = 0;
You can use a command line argument as a simple boolean value to see if this should be done or not.
Note that writing to NULL is not actually guaranteed to cause a crash, it's simply undefined behavior so basically anything could happen (including causing nasal demons).
The warning is because you have an array of pointers, and try to assign an integer to a pointer in the array.
char * buffer[100]; is an array of pointer which points to some garbage locations by default.
Here *( buffer + i ) = i; you are trying to deference that area which doesn't belongs to you.
My guess is that, you wanted to create a buffer. so
char buffer[100]; is enough.
I would not worry about writing to cause a segmentation fault. Reading is sufficient enough. You stand a better chance of causing a segfault if the buffer is on the heap. This application fairly reliably segfaults for negative inputs less than -10 for me.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
int main(int argc, char* argv[])
{
static const int array[10] = {0,1,2,3,4,5,6,7,8,9};
int * const heapArray = malloc(sizeof(array));
memcpy(heapArray,array,sizeof(array));
const int index = atoi(argv[1]);
printf("%i\n",heapArray[index]);
free(heapArray);
return 0;
}
The problem is, the result of malloc() can be much much larger than the requested size for most systems. So even for large values it does not segfault, it just returns whatever happens to be there in memory.
ericu#eric-phenom-linux:~$ ./segfault -5
Segmentation fault (core dumped)
ericu#eric-phenom-linux:~$ ./segfault 11
0
ericu#eric-phenom-linux:~$ ./segfault 100
0
ericu#eric-phenom-linux:~$ ./segfault 100
0
ericu#eric-phenom-linux:~$ ./segfault 1000
0
ericu#eric-phenom-linux:~$ ./segfault 10000
0
ericu#eric-phenom-linux:~$ ./segfault 100000
Segmentation fault (core dumped)

C application error on run

I've built a C application, and when I build it, it shows no errors, but when I run it, it gives me the error "Segmentation Fault: 11".
If it helps, here is the code I am using:
#include <stdio.h>
int main(char *argv[]) {
printf("The project path is: ./Projects/%c", argv[1]);
return 0;
}
The correct main prototyped syntax is
int main(int argc, char *argv[]) { ... }
Also %c conversion specification in printf prints a character, to print a string use %s.
You have a number of problems:
The signature for main is an argument count followed by an array of C strings.
You should always check the count before using the array.
The array is of strings so you need %s to print them.
This should work:
#include <stdio.h>
int main(int argc, char *argv[]) {
if (argc < 2)
fprintf (stderr, "Wrong number of arguments\n");
else
printf ("The project path is: ./Projects/%s\n", argv[1]);
return 0;
}
Change the signature to int main(int, char*[]);
What arguments are you passing to the process? If you're not passing any argv[1] is out of range
In addition to the other suggestions, you may need to revisit your printf format. %c is used to print a single character, and argv[1] is char *. Either use argv[1][0] or some such, or use the string format specifier, %s.
First, change your main to:
int main(int argc, char *argv[])
Second, you have a mismatch between what you're passing to printf, and what you've told it you're going to pass. argv[1] is a pointer to characters, not a character. You need/want to use the %s conversion to print it out:
printf("The project path is: ./Projects/%s", argv[1]);
In this specific case, it's not really mandatory to check for enough arguments, because even if you don't pass any command line arguments, argv will contain at least argv[0] followed by a null pointer. As such, using argv[1] is safe, but if you haven't passed a command line argument, may print as something like (null).
Nonetheless, you generally want to check the value of argc before using argv. In this case, you can get away with it, but only more or less by accident. Trying to use argv[2] the same way could give undefined behavior.

Input from the execution line in the terminal in c

The problem that i have is that i have to write a hanois tower game in c and the input for the number of the rings must not be in the programm but the code must read the number of rings in the execution.
Example: ./hanoistower 3
And the code should get the 3 as the input. How can i do that?
Command line arguments are propagated as strings through the main() function of your C program.
In int main(int argc, char *argv[]) argc is the number of arguments, and argv is an array of strings containing the arguments. Note that the program name itself is always the first "argument".
As the arguments are passed as strings, you likely need to convert your 3 to an integer, which can be done with the atoi function. Here's a start:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int rings;
if(argc != 2) {
printf("Usage: %s number-of-rings\n",argv[0]);
return 1;
}
rings = atoi(argv[1]);
printf("Using number-of-rings = %d\n", rings);
...
return 0;
}
I strongly suggest reading a good C programming book (in 2020, Modern C).
It will be much faster than asking questions here. Don't forget to also read the documentation of your C compiler (perhaps GCC), your build automation tool (e.g. GNU make or ninja), and debugger (perhaps GDB). If you code on and for Linux, read also Advanced Linux Programming and syscalls(2), and the documentation of GNU glibc (or of musl-libc, if you use it).
Hovever, the program arguments is given as a null terminated array of strings to the main function, which is usually declared as
int main (int argc, char**argv) { /*...*/ }
if you run your program with ./hanoistower 3 and if your hanoistower.c is your source code (which you need to compile with debugging and warning enabled, i.e. gcc -Wall -g hanoistower.c -o hanoistower on Linux) then you have one extra argument, so
argc == 2
argv[0] is the "./hanoistower" string
argv[1] is the "2" string (use atoi to convert it to an int)
argv[2] is NULL
Please, please learn to use the debugger (gdb on Linux).
Just add, argc and argv to the list of main method parameters, as shown below:
int main ( int argc, char *argv[] )
Then use argv as the variable to specify number of rings inside your code.

Resources