Segmentation fault when casting int to char in C - c

I have a very simple C program. In main, I have this operation:
int main(){
int theNumber = 9009;
printf("%s", (char *)theNumber);
}
And when I run it, it gives me a seg fault. Any idea why? Am I doing this wrong?
Expected Output
This code should convert theNumber to a string and then print it. So the output would be:
9009
Actual Output
A segmentation fault.

This is trying to print whatever is found at the address 9009. Seeing as the operating system is not giving your program access to this address (it is likely being used for something else entirely) the operating system raises a segmentation fault. Read more here: What is a segmentation fault?
If you really just wanted to print the value of the integer then use the correct printf command:
int main(){
int theNumber = 9009;
printf("%d", theNumber);
}
Note that you don't need to introduce a string here to achieve this.

Okay. Let's start by talking about what a string is in the C language. Fundamentally, it's a character pointer char * to a location in memory that stores a null terminated series of characters.
An example of this would be:
char *str = malloc(3);
str[0] = 'h';
str[1] = 'i';
str[2] = '\0';
str now contains the String "hi".
What does a type cast do?
The type casting that you are doing takes the integer 9009, and converts it to a char *. Then, since you use that pointer as a string, means that you are telling the computer that at address 9009, there is a null terminated series of bytes.
That's probably not true though, and unless you are on specialized hardware, is certainly not what you want.
How do you convert an integer to a string
We have a fairly easy mechanism to convert printf-able data to strings via snprintf().
First we need to allocate memory for the resultant string. This is a common difference in C from other languages. In C, you are very aware of the memory requirements of your data.
char str[100];
int size_used = snprintf(str, 100, "%d", 9009);
assert(size_used < 100);
Now, if size_used >= 100, then we have a problem. We overflowed our memory area. snprintf() will write as many characters as it can, but not the null terminating zero in that case.

