char c1[ ]="abcde" works while char *c1="abcde" turns out wrong? - c

I was working on the "c programming language" exercise2.4, which deletes each character in s1 that matches any character in the string s2.Below is my code, it works. However,if I change the definition in Main function from char c1[ ]="abcde" to char *c1="abcde", it will turns out segmentation fault(core dumped). Any idea why?
#include<stdio.h>
#define UNREPEAT 1
#define REPEAT 0
void squeeze(char *s1,char *s2);
void main(){
char c1[]="abcde";
char c2[]="cd";
printf("c1 is %s\n",c1);
squeeze(c1,c2);
printf("the final result is %s\n",c1);
}
void squeeze(char *s1,char *s2){
int i,j,judge;
int k=0;
for(i=0;*(s1+i)!='\0';i++){
judge=UNREPEAT;
for(j=0;*(s2+j)!='\0';j++){
if (*(s1+i)==*(s2+j)){
judge=REPEAT;
break;}
}
if( judge==UNREPEAT){
* (s1+k)=*(s1+i);
k++;}
}
*(s1+k)='\0';
}

Because
char c1[] = "abcde";
declares an array, it's readable and writable and will always have 6 bytes (if you consider the terminating '\0') you can't extend it but of course you can use it to store less bytes.
While
char *c1 = "abcde";
is a static string literal it shall not be modified, you should always declare string literals using the const qualifier, that way the compiler would warn you if you try to modify its contents, which is illegal, just use
const char *c1 = "abcde";

char *c1="abcde"
This is a string literal which is read-only and in your function you try to change the contents of it so you might hit seg fault.
Whereas the other case
char c1[] = "abcde";
You are allocating memory on the stack whose contents can be modified.
PS: String literals are read-only

Related

Stack smashing detected when trying to copy one string to another using pointers

I am trying to copy one string to another using pointers, but stack smashing error occurred, while the string is copied successfully.
Here's the code below,
#include <stdio.h>
void strcat(char *str1, char *str2) {
char *run = str1;
while(*run !='\0')
run++;
while(*str2 !='\0') {
*run = *str2;
run++;
str2++;
}
*run = '\0';
}
int main() {
char s[] = "hellomojo";
char t[] = "world";
printf("\ns :%s", s);
printf("\n t :%s",t);
strcat(s, t);
printf("\ns after:%s",s);
}
Is it due to illegal access to memory not pointed by pointers?
This char s[]="hellomojo"; is basically the same as char s[10]="hellomojo";. It is an array of 10 characters (including the NUL-terminator). You cannot store more than 10 characters in it. But you concatenate the other string with this, writing into illegal memory locations beyond the array. This invokes Undefined Behaviour. Hence the stack smashing problem.
The fix would be to increase the size of the first array like:
char s[32] = "hellomojo"; /* 32 chosen arbitrary */
Working with what little code was supplied, my guess would be that at least one of those char pointers doesn't have enough allocated memory, or does not have a null terminating character as expected.
You show the code, but what is the output and the error message? With more information, it would be easier to debug.

Swapping elements of a char array works but swapping elements of a char string leads to core dump

I am trying to perform swap operation as shown in below program, but it seems to crash when I am copying the element b into a (line 3 in swap() method) - this happens if the input is a char string i.e, char *str; If it is a character array instead (as in char str[];) the swap operation works fine.
#include<stdio.h>
void swap(char *a, char *b)
{
char tmp;
tmp = *a;
*a = *b; /* crash occurs here */
*b = tmp;
}
void func(char *a)
{
swap(a+1, a+2);
}
int main()
{
char *str = "abc";
// char str[] = "abc"; /* with this char array, the above swap func works */
func(str);
}
I think this is related to some C string rules that I seem to be unaware of. Please help!
String literals are read-only, trying to modify a string literal leads to undefined behavior.
Simplest solution? Declare it as an array instead:
char str[] = "abc";
char *str = "abc";
Above puts the string in the constant data section (also known as .rdata) of the program.As this is treated as constant data, it can not be modified
char str[] = "abc";
Above puts the string in the stack area of the program, as declared inside the function scope.This data can be modified.
As this is about the storage of string data, you are getting Crash in first declaration.
'char *str = "abc";'
The above places the abc in read only memory. So it cannot be modified.
'char str[]="abc";' is placed in stack. so it can be modified.

Bus error in my own strcat using pointer

I'm doing a pointer version of the strcat function, and this is my code:
void strcat(char *s, char *t);
int main(void) {
char *s = "Hello ";
char *t = "world\n";
strcat(s, t);
return 0;
}
void strcat(char *s, char *t) {
while (*s)
s++;
while ((*s++ = *t++))
;
}
This seems straightforward enough, but it gives bus error when running on my Mac OS 10.10.3. I can't see why...
In your code
char *s = "Hello ";
s points to a string literal which resides in read-only memory location. So, the problem is twofold
Trying to alter the content of the string literal invokes undefined behaviour.
(almost ignoring point 1) The destination pointer does not have enough memory to hold the concatinated final result. Memory overrun. Again undefined behaviour.
You should use an array (which resides in read-write memory) with sufficient length to hold the resulting (final) string instead (no memory overrun).
Suggestion: Don't use the same name for user-defined functions as that of the library functions. use some other name, e.g., my_strcat().
Pseudocode:
#define MAXVAL 512
char s[MAXVAL] = "Hello";
char *t = "world\n"; //are you sure you want the \n at the end?
and then
my_strcat(s, t);
you are adding the text of 't' after the last addres s is pointing to
char *s = "Hello ";
char *t = "world\n";
but writing after 's' is undefined behavior because the compiler might put that text in constant memory, in your case it crashes so it actually does.
you should reserve enough memory where s points to by either using malloc or declare it array style
char s[32] = "Hello ";

