Segmentation fault by passing arguments to a function (C, codeblocks on linux) - c

Why do i keep getting "segmentation fault (core dumped)" by running this?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
printf("%d", strlen(argc));
return 0;
}
That's my "argc"
gnome-terminal --disable-factory -t Es1 -x /usr/bin/cb_console_runner LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. /.../Lab1/Es1/bin/Debug/Es1 Es1.cbp es1file.txt es1out.txt (in /.../Lab1/Es1/.)

size_t strlen(const char *str)
The strlen() function takes a pointer to character string. and you are passing an integer to it.

That's because argc isn't a string, it's an integer value. The name argc stands for "argument count", and tells you the number of entries in the argv array.
Using argc as a pointer to a string leads to undefined behavior, which often results in crashes. Really, using anything that is not a pointer to a string as argument to a function which expects a pointer to a string will lead to undefined behavior.
Don't you get a warning about it? Then you need to enable more warnings when compiling! You should get a warning telling you that you are "making a pointer from integer without cast" (or something similar).

argc is an integer, but strlen() expects a pointer to a string (char *), that's why you get a Segmentation Fault.

1°) strlen, as its name clearly states, gives you the length of a string. Here, you're trying to use it on a int : argc. (Which gives you the length of the argument array argv).
In C, strings are arrays of characters terminated by the "\0" character. Strlen will only work safely if you use on such an array (if the array do not have a "\0" ending character, you'll get the same error).
2°) If you want to display the number of arguments, simply use argc (as in "argument count") minus one (since the name of the program will be the first argument).
3°) If you want to display the length of one argument, you'll need to specify the argument and then use strlen. E.g. :
if (argc > 1) {
printf("%d", strlen(argv[1]));
}

Related

scanf results in seg fault?

gcc compiles perfectly well, but as soon as scanf accepts a string it seg faults. I'm sort of at a loss. Here's the code.
char *line[256];
void *mainThread()
{
while (*line != "quit") {
scanf("%s", *line);
printf("%s", *line);
}
return;
}
Is there something about scanf I'm not understanding here?
First, you are allocating an array of pointers to characters, not an array of char:
char *line[256]; /* allocates 256 pointers to a character -
(pointers are initialized to NULL) */
You need to allocate an array of characters instead:
char line[256]; /* allocates 256 characters */
Second, you need to use strcmp to compare the strings - with !=, you are comparing the pointer (address) stored in line[0] (which is the same as *line) with a pointer to the string literal "quit", and they are always different.
You can use the following sscce as a starting point:
#include <string.h>
#include <stdio.h>
char line[256];
int main()
{
while (strcmp(line, "quit") != 0) {
scanf("%s", line);
printf("%s", line);
}
return 0;
}
Some additional notes:
See #Joachims answer for an explanation of the actual cause of the segmentation fault.
You are declaring your function to return a void* pointer, but you are not returning anything (using return with no argument). You should then simply declare it as void.
Do not use scanf() to read input, since it might read more characters than you have allocated which leads to buffer overflows. Use fgets() instead. See also Disadvantages of scanf.
Always compile with all warnings enabled, and take them serious - e.g. if you are using gcc, compile with -Wall -pedantic.
When declaring global variables, they are initialized to zero. And as you are declaring an array of pointers to char (instead of an array of char as I think you really intended) you have an array of 256 NULL pointers.
Using the dereference operator * on an array is the same as doing e.g. array[0], which means that as argument to both scanf and printf you are passing line[0], which as explained above, is a NULL pointer. Dereferencing NULL pointers, like scanf and printf will do, is a case of undefined behavior, one that almost always leads to a crash.
It is compiling because your program is syntactically correct. However, it has serious semantic errors which show up as program crash due to segfault. The global array line is initialized to zero, as any global variable. Since, line is an array of pointers (not an array of characters which is intended), the zeros are interpreted as NULL, the null pointer. *line is same as line[0] and the string literal "quit" evaluates to a pointer to its first element. Therefore the while condition is the same as
while(NULL != "quit") // always true
Next, scanf("%s", *line); tries to write the input string into the buffer pointed to by line[0] which is NULL - a value which is unequal to the address of any memory location. This will result in segfault and cause the program to crash.
There are other mistakes in your code snippet. Let's take them one by one.
char *line[256];
The above statement defines an array line of 256 pointers to characters, i.e., its type is char *[256]. What you need is an array of characters -
char line[256];
You can't compare array in C. What you can do is compare them element-by-element. For strings, you should use the standard library function strcmp. Also, please note that the %s conversion specifier in the format string of scanf reads a string from stdin and writes it into the buffer pointed to by the next argument. It puts a terminating null byte at the end but it does not check for buffer overrun if you input a string too large for the buffer to hold. This would lead to undefined behaviour and most likely segfault due to illegal memory access. You should guard against buffer overrun by specifying maximum field width in the format string.
void *mainThread();
The above function declaration means that mainThread is function which returns a pointer of void * type and take an unspecified but fixed number and type of arguments because empty parentheses mean no information about the parameter list is provided. You should write void in the parameter list to mean that the function takes no arguments. Also note that the empty return statement in your function would cause undefined behaviour if the return value of the function is used because you are not returning anything and would be using the garbage value in the return address of the function instead. Assuming that you want to return the string, it should be defined as -
char line[256];
char *mainThread(void) {
while(strcmp(line, "quit") != 0) {
scanf("%255s", line); // -1 for the terminating null byte
printf("%s", line);
}
return line;
}