Because that is not a casting of an int to a char. It's a casting of an int to a pointer to char. Basically, a pointer is a variable that holds a memory address. When you try to print that pointer, whose value is 9009, the function accesses the memory at that address, which probably is forbidden, and so you get the segfault.
To avoid that, you should use something like itoa function (be careful that it's not standard, so you may have to implement it yourself).

Related

char pointer interpretation in C

I'm sort of new to C. So, dumb question alert! I would like to understand how the following statements are interpreted by the compiler.
char *str="string1";
*str = "string2"; --> Gives a segmentation fault
puts(ptr);
whereas this works
char *ptr="string1";
puts(ptr);
ptr="string2";
puts(ptr);
This
*str = "string2"; --> Gives a segmentation fault
should be written like this:
str = "string2";
The str identifier is of the type char*, that is, pointer to char. To avoid the mistake, you can write like this:
char* str;
Also, you are assigning a constant string to the variable. So, if you want to assign a modifiable string to str, use strcpy (string copy):
char str[40];
strcpy(str, "My string");
str[2] = '_'; //replacing space with underscore
char *str="string1";
*str = "string2"; --> Gives a segmentation fault
puts(ptr);
Your assignment *str = "string2"; is a constraint violation.
The C standard (perhaps unfortunately) doesn't require C compilers to reject incorrect programs. It does require diagnostic messages for certain kinds of errors, but in some cases not all compilers even do that. You should find out what options to use to get it to diagnose more errors.
If your compiler did give you a warning message, don't ignore it. Warnings from C compiler might be about minor stylistic issues, or they might be about things that you'd expect to be treated as fatal errors. You'll need to learn how to tell the difference.
*str is of type char. "string2" is a string literal, and it's of type char[8], and array of char. But in most contexts (this is another odd thing about C), an expression of array type is treated as an expression of pointer type. So "string2" is treated as an expression yielding a result of type char*, a pointer to the 's' in "string2".
C doesn't support assignment for arrays.
It doesn't make sense to assign a pointer value to a char object (a small integer) -- but old versions of C, from decades ago, didn't make a strong distinction between integers and pointers. Ideally a modern C compiler should just reject the assignment because of the type conflict, but yours is generating code that takes an address of type char*, treats it as an integer, truncates that integer value to store in a single byte, and tries to store it in the 0th element of the array. (You could still do that in modern C with a cast, an explicit conversion, but you don't want to do that anyway.)
So why the segmentation fault? String literals are read-only. (Well, sort of, long story; they're not guaranteed to be read-only, but they often are.) So the chunk of memory holding the array "string1" is protected by the operating system against being modified. A segmentation fault, killing your program, is how the OS responds when you try to bypass that protection.
Incidentally, that last line should be puts(str);, not puts(ptr);. When posting a question here, it's always best to copy and paste the exact code that you compiled. If there are errors, we need to know whether they're errors in your actual code or just typos.
*str = "string2"; --> Gives a segmentation fault because you are trying to assign a value of multiple chars to the char pointer *str which should return only one char value,since its a char pointer not a string pointer.
char *ptr="string2";
This statement works because you are initializing it at the time of declaration and hence, it works.

Why scanf works normally when using pointer to a pointer?

I'm wondering why this code can work. I'm assuming that the scanf is assigning the value to the address of a pointer to a char. I know this expression is undefined but why does printf using a pointer can print the correct value?
int main() {
char* p;
p = (char*)malloc(sizeof(char));
scanf("%c", &p);
printf("%c", p);
return 0;
}
And the result is
c
c
p is a variable that holds a memory address, and memory addresses are surely longer than 1 byte. If you store a char value in this variable, the previous value (the malloc'ed memory block) will be lost. printf just treates your variable as a char variable and prints its contents. If you suspected that the char would be stored in the memory block obtained by malloc, no it wasn't.
Try this:
int main() {
char *p, *q;
p = q = (char*)malloc(sizeof(char));
scanf("%c", &p);
printf("%c\n%c\n", p, *q);
return 0;
}
With the scanf(), you are storing (rather forcibly) one byte into a variable that is more than one byte (sizeof(char *), likely 8 bytes on a 64-bit machine). With the printf(), you then read one byte (sizeof(char), always one by standard) of this variable of size sizeof(char *) (more than one byte) and print it. Your variable p is more space than is needed to store a char. Since the sizes don't line up, you're not sure which byte of p will be read by printf(). It could be the byte that scanf() wrote, or it could be garbage data. You just got lucky and printf() read the same byte that scanf() wrote.
If all this sounds a bit uncertain, it is because it involves undefined behaviour. You are using scanf() and printf() improperly, so they make no guarantees as to what will happen. In short, don't do this.
printf() and scanf() don't perform any special type checking on the source/destination given as an argument. They use fancy pointer arithmetic with the arguments on the stack to figure out where to read/write things as needed. After the compiler builds it, printf() and scanf() will not complain. Your compiler should have given you warnings that the types of the arguments given do not match the format string. If it didn't, you either have a bad/old compiler or you should enable more warnings with the command line option -Wall.
To hopefully help explain the other answers, it looks as if you were aiming to do the following - compare the differences then take another look at the other answers and see if that helps, as I'm not sure you're yet clear about what's happening in your code.
int main() {
char* p = malloc(sizeof(char));
scanf("%c", p);
printf("%c", *p);
return 0;
}

How to point at incompatible pointer type in C?

In the book Learn C The Hard Way at excercise 15 there is suggestion to break program by pointing integer pointer at array of strings and using C cast to force it. How can I do it?
Here is a small example. the result depends on the endianness of your system and the size of int. I would expect the first or fourth character to change to the next character in the alphabet.
#include<stdio.h>
int main(void) {
char string[100] = "Somestring";
int *p;
/* Let p point to the string */
p = (int*)string;
/* modify a value */
(*p)++;
/* Let's see if any character got changed */
printf("%s", string);
return 0;
}
It should be pointed out that not all casts are safe and that the result could be implementation defined or undefined. This example is actually undefined, since int could have stricter alignment constraints than char.
When writing portable code you need to take great care when using casts.
The code above could break on any system where sizeof(int) is greater than the string length regardless of alignment issues. In this case, where the string has size 100, we wouldn't expect that to happen in a long while. Had the string been 4-7 bytes it could happen sooner. The jump from 32- to 64-bit pointers broke a lot of old code that assumed that pointers and int were the same size.
Edit:
Is there an easy fix to the alignment problem? What if we could somehow make sure that the string starts in an address that is also suitable for an int. Fortunately, that is easy. The memory allocation function malloc is guaranteed to return memory aligned at an address that is suitable for any type.
So, instead of
char string[100] = "Somestring";
we can use
char *string = malloc(100);
strcpy(string, "Somestring");
The subsequent cast is now safe alignment-wise and is portable to systems where int is smaller than 100.
Note that malloc is declared in stdlib.h, so we should add the following at the top of our code file:
#include<stdlib.h>
That's simply an abusive way of casting.
// setup the pointers to the start of the arrays
int *cur_age = ages;
char **cur_name = names;
What the author of that link meant by "to break program by pointing integer pointer at array of strings and using C cast to force it." He meant that you can write something like this int *cur_age = (int *)names; That is to cast a pointer to pointer to char to a pointer to int. You can do that in C, which allows you to cast from one type of pointer to another type of pointer; but be warned you need to know what you are doing.
Here the author wanted to show how to break a program by pointing a pointer to a wrong type. His example, however, is probably making you more confused rather than helping you to understand pointers.
To cast, use the cast operator: (type)expression. For example, to cast an expression of type double to int:
(int)sqrt(2);
In your specific case, cast names to int* (the type of cur_age) to break the program:
cur_age = (int*)names;
To point incompatible pointer in c you only need to cast it to void.
//array of string declaration
char aStr[50][50];
Int *pint;
//do whatever you need with string array
pint = (*int)(*void)aStr;
I'm writing this from my cell phone.
if you increment your pointer past the allocated memory, you might end up in your program stack and change value to it.

string manipulations in C

Following are some basic questions that I have with respect to strings in C.
If string literals are stored in read-only data segment and cannot be changed after initialisation, then what is the difference between the following two initialisations.
char *string = "Hello world";
const char *string = "Hello world";
When we dynamically allocate memory for strings, I see the following allocation is capable enough to hold a string of arbitary length.Though this allocation work, I undersand/beleive that it is always good practice to allocate the actual size of actual string rather than the size of data type.Please guide on proper usage of dynamic allocation for strings.
char *str = (char *)malloc(sizeof(char));
scanf("%s",str);
printf("%s\n",str);
1.what is the difference between the following two initialisations.
The difference is the compilation and runtime checking of the error as others already told about this.
char *string = "Hello world";--->stored in read only data segment and
can't be changed,but if you change the value then compiler won't give
any error it only comes at runtime.
const char *string = "Hello world";--->This is also stored in the read
only data segment with a compile time checking as it is declared as
const so if you are changing the value of string then you will get an
error at compile time ,which is far better than a failure at run time.
2.Please guide on proper usage of dynamic allocation for strings.
char *str = (char *)malloc(sizeof(char));
scanf("%s",str);
printf("%s\n",str);
This code may work some time but not always.The problem comes at run-time when you will get a segmentation fault,as you are accessing the area of memory which is not own by your program.You should always very careful in this dynamic memory allocation as it will leads to very dangerous error at run time.
You should always allocate the amount of memory you need correctly.
The most error comes during the use of string.You should always keep in mind that there is a '\0' character present at last of the string and during the allocation its your responsibility to allocate memory for this.
Hope this helps.
what is the difference between the following two initialisations.
String literals have type char* for legacy reasons. It's good practice to only point to them via const char*, because it's not allowed to modify them.
I see the following allocation is capable enough to hold a string of arbitary length.
Wrong. This allocation only allocates memory for one character. If you tried to write more than one byte into string, you'd have a buffer overflow.
The proper way to dynamically allocate memory is simply:
char *string = malloc(your_desired_max_length);
Explicit cast is redundant here and sizeof(char) is 1 by definition.
Also: Remember that the string terminator (0) has to fit into the string too.
In the first case, you're explicitly casting the char* to a const one, meaning you're disallowing changes, at the compiler level, to the characters behind it. In C, it's actually undefined behaviour (at runtime) to try and modify those characters regardless of their const-ness, but a string literal is a char *, not a const char *.
In the second case, I see two problems.
The first is that you should never cast the return value from malloc since it can mask certain errors (especially on systems where pointers and integers are different sizes). Specifically, unless there is an active malloc prototype in place, a compiler may assume that it returns an int rather than the correct void *.
So, if you forget to include stdlib.h, you may experience some funny behaviour that the compiler couldn't warn you about, because you told it with an explicit cast that you knew what you were doing.
C is perfectly capable of implicit casting between the void * returned from malloc and any other pointer type.
The second problem is that it only allocates space for one character, which will be the terminating null for a string.
It would be better written as:
char *string = malloc (max_str_size + 1);
(and don't ever multiply by sizeof(char), that's a waste of time - it's always 1).
The difference between the two declarations is that the compiler will produce an error (which is much preferable to a runtime failure) if an attempt to modify the string literal is made via the const char* declared pointer. The following code:
const char* s = "hello"; /* 's' is a pointer to 'const char'. */
*s = 'a';
results in the VC2010 emitted the following error:
error C2166: l-value specifies const object
An attempt to modify the string literal made via the char* declared pointer won't be detected until runtime (VC2010 emits no error), the behaviour of which is undefined.
When malloc()ing memory for storing of strings you must remember to allocate one extra char for storing the null terminator as all (or nearly all) C string handling functions require the null terminator. For example, to allocate a buffer for storing "hello":
char* p = malloc(6); /* 5 for "hello" and 1 for null terminator. */
sizeof(char) is guaranteed to be 1 so is unrequired and it is not necessary to cast the return value of malloc(). When p is no longer required remember to free() the allocated memory:
free(p);
Difference between the following two initialisations.
first, char *string = "Hello world";
- "Hello world" stored in stack segment as constant string and its address is assigned to pointer'string' variable.
"Hello world" is constant. And you can't do string[5]='g', and doing this will cause a segmentation fault.
Where as 'string' variable itself is not constant. And you can change its binding:
string= "Some other string"; //this is correct, no segmentation fault
const char *string = "Hello world";
Again "Hello world" stored in stack segment as constant string and its address is assigned to 'string' variable.
And string[5]='g', and this cause segmentation fault.
No use of const keyword here!
Now,
char *string = (char *)malloc(sizeof(char));
Above declaration same as first one but this time you are assignment is dynamic from Heap segment (not from stack)
The code:
char *string = (char *)malloc(sizeof(char));
Will not hold a string of arbitrary length. It will allocate a single character and return a pointer to char character. Note that a pointer to a character and a pointer to what you call a string are the same thing.
To allocate space for a string you must do something like this:
char *data="Hello, world";
char *copy=(char*)malloc(strlen(data)+1);
strcpy(copy,data);
You need to tell malloc exactly how many bytes to allocate. The +1 is for the null terminator that needs to go onto the end.
As for literal string being stored in a read-only segment, this is an implementation issue, although is pretty much always the case. Most C compilers are pretty relaxed about const'ing access to these strings, but attempting to modify them is asking for trouble, so you should always declare them const char * to avoid any issues.
That particular allocation may appear to work as there's probably plenty of space in the program heap, but it doesn't. You can verify it by allocating two "arbitrary" strings with the proposed method and memcpy:ing some long enough string to the corresponding addresses. In the best case you see garbage, in the worst case you'll have segmentation fault or assert from malloc or free.

Why is this string reversal C code causing a segmentation fault? [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 5 years ago.
I am trying to write code to reverse a string in place (I'm just trying to get better at C programming and pointer manipulation), but I cannot figure out why I am getting a segmentation fault:
#include <string.h>
void reverse(char *s);
int main() {
char* s = "teststring";
reverse(s);
return 0;
}
void reverse(char *s) {
int i, j;
char temp;
for (i=0,j = (strlen(s)-1); i < j; i++, j--) {
temp = *(s+i); //line 1
*(s+i) = *(s+j); //line 2
*(s+j) = temp; //line 3
}
}
It's lines 2 and 3 that are causing the segmentation fault. I understand that there may be better ways to do this, but I am interested in finding out what specifically in my code is causing the segmentation fault.
Update: I have included the calling function as requested.
There's no way to say from just that code. Most likely, you are passing in a pointer that points to invalid memory, non-modifiable memory or some other kind of memory that just can't be processed the way you process it here.
How do you call your function?
Added: You are passing in a pointer to a string literal. String literals are non-modifiable. You can't reverse a string literal.
Pass in a pointer to a modifiable string instead
char s[] = "teststring";
reverse(s);
This has been explained to death here already. "teststring" is a string literal. The string literal itself is a non-modifiable object. In practice compilers might (and will) put it in read-only memory. When you initialize a pointer like that
char *s = "teststring";
the pointer points directly at the beginning of the string literal. Any attempts to modify what s is pointing to are deemed to fail in general case. You can read it, but you can't write into it. For this reason it is highly recommended to point to string literals with pointer-to-const variables only
const char *s = "teststring";
But when you declare your s as
char s[] = "teststring";
you get a completely independent array s located in ordinary modifiable memory, which is just initialized with string literal. This means that that independent modifiable array s will get its initial value copied from the string literal. After that your s array and the string literal continue to exist as completely independent objects. The literal is still non-modifiable, while your s array is modifiable.
Basically, the latter declaration is functionally equivalent to
char s[11];
strcpy(s, "teststring");
You code could be segfaulting for a number of reasons. Here are the ones that come to mind
s is NULL
s points to a const string which is held in read only memory
s is not NULL terminated
I think #2 is the most likely. Can you show us the call site of reverse?
EDIT
Based on your sample #2 is definitely the answer. A string literal in C/C++ is not modifiable. The proper type is actually const char* and not char*. What you need to do is pass a modifiable string into that buffer.
Quick example:
char* pStr = strdup("foobar");
reverse(pStr);
free(pStr);
Are you testing this something like this?
int main() {
char * str = "foobar";
reverse(str);
printf("%s\n", str);
}
This makes str a string literal and you probably won't be able to edit it (segfaults for me). If you define char * str = strdup(foobar) it should work fine (does for me).
Your declaration is completely wrong:
char* s = "teststring";
"teststring" is stored in the code segment, which is read-only, like code. And, s is a pointer to "teststring", at the same time, you're trying to change the value of a read-only memory range. Thus, segmentation fault.
But with:
char s[] = "teststring";
s is initialized with "teststring", which of course is in the code segment, but there is an additional copy operation going on, to the stack in this case.
See Question 1.32 in the C FAQ list:
What is the difference between these initializations?
char a[] = "string literal";
char *p = "string literal";
My program crashes if I try to assign a new value to p[i].
Answer:
A string literal (the formal term for a double-quoted string in C source) can be used in two slightly different ways:
As the initializer for an array of char, as in the declaration of char a[], it specifies the initial values of the characters in that array (and, if necessary, its size).
Anywhere else, it turns into an unnamed, static array of characters, and this unnamed array may be stored in read-only memory, and which therefore cannot necessarily be modified. In an expression context, the array is converted at once to a pointer, as usual (see section 6), so the second declaration initializes p to point to the unnamed array's first element.
Some compilers have a switch controlling whether string literals are writable or not (for compiling old code), and some may have options to cause string literals to be formally treated as arrays of const char (for better error catching).
(emphasis mine)
See also Back to Basics by Joel.
Which compiler and debugger are you using? Using gcc and gdb, I would compile the code with -g flag and then run it in gdb. When it segfaults, I would just do a backtrace (bt command in gdb) and see which is the offending line causing the problem. Additionally, I would just run the code step by step, while "watching" the pointer values in gdb and know where exactly is the problem.
Good luck.
As some of the answers provided above, the string memory is read-only. However, some compilers provide an option to compile with writable strings. E.g. with gcc, 3.x versions supported -fwritable-strings but newer versions don't.
I think strlen can not work since s is not NULL terminated. So the behaviour of your for iteration is not the one you expect.
Since the result of strlen will be superior than s length you will write in memory where you should not be.
In addition s points to a constant strings hold by a read only memory. You can not modify it. Try to init s by using the gets function as it is done in the strlen example

Resources