C string function (strcopy,strcat...,strstr) with arrays and pointers - c

Whenever I am using one of these functions in dev-C++(I know its old but for some reason still taught at my college.)
strcat,strcpy,strcmp,strchr...//And their variants stricmp...
The first argument for these functions always has to be an array (i.e:
char ch[]="hello";
But it can't be a pointer to a string bc for some reason this causes a crash.
In fact for an example look at both of these codes:
code1:
#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
char *ch2="Hello Galaxy!";
strcat(ch,ch2);
printf("%s",ch);
scanf("%d")//Just to see the output.
}
This code works fine and gives the expected result(Hello World!Hello Galaxy!)
But the inverse code2 crashes.
code2:
#include<stdio.h>
#include<string.h>
main()
{char ch[20]="Hello world!";
char *ch2="Hello Galaxy!";
strcat(ch2,ch);
printf("%s",ch2);
scanf("%d")//Just to see the output.
}
This code crashes and causes a
file.exe has stopped working Error.
This is the same for almost all of the strings functions that takes two arguments.
What is the cause of this problem.

With char *ch2 = "Hello Galaxy!"; you are obtaining a pointer to a string literal. You should never attempt to modify a string literals, as this invokes undefined behaviour (which in your case has manifested as a crash).
With char ch[20] = "Hello World!"; you are initialising an array using the contents of a string literal, so you end up with your own modifiable copy of the string in ch.
Also, note that 20 characters is not enough for Hello World!Hello Galaxy! to fit, and this is also undefined behaviour, and known as overflowing your buffer.

char ch[20] = "Hello world!"
ch is an array of char initialized by the elements of a string literal (and the rest of the array is initialized with 0).
char *ch2="Hello Galaxy!";
ch2 is a pointer to a string literal.
String literals are not required to be modifiable in C. Modifying a string literal is undefined behavior in C.

