Simple program leads to seg fault when opening a file - c

I've got a text file that contains a bunch of strings, nothing important in terms of my problem.
The code here compiles/runs, and If I type in the correct text file, the first if statement runs. However, if I don't the else statement doesn't execute, but instead I get a seg fault, would Mallocing the pointer be of any help here? Any help would be much appreciated.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main (int argc, char * argv[])
{
FILE * ptr;
if(strcmp(argv[1],"test.txt") == 0)
{
printf("Right text file was inputted");
}
//but if I wan't the alternative (if the user didn't enter the right thing
else
{
// this never executes, but instead the program just seg faults if the first if statement is not true
printf("You didn't enter the right textfile, or none at all");
exit(1);
}
}

You should be using argc (the count of the number of arguments given) to determine if a value is entered or not. As it stands, accessing argv[1] when argc is 0, will cause a segmentation fault as you're accessing passed the end of the array when strcmp dereferences the terminating NULL pointer.
Your first if statement should be:
if(argc > 1 && strcmp(argv[1],"test.txt") == 0) {
...

when you pass arguments to main(), they are passes in the form of strings to main(). argc is a count of the arguments passed to the main() and argv is argument vector which is always NULL ended. so if you dont provide any arguments you have to first check with argc count and then proceed. other thing is you cannot check if wrong file name is passed or file name is not passed at all in just one condition
it should be like,
int main (int argc, char * argv[])
{
FILE * ptr;
if(argc>1)
{
if(strcmp(argv[1],"test.txt") == 0)
{
printf("Right text file was inputted");
}
else
{
printf("You didn't enter the right textfile");
exit(1);
}
}
else
printf("you havn't entered any file name");
}

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.

Is it possible to add an argument to main by scanf?

I tried to add an argument to main by scanf. But it didn't work. The following is my program. My question is: what's wrong with this program? And is it possible to add an argument to main by scanf() instead of in the command line?
#include <stdio.h>
#include <errno.h>
int main(int argc, char* argv[]){
/*check if there is no argument, that is, argc!=2*/
if(argc != 2){
puts("Please enter an argument: ");
scanf("%s", &argv[1]);
printf("\nYou've entered argument: %s\n", argv[1]);
return 1;
}
printf("\nYou've entered argument: %s\n", argv[1]);
return 0;
}
Yes, code can effectively add arguments.
"The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination." C11dr ยง5.1.2.2.1 2
So this allows code to change argc and argv and change argv[0][0] (if argc > 0) - but wait, there's more...
Can code change the original elements of argv[], like argv[1], etc? That is an open question still hanging in SO here. So let us avoid that.
The way to change the contents of argv[] is to first create an alternate set argv_alt[] array and then assign argv_alt --> argv.
#include <stdio.h>
int main(int argc, char *argv[]) {
// Assume argc == 1
printf("%d '%s'\n", argc, argv[0]);
char a[3][10] = { "abc", "def", "fgh" };
char *argv_alt[] = { a[0], a[1], a[2], NULL };
argc = 3;
argv = argv_alt;
printf("%d '%s' '%s' '%s'\n", argc, argv[0], argv[1], argv[2]);
return 0;
}
Argv is allocated by the system when the user types in her arguments. If there wasn't arguments you cannot use the position 1 on that array. Although, as pointed out on the comments, you shouldn't do the way you are willing to, you could scanf arguments if you declare your own local variable.
The %s specifier in scanf expects that you pass in a pointer which points to space that has already been allocated and is big enough to hold whatever will be read.
Instead you pass in a pointer which points to an area where another pointer is stored. This causes undefined behaviour because the pointer you pass in has the wrong type.
It's not possible to extend the length of the argv array. In fact, writing to argv[n] probably causes undefined behaviour anyway.
Instead you should just read into a variable inside main.

how to create a chaine of symbolic links in c

when i try to execute this code i "segmentation fault"appears on the screen. Can someone please tell me what the error is? thanks in advance
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char * argv[]){
int fd , i;
int count= atoi(argv[2]);
char name[50];
char nname[50];
strcpy(nname, "./lfille");
strcpy(name, argv[1]);
struct stat statbuf;
/* if((fd=open(argv[1], O_RDWR)==-1)){
fprintf(stderr, "Datei existiert nicht\n");
}else*/ if((lstat(argv[1], &statbuf)==-1)){
fprintf(stderr, "Error bei lstat\n");
}else if(!(S_ISREG(statbuf.st_mode))){
printf("%s ist nicht REG\n ", argv[1]);
exit(1);
}else{
for(i=0; i<count; i++){
printf("%s", nname);
symlink(name, nname);
sprintf(name,"%s", nname);
sprintf(nname, "./lfille%d", i);
}
}
return 0;
}
I compiled the source code with gnu gcc 4.8.2.
The program worked fine for me. I think you are only passing one argument to the program instead of two. This is why. I suggest what Weather Vane said in his answer.
The parameter *argv[] is an array of string pointers, with argc informing the length of this array.
The first element argv[0] points to a string holding the program name. If there were any runtime arguments supplied when the program is run, a string pointer is supplied for each one, with the appropriate value in argc to tell you how many elements of the string pointer array have been supplied. If there were no program arguments supplied, *argv[] array will have a length of 1.
If you try to access the arguments that should have been given, you will be indexing beyond the length of the array *argv[] which leads to undefined behaviour. You will be dereferencing a pointer which has an essentially random value. This might be benign, or it might lead to the segmentation fault due to trying to access memory you are not allowed.
I suggest any program which takes (say 2) user arguments at run time have checking code similar to this:
if (argc < 3) {
printf ("Syntax should be: %s filename links\n", argv[0]);
exit (1);
}