Pointer to one single char of a two dimensional array

As far as I know, an array like
int example[10]
Is nothing else than a pointer to the first element in this array.
char* argv[]
Is an array of pointers; so that should be pointers which point to other pointers.
I have following problem now:
int main(int argc, char* argv[])
{
double ptrarg2=argv[2][1];
printf("beginletter=%c\nbeginpos=%d\n",&ptrarg2, ptrarg2);
return 0;
}
I am starting the program with ./program test and expecting the output to be:
beginletter=c
beginpos=123213123
While 123213123 should be the adress where the c is actually stored.
I am actually getting:
beginletter=
beginpos=0
what am I doing wrong? Thank you in advance!
It looks like argv[0] is going to be "./program", argv[1] is going to be "test", and argv[2] is going to be undefined or NULL because you don't have three arguments. The value of argc should tell you how many items there are in argv[]. My guess in this case is that the answer will be 2, and therefore only the first two (argv[0] and argv[1]) are valid.
There are several other strange things going on here. ptrarg2 is declared as a double, not as a char; the behavior here would be to convert the character to its floating point numeric equivalent and store that. Perhaps you meant ptrarg2 to be a char?
Next up, the printf() doesn't correspond very well to its additional arguments. &ptrarg2 is a double *, but you're assigning it to a %c (character) field, not a %p (pointer) field. ptrarg2 is a double, but you're assigning it to a %d (decimal number) field, not a %lf (long float, aka double) field. printf will happily try and print out values even when your types don't match, but they will be wrong, and crashing is quite possible.
&ptrarg2 is the address of the local variable, which is not the address that you are expecting. Just use argv[1][0] and argv[1]. argv[1][0] will give you the first character of the first argument, and argv[1] will give you the pointer to the first argument.
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("beginletter=%c\nbeginpos=%p\n",argv[1][0], argv[1]);
return 0;
}

pass char array as argument

Can anyone explain to me what I don't understand here please?
I am trying to pass the argument as a "string" (i know there are no strings in c) so that I can use that string later with other functions like it's a file name that has to be passed for example.
But I don't know why it won't accept it or what type should it be
#include <stdio.h>
int main ( int argc, char *argv[] )
{
char *array= argv[0];
foo(*array);
}
void foo( char *array)
// notice the return type - it's a pointer
{
printf(array);
}
thanks alot!
You should be calling the function like this:
foo(array);
What you're doing is dereferencing the pointer, which returns a char, which is the first character in the string.
Your printf call should also look like this:
printf("%s", array);
Your entire fixed code should look like the following:
#include <stdio.h>
void foo(char *array)
{
printf("%s", array);
}
int main ( int argc, char *argv[] )
{
// TODO: make sure argv[1] exists
char *array= argv[1];
foo(array);
}
When you say foo (*array), you're decaying the array into a pointer to the first element, in order to dereference that element, giving you the first character. That's what you're trying to pass to the function. Leave out the asterisk and just pass array for it to decay into the pointer you need.
The other issue is that you're not using printf correctly. First of all, here's a reference. You need to pass a string of tokens that tell the compiler what type of argument to expect next because it has no way of telling. In your case, your string would contain "%s" to tell it to expect a char *, and then you'd pass array as that char * argument.
printf ("The string is %s", array);
argv is a array of character pointers, that means argv is going to store the address of all the strings which you passed as command line argument.
so argv[0] will gives you the address of first string which you passed as command line argument, that you are storing into the pointer variable array in main function.
Now you have to pass only the address to the function foo but you are passing the first character of that string. For example if your first command line argument is temp.txt you are passing character t to the function foo. So inside foo function you are having a char pointer variable array, in that ASCII value of the character t will be assigned. And then you are passing that to printf, which will treads that ASCII value as address, and it will tries to access that address to print which will leads to crash (unexpected behaviour).
So you have to pass only the address of the command line argument to the function foo like below.
foo(array);
printf(array) - Here printf will treads the format specifier as string(%s) and it will tries to print all the characters starting from the address array untill it meets a null character \0.
But better to add the printf like below
printf("%s", array);

segmentation fault in C assign string to char

