strcat function not working with pointers - c

int main(int argc , int *argv[]){
char str[7] = "Mobile";
char str2[11] = "Samsung4g";
char *str3 = 0;
str3 = ( char* )(malloc(30));
str3 = "Carrier";
strcat(str3, str);//Problem facing here, dunno why

Like what others have mentioned in the comments, the statement:
str3 = "Carrier";
overwrites the value of str3 with the address of the string literal "Carrier" causing the address returned by malloc() to be lost.
Using str3 then in strcat() as a first argument attempts to modify a string literal which results in undefined behaviour.
Use strcpy() or equivalent functions to copy strings in C.

Related

I am unable to use strtok over a char

I am unable to use strtok over char *a but on b its working.
Its working with malloc and array
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DELIM ":"
int main()
{
char *a = "xgdgsf: duh d";//unable to use strtok on it
char *token=NULL;
printf("%s",a);
char *b = malloc(strlen(a) + 1);
strcpy(b, a);//i can use strtko on it
token=strtok(b,DELIM);
printf("\n%s",token);
token=strtok(a,DELIM);
printf("\n%s",token);
return 0;
}
You have passed a to strtok which is a string literal. You can't do that because strtok modifies the string.
If you had defined the array as
const char *a = "xgdgsf: duh d";
then the compiler would give you a warning.
The second call to strtok should be
token=strtok(NULL, DELIM);
to extract the second token from b.
Change
char *a = "xgdgsf: duh d";
to
char *a = strdup("xgdgsf: duh d");
In C, string literals are read only. However, do remember that you need to free the pointer after calling strdup. Do it with free(a) when you are done with the string.
As others have pointed out, the problem is that a points to a string literal. strtok modifies its input (it overwrites the delimiters with a string terminator) and the behavior on attempting to modify a string literal is undefined - you may get a runtime error, the code may work as expected, or something else may happen. String literals are supposed to be immutable, but it's not guaranteed that they'll be stored in read-only memory.
There are several ways to resolve this. One is to declare a as an array and initialize it with the string:
char a[] = "xgdgsf: duh d";
Another is to dynamically allocate a buffer and copy the contents of the string to it:
char *a = malloc( strlen( "xgdgsf: duh d" ) + 1 );
if ( a )
strcpy( a, "xgdgsf: duh d" );
If it's available on your system, you can use the non-standard function strdup to do the same thing:
char *a = strdup( "xgdgsf: duh d" );
When declaring a pointer to a string literal, it's usually a good idea to qualify it as const:
const char *a = "xgdgsf: duh d";
that way the compiler will yak at you if you try to modify (assign to) *a or a[i] or pass it to a function that expects a plain char * as an input. That way mistakes like using strtok on a literal are caught at compile time, not runtime.

Segmentation fault in my strcpy

I'm writing my own strcpy due to the fact that the default one in string.h only accept a const char * as a source string to copy from.
I'm trying this very basic prototype (yes, the return isn't meaningful, I'm just trying things):
int copyStrings(char * dest, char * source){
int i=0;
while(source[i]!='\0'){
dest[i]=source[i];
i++;
}
dest[i]='\0';
return 0;
}
and it gives me SIGSEGV, Segmentation Fault error in gdb, at the line dest[i]=source[i], right at the first character. I'm pretty sure dest[i] isn't a string literal, so I should be able to modify it.
What am I doing wrong?
EDIT: here's the calling
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
This is assigning a string literal to str2 - the very thing that you claim you aren't doing. This is actually the cause of your segfault.
str2 = "hey jude";
It also is causing a memory leak as prior to this, you malloc'd some memory and assigned it to str2 as well. But not enough memory to hold the string. Typically an int is 4 bytes and you need 9 bytes to store that string.
What you want to do is this, which allocates as many bytes as there are in the string, plus an extra one to store the \0 terminating character at the end.
str2 = malloc(strlen("hey jude")+1);
strcpy(str2,"hey jude");
or on some systems you can use POSIX function strdup() which effectively does the job of the above in one handy function call.
str2 = strdup("hey jude");
Let's go at it line by line and see where it goes wrong:
int main(){
char * str = (char*)malloc((int)sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int));
str = "hello";
str2 = "hey jude";
copyStrings(str2, str);
free(str);
free(str2);
return 0;
}
int main(){ - this is an improper definition of main. Should be int main(int argc, char **argv)
char * str = (char*)malloc((int)sizeof(double)); - defines str, then allocates (probably) 8 bytes of memory and assigns its address to str. malloc takes a size_t argument, so the cast (int)sizeof(double) is incorrect. Also, in C the return value of malloc should never be cast. So this line should be char * str = malloc(sizeof(double));
char * str2 = (char *)malloc((int)sizeof(int)); - all the same problems as the preceding line. Should be char *str2 = malloc(sizeof(int));
str = "hello"; - causes a memory leak, because the memory you JUST ALLOCATED two lines earlier is now irretrievably lost. You've got two options here - either don't allocate the memory when defining str or free it first. Let's do the latter:
free(str);
str = "hello";
str2 = "hey jude"; - same problem, similar solution:
free(str2);
str2 = "hey jude";
copyStrings(str2, str); - here you're telling your routine to copy the constant string "hello" over the top of the constant string "hey jude". This will work fine on some systems, but will blow up on other systems. The question is in the treatment of the constant string "hey jude". If it's stored in modifiable memory the code will work just fine. If it's stored in memory which is marked as being unmodifiable, however, it will blow up. It seems that the latter is the case on your system. To fix this you probably want to go back to the previous line and change it to
str2 = malloc(20);
That's more memory than you'll need, but it will work just fine.
free(str); - you're attempting to free the constant string "hello", which is not dynamically allocated memory. This needed to be done prior to the assignment str = "hello";.
free(str2; - same problem as above. This needed to be done prior to the assignment str2 = "hey jude";.
} - correct
Best of luck.

Copy c-string char by char to dynamic char*

I have a const char* string, I want to copy that string character by character to dynamic `char*.
const char *constStr = "Hello world";
char *str = (char*) malloc(strlen(constStr)+1);
while(*constStr){
*str = *constStr;
constStr++;
str++;
}
printf("%s", str);
free(str);
The problem is that previous code just copies each character of constStr to only the first index of the str. I don't know why?
As others have pointed out, you are incrementing str pointer in each iteration, so you always end up printing the end of the string.
You can instead iterate over each character without incrementing the pointer. The following code worked for me:
const char *constStr = "Hello world";
int len = strlen(constStr);
char *str = (char *) malloc(len + 1);
int i;
for (i = 0; i <= len; ++i) {
str[i] = constStr[i];
}
printf("%s", str);
free(str);
Yes you didn't null terminate the string. That was the primary problem. To be more clear, it is not that you didn't nul terminate the string which is the problem but rather your use of them where a pointer to a nul terminated char array is expected is the problem. But even if you did there was significant amount of problems in the code.
You allocated the memory and the casted the return value of malloc which is unnecessary. void* to char* conversion is implicitly done.
malloc might not be able to service the request, it might return a null pointer. It is important to
check for this to prevent later attempts to dereference the null pointer.
Then you started copying - you copied everything except the NUL terminating character. And then you passed it to printf's %s format specifier which expects a pointer to a null terminated char array. This is undefined behavior.
The one position, in the str is uninitialized - beware that accessing uninitialized value may lead to undefined behavior.
Also there is another problem, From standard §7.22.3.3
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
Yes so is is the case here? No. when you called free(str) str is not pointing to the dynamically allocated memory returned by the malloc. This is again undefined behavior.
The solution always is to keep a pointer which stores the address of the allocated chunk. The other answers already showed them (without repeating them - both of them provides a good solution).
You can use strdup or strcpy also - even if you don't need them now - get accustomed with them. It helps to know those. And yes strdup is not part of standard, it is a POSIX standard thing.
Example:
const char *constStr = "Hello world";
char *str = malloc(strlen(constStr)+1);
if( !str ){
perror("malloc");
exit(EXIT_FAILURE);
}
char *sstr = str;
while(*constStr){
*str = *constStr;
constStr++;
str++;
}
*str = 0;
printf("%s", sstr);
free(sstr);
Here's the "classical" string copy solution:
const char *constStr = "Hello world";
char *str = malloc(strlen(constStr) + 1), *p = str;
/* Do not forget to check if str!=NULL !*/
while((*p++ = *constStr++));
puts(str);
The problem is that previous code just copies each character of
constStr to only the first index of the str. I don't know why?
Use index variable.
Don't forget terminating '\0' because you have a good chance of segmentation fault.

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";

Runtime error while doing string concatenation

What is the problem with the below program?
main( )
{
char *str1 = "United" ;
char *str2 = "Front" ;
char *str3 ;
str3 = strcat ( str1, str2 ) ;
printf ( "\n%s", str3 ) ;
}
I am not able to compile the above program and it always give me runtime error. I am trying to concatenate the two string. Is there any error in the above program?
Thanks.
Make your char *str1 = "United" as
char str1[<required memory for concatenated resultant string>] = "United".
You need to allocate memory for the destination buffer which is str1. str3 will also receive address of str1 in the result. 'strcat' will not check for space availability in destination buffer (str1). Programmer has to take care of it.
You are trying to modify a string literal, but your compiler (and runtime support) won't let you. When you do so, you are invoking 'undefined behaviour', which is a Bad Thing!™ Anything could happen; it is legitimate for the program to crash. Avoid undefined behaviour.
You need to allocate enough (writable) memory for the strings, maybe like this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *str1 = "United";
char *str2 = "Front";
char str3[64];
strcpy(str3, str1);
strcat(str3, str2);
printf("%s\n", str3);
return(0);
}
When you declare char *str = "someText", basically, you initialize a pointer to a string constant which can't be changed, and is located somewhere in your computer's memory.
After that by using the function strcat() you are trying to change that string constant, which we said is constant -
Such behavior compiles with no errors, but will cause your program to crash during runtime since const (constant) works during runtime and is not precompiled like #define.
A different solution for you might be,
#include<stdio.h>
#include<string.h>
int main(void) {
char* str1 = "Hello,";
char* str2 = " World";
char str3[30];
strcpy(str3, str1);
strcat(str3, str2);
printf("%s\n", str3);
printf("\n\n\n");
return 0;
}
Hope that helps!
Best of luck in the future!

Resources