subsequent printf statement ruining unrelated array

In the following code, the printed result for char array dir is gibberish.
However, if I comment out the indicated printf statement, the printed result is intelligible. What is going on here? Thanks. sing code blocks / gcc.
#include <stdio.h>
#include <string.h>
char* handle_input(int argc,char *argv[]){
char dir[200];
printf("Number of arguments: %d\n",argc);
if(argc<2) {
printf("No argument specified\n");
strcpy(dir,"Default argument");
}
else{
printf("Command line directory was specified\n");
++argv;
strcpy(dir,argv[0]);
}
strcat(dir,"_CAT");
return dir;
}
int main(int argc, char *argv[]){
char* dir;
dir = handle_input(argc,argv);
printf("This one messes it up!\n");
printf("%s\n",dir);
printf("DONE\n");
return 0;
}
In your handle_input function, you're returning a local array, which is a huge no-no; after the function ends, that array no longer exists, and what you return is just nonsense. This invokes undefined behavior later in your program. That printf call happens to overwrite the memory which previously belonged to the array. Without the printf call, that memory just happens to be intact, which is why it comes out intelligibly.
The right way to return an array is like this:
char* handle_input(int argc,char *argv[]){
char* dir = malloc(200 * sizeof(char)); // sizeof unnecessary for char,
// but it's a good habit to have
printf("Number of arguments: %d\n",argc);
if(argc<2) {
printf("No argument specified\n");
strcpy(dir,"Default argument");
}
else{
printf("Command line directory was specified\n");
++argv;
strcpy(dir,argv[0]); // This is unsafe! use strncpy instead
}
strcat(dir,"_CAT");
return dir;
}
Using malloc ensures that the memory allocated will continue to exist after the end of the function, and that you will no longer be causing undefined behavior. Note that arrays are somewhat "special"; you can return primitive values (int, char, etc) and structs without having this sort of behavior occur.
You are returning a local char dir[200] in the function handle_input, after the function exits, it's undefined behavior to access it.
Use dynamic memory allocation instead, like:
char* handle_input(int argc,char *argv[]){
char *dir = malloc(200);
//do the processing
return dir;
}
Remember to free it once it's out of use.
You are returning a local vasriable
Either
Use malloc (as you are in the C world with printf)
Pass in a pointer to be filled up

input from command-line argument works, but input from internal char* gives Bus Error. Shouldn't it be identical?

I wrote a function that will take a char* representing a binary number, and add one to that number. I've encountered a very confusing error, which is that the function works fine and dandy when the char* comes from user input when calling the function (a.k.a. argv[1]), but gives me a Bus error: 10 when I instead initialize the variable internally and pass it to the same function. I'm not sure what's behind this, so I turn to you guys. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void addOneBinaryMain(char* strBiNum, int index)
{
if (strBiNum[index] == '0' || index == 0) { //BUS ERROR OCCURS HERE
strBiNum[index] = '1';
return;
} else {
strBiNum[index] = '0';
addOneBinaryMain(strBiNum, index - 1);
}
}
void addOneBinary(char* strBiNum)
{
addOneBinaryMain(strBiNum, strlen(strBiNum)-1);
}
int main(int argc, char* argv[]) {
char* str = argv[1];
char* strZero = "00000000";
int i;
printf("%s\n", str);
printf("%s\n", strZero);
addOneBinary(str);
printf("added one to input string: %s\n", str); //succeeds
addOneBinary(strZero);
printf("added one to internal zero string: %s\n", strZero);
return 0;
}
Following around the error with print statements, it seems that it occurs in the addOneBinaryMain function (the recursive step), at the point I've marked.
strZero points at a constant string, that cannot be changed
strZero is just a point initialized with the address of your literal string "000000". This literal string is stored at a place in the application's ram that is read only (If i remember correctly think it's called static store).
Try declaring a char array on the stack or on the heap and copying strZero to it using strcpy.

Resources