#include <stdio.h>
#include <stdlib.h>
int main()
{
char a="9jhjhi";
printf("%s",a);
}
Why does this throw a segmentation fault? What happens behind the screens?
You need to use char *a = "...".
printf when passed %s will run through a string looking for a 0/NULL byte. In your case you are not assigning a string literal to a, and in fact your compiler should have thrown a warning that you were trying to initialize a char from a pointer.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *a="9jhjhi";
printf("%s",a);
}
Your error is that
char a="9jhjhi";
should be
char *a="9jhjhi";
What happens is undefined behavior - so anything could happen.
Your assigning a string literal to a char, so your a will contain a pointer(to the beginning of that string) converted to a char - whatever that'll be.
%s conversion in printf assumes you pass it a string, which must be a char* pointing to a sequence of chars ending with a 0 terminator. You passed it a char, which certainly does not meet those requirements, so it's quite undefined what'll happen - a crash could be common.
You should also return something from the main() method - it's declared to return an int after all.
a is initialized to a (cast to integer and truncated because char is 3 or 7 bytes too small) pointer that points to a char array (propably somewhere in ROM). What follows is undefined, but it's propably like this: When you pass it to printf with a %s in the format string, it takes the value of a (something in 0-255) and 3 (or 7) unrelated bytes from the stack, gets some bogus address and wreaks havok by accessing someone else's memory.
Use char *a = ....
C does not have strings as in String b = new String();
C has arrays of type char.
So char a="123123" should be a character array.
You aren't using anything from stdlib.h in that code either so there is no reason to #include it.
Edit: yeah, what nos said too. An array name is a pointer.
You mean
char *a = "9jhjhi";
If this compiles without warnings, your compiler settings are messed up. The warnings from gcc show plainly what's happening:
test.c: In function ‘main’:
test.c:5: warning: initialization makes integer from pointer without a cast
test.c:6: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
The string literal is interpreted as a pointer, which is converted (and truncated) to a char.
Then the char is sent into printf as a number, but interpreted as a string. Since it's not null-terminated in any way, printf probably overruns memory when racing through that "string".
When you declare char a without a pointer symbol, you are only allocating enough space on the stack for a single character.
Strings in C are represented by a char array, or a pointer to a char array, terminated by the null character '\0'. But if you use a literal string, the compiler takes care of all of that for you.
Here's how you can get your code to work, then:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *a = "9jhjhi";
printf("%s",a);
}
First of all, you're trying to save an entire string into a single char variable. Use char array (char[size]) instead. You may also want to terminate the string with "\0".
You could remove this error in two ways.
1.char * p="karthik A"
2.char [ ]p="karthik A"

What does the ** operator mean in C?

Does ** have any special meaning in C?
Like this:
static intparse_one (int argc, char **argv)
{
cmd_line *slot;
int value;
Flag_name flag_name;
int i;
printf("argv %s\n",argv);
printf("argv[0] %c\n",**argv);
If so, does the line
**argv
make sense? A program I am trying to get to run is choking on it. If I try to print it I get a segmentation fault.
The first printf prints the string fine. The second printf fails.
Here is what I am getting for the output (The first line is correct):
argv -aps_instance1001-aps_ato0-aps_ipc_debug3
Segementation Fault (core dumped)
"Does ** have any special meaning in C?"
No, it is just two dereferences.
char **argv
means: argv dereferenced two times is a char. In other words argv is a pointer to a pointer to char.
The same for:
"If so, does the line: **argv make sense?"
The declaration says that **argv is a char. At runtime argv will be dereferenced two times; the value is the char that argv, the pointer to a pointer to char, is pointing to.
** is just two *.
As far as the segfault goes, look at your line printf("argv %s\n",argv);. The printf expects a char *, not char **, and so it's looking at an array of pointers rather than an array of characters. printf is trying to print everything at argv as a string of characters until it encounters a zero, and probably goes out of bounds before it finds one.
argv is a char **, which is a pointer to a pointer, or in this case an array of pointers. Don't print it directly, because it has no external meaning. (You can print the pointer value if you want to see it, of course.)
*argv or argv[0] is a char *, which is a pointer to char, which in this case is the first string in argv.
**argv is a char, which in this case is the first character of the first string in argv.
Yes.
char **argv
is the same thing as
char* argv[]
No.
Every * introduces a level of indirection. In this context, it means that argv is a pointer to a pointer. Which it is not, really, as technically you can see it a an array of pointers - it can be declared as char * argv[].
Obviously, by "no", I mean that ** is not special in itself. Or it is special, but neither more nor less than * or ***.
char **argv is same as char *argv[].
Here argv is the argument vector.
Isn't that a pointer to a pointer? I think the ** in front of the argv parameter has the same effect as ref in C#, in case you know C#.
While the string "**" does have a well defined meaning, I think the answer to the questions is "**" is not one operator, but two "*" in a row.
This is in contrast to Fortran where "**" is a single token and functions as the exponentiation operator.
So the meaning is well covered by Martin Beckett, but it really isn't "an operator".

Resources