C char pointer, char pointer copying char pointer. Whether it can be considered as a automatic / dynamic space creation in memory?

I write my own version of strcpy(). I learn it from http://pweb.netcom.com/~tjensen/ptr/ch3x.htm .
So.. here is the source code:
#include <stdio.h>
char *my_strcpy(char *dst, char *src);
char *my_strcpy(char *dst, char *src)
{
char *ptr = dst;
while (*src)
{
*ptr++ = *src++;
}
*ptr = '\0';
return dst;
}
int main(int argc, const char *argv[])
{
char strA[] = "Awesome string! Yes it is G-String!";
char strB[20];
my_strcpy(strB, strA);
puts(strB);
return 0;
}
In function main() i experiment to change:
char strA[] = "Awesome string! Yes it is G-String!";
char strB[20];
become
char *strA = "Awesome string! Yes it is G-String!";
char *strB;
And, yay! it works! Then the question is, How char *strB and char *ptr = dst (inside my_strcpy() ) work?
In my understanding, they not have more than one space in memory. They only have one space in memory since char *strB not initialized as like char *strA . Whether it can be considered as a automatic / dynamic space creation in memory? How the data stored?
Please enlightenment
Thank you :)
In both char strB[20]; and uninitialized char * strB, you'll face Undefined behaviour.
In the former case, you'll be writing past allocated memory.
In the later case, you'll try to access uninitialized memory.
However, as per the standard function comparison, my_strcpy() function behaviour is okay. If you want to add some preventive measure to your version of the code, consider at least adding a Check for NULL incoming pointer for both source and destination.
If
char *strA = "Awesome string! Yes it is G-String!";
char *strB;
works then it is undefined behvaior. strA is a string literal and is read-only.
Whereas strB is just a pointer and is not pointing to any valid memory location and accessing/writing unallocated memory is undefined behvaior.
it can be considered as a automatic / dynamic space creation in memory?
No, in none of your examples the function my_strcpy() allocates any memory for the destination "string".
It is undefined behavior.
char *strA = "Awesome string! Yes it is G-String!";// It is stored in a read only memory.
char *strB;// it is uninitialized pointer and not pointing to any where.
In first case,
char strB[20];
It is also a undefined behavior. first string length greater that twenty.
I think there is a misunderstood on function prototype.
Do you know why have you writing this line ?
char *my_strcpy(char *dst, char *src);
This is a function prototype, it says to the compiler:
you will see a function named my_strcpy(char *dst, char *src)
but, if you see you need it (see Subroutine) before I define
it don't worry, I explain later how it works.
So write a function prototype following by definition of this function is a nonsense.
You could remove the function prototype or you could keep prototype if you write this:
#include <stdio.h>
char *my_strcpy(char *dst, char *src);
int main(int argc, const char *argv[])
{
[...]
my_strcpy(strB, strA);
[...]
}
char *my_strcpy(char *dst, char *src)
{
[...]
}
Because the compiler read line by line, from the top to the bottom.
So when it will be in main() at line my_strcpy(strB, strA);, if you remove char *my_strcpy(char *dst, char *src); before main() compiler will say:
I don't kown any my_strcpy(arg1, arg2) function so I stop there.
I hope this can help you!

C function to swap two chars in a char[] segfaults, despite not working with string literals

I've verified in GDB that the program crashes on the *(a) = *(b) line. This does not make sense to me.
In my main function I allocated a 5 bytes for the char* string. I pass two pointers to swap, one is string offset by sizeof(char) and the other is the pointer to string. These pointers are copied to swap()'s call stack. The 5 bytes I allocated earlier should still be on the stack so swap() should have no problem with dereferencing and writing to those locations on stack, right?
int main(int argc, char* argv[])
{
char *string = "abcd";
swap((string+1), string);
printf("%s\n",string);
return 0;
}
void swap(char *a, char *b)
{
if(!a || !b)
return;
char temp = *(a);
*(a) = *(b);
*(b) = temp;
}
char *string = "abcd";
is a pointer to a string literal and string literals are immutable in C. Modifying a string literal invokes undefined behavior.
Change the declaration of string to:
char string[] = "abcd";
to fix you program. Here string is an array, initialized with the content of a string literal and is modifiable.
String literals like "abcd" are read only, you must not change them. Use
char string[] = "abcd";
instead.
you should use char string[] = "abcd";, becase string is inmuttable in char* string= "abcd";

Resources