There are two problems. The first is that your string literal is not long enough to hold the concatenated string "Hello world!Hello Galaxy!". The space allocated is only 13 bytes (12 characters plus the space for the '0' byte that terminates the string). The concatenated string requires 26 bytes (25 chars + 1 null-valued char).
However, this isn't the real problem. The real problem is that you're accessing memory that you should not be, and that the operating system often protects. Most implementations of C provide four areas of storage:
The stack, where variables you declare in a function are allocated
The heap, where calls to malloc/calloc/realloc allocate memory
Global static storage, where non-const global variables (those declared outside of a function) are allocated.
Global constant storage, where all string literals and other global variables declared const are allocated.
The first three areas are, in principle, modifiable. The fourth area is not, and is often stored in memory that the operating system marks as read-only. When you assign the string literal "Hello Galaxy!" tochar* ch2, the variablech2` points into global constant storage.
To give you a better idea, the following code generals a segfault when I run it:
#include <stdio.h>
int main(int argc, char** argv)
{
char* s = "Foo bar baz";
s[0] = 'B';
printf("%s\n",s);
return 0;
}
The segfault occurs in the s[0] = ... line, because I'm accessing storage that the operating system has marked as read-only.

That is about the size of pointer array..overflow problem..
char *ch2="Hello Galaxy!"; when you use this automaticly the size of *ch2 gets 14 with the null character but when you move the ch[] array into the *ch2 , you get an error. you cannot move an array with 20 size into another array with 14 size...

String literals are read-only.This means that if you assign:
char* str="Hello";
You can't pass str as first argument of strcpy and strcat, because this would cause to write over read-only memory.
If instead you declare it this way:
char str2[]="Hello";
Then the str2 array is stored on the stack, and you can change it's values.
You can still pass str to functions like strcmp (which just reads the wto strings and compare them), or as second argument of strcat and strcpy, since this doesn't cause the string to be written.

you got an error because you try to access the code section of your process which is read-only.
that is your string literal present in code and the address of that string literal you use in assignment to your pointer variable.
So you can access the code but you cannot modify this.
every executable file contain some sections
like...
1.text(code of your program as well as string literals present here)
2.data uninitialized
3.data initialized
you can veryfy this by command
size <executable-file-neme>
Also using command
objdump -D <executable-file-neme>

Related

How char * pointers works [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

I want to know why this works without having to bind memory for the string

Hello guys I recently picked up C programming and I am stuck at understanding pointers. As far as I understand to store a value in a pointer you have to bind memory (using malloc) the size of the value you want to store. Given this, the following code should not work as I have not allocated 11 bytes of memory to store my string of size 11 bytes and yet for some reason beyond my comprehension it works perfectly fine.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
char *str = NULL;
str = "hello world\0";
printf("filename = %s\n", str);
return 0;
}
In this case
str = "hello world\0";
str points to the address of the first element of an array of chars, initialized with "hello world\0". In other words, str points to a "string literal".
By definition, the array is allocated and the address of the first element has to be "valid".
Quoting C11, chapter §6.4.5, String literals
In translation phase 7, a byte or code of value zero is appended to each multibyte
character sequence that results from a string literal or literals.78) The multibyte character
sequence is then used to initialize an array of static storage duration and length just
sufficient to contain the sequence. For character string literals, the array elements have
type char, and are initialized with the individual bytes of the multibyte character
sequence. [....]
Memory allocation still happens, just not explicitly by you (via memory allocator functions).
That said, the "...\0" at the end is repetitive, as mentioned (in the first statement of the quote) above, by default, the array will be null-terminated.
Using a char variable without malloc is stating that the string you are assigning is read-only. This means that you are creating a pointer to a string constant. "hello world\0" is somewhere in the read-only part of memory and you are just pointing to it.
Now if you want to make changes to the string. Let's say changing the h to H, that would be str[0]='H'. Without malloc that will not be possible to make.
When you declare a string literal in a C program, it is stored in a read-only section of the program code. A statement of the form char *str = "hello"; will assign the address of this string to the char* pointer. However, the string itself (i.e., the characters h, e, l, l and o, plus the \0 string terminator) are still located in read-only memory, so you can't change them at all.
Note that there's no need for you to explicitly add a zero byte terminator to your string declarations. The C compiler will do this for you.
Right. But in this case you are just pointing to a string literal which is placed in the constant memory area. Your pointer is created in the stack area. So you are just pointing to another address. i.e, at the starting address of string literal.
Try using copy the string literal in your pointer variable. Then it will give error because you have not allocated memory. Hope you understand now.
Storage for string literals is set aside at program startup and held until the program exits. This storage may be read-only, and attempting to modify the contents of a string literal results in undefined behavior (it may work, it may crash, it may do something in between).

constant pointer and pointer to constant in a string [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

Who throws the segmentation fault?

Given the below program.
int main() {
char *str = "hello word";
str[0] = 'a';
return 0;
}
The above program throws segmentation fault. I know it throws because the read only segment contains the hello world, and it cannot be modified. If store instruction that changes from "h" to "a" is done in the L1 cache(inside the processor) and MMU comes into picture only when the page is flushed from L3 to main memory, who throws segmentation fault almost immediately.
The below code which is effectively doing the same thing, doesn't cause any segmentation fault. Why?
int main() {
char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
str[0] = 'a';
return 0;
}
The processor cache has tags associated with each cache line that tell it the permissions applied to the memory currently held in that cache line. As such, an attempt at writing to read-only memory will (normally) be caught immediately upon attempting to write to the cache; it will not wait until that cache line is flushed to main memory.
As far as the difference between the two examples goes, it's pretty simple: the first defines a statically allocated string literal. Attempting to modify that string literal causes undefined behavior. The second defines an array of char that is initialized to a particular value -- but after it's initialized, it's pretty much like any other array. In particular, the result of modifying the content of the array is well defined.
In the second, you are making a copy. While in the first you aren't.
char str[] = {'h','e','l','l','o',' ','w','o','r','l','d','\0'};
Here str is an array created on stack. To str, contents are being copied. How ever in -
char *str = "hello word";
str is pointing to data residing in non-modifiable section. So, you can't and when tried results segmentation fault.
Description for comments
I don't think, for the primitive data types C and C++ varies it's rules. From ISO/IEC 14882:2003(E), Section 8.5.2
1. A char array (whether plain char, signed char, or unsigned char) can be
initialized by a string- literal (optionally enclosed in braces); a wchar_t
array can be initialized by a wide string-literal (option- ally enclosed in
braces); successive characters of the string-literal initialize the members of
the array.
[Example:
char msg[] = "Syntax error on line %s\n"; shows a character array
whose members are initialized with a string-literal. Note that because
’\n’ is a single character and because a trailing ’\0’ is appended,
sizeof(msg) is 25.
]
2. There shall not be more initializers than there are array elements.
[Example:
char cv[4] = "asdf" ;// error is ill-formed since there is no space for the implied trailing ’\0’.
]
So, example 2 clears the doubt.

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