Suppose I do like this to copy the string.
char str[] = "";
char *str2 = "abc";
strcpy(str, str2);
printf("%s", str); // "abc"
printf("%d", strlen(str)); // 3
Then, why it doesn't give me undefined behaviour or causing the program to fail. What are the disadvantages of doing like that ?
You are writing past the memory space allocated to str on the stack. You need to make sure you have the correct amount of space for str. In the example you mentioned, you need space for a, b, and c plus a null character to end the string, so this code should work:
char str[4];
char *str2 = "abc";
strcpy(str, str2);
printf("%s", str); // "abc"
printf("%d", strlen(str)); // 3
This code is definitely causing a stack problem, though with such a small string, you are not seeing the issue. Take, for example, the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char str[] = "";
char *str2 = "A really, really, really, really, really, really loooooooooooooooonnnnnnnnnnnnnnnnng string.";
strcpy(str, str2);
printf("%s\n", str);
printf("%d\n", strlen(str));
return 0;
}
A contrived example, yes, but the result of running this is:
A really, really, really, really, really, really loooooooooooooooonnnnnnnnnnnnnnnnng string.
92
Segmentation fault
This is one of the reasons why the strcpy function is discouraged, and usage of copy and concatenate functions that require specifying the sizes of the strings involved are recommended.
It actually gives you undefined behavior, but your program doesn't have to fail because of that. That's how undefined behavior works.
Related
I have read the documentation of strcat() C library function on a few websites.
I have also read here: Does strcat() overwrite or move the null?
However, one question is still left - can strcat() function be used to override the characters in the destionation string (assume that dest string has enough space for the source string, so there will be no errors)?
I ran the following code and found that it doesn't have the ability to override the dest string's characters...
char dest[20] = "Hello World";
char src[] = "char";
strcat(dest+1, src);
printf("dest: %s", dest);
Assume that the goal is to have a destination string that contains: "Hchar World!"
(I know that strcat() also copies the NULL characters('\0') to the dest string, so if printf() function is called, it should print Hchar, as I mistakenly thought would happen...).
Is that a possible task to do with strcat()? If not, is strcpy() the answer to the question?
If there is an assignment of '\0' (NULL character) in the middle of the string, for example, will strcat() always treat the first '\0' (NULL character) it meets? I mean, If I had:
char str[] = "Hello";
str[2]= 0;
strcat(str, "ab");
I just want to be sure and clarify the misunderstanding. I will be glad to read explanations.
As noted in the comments, the strcat function will always (attempt to) append the string given as its second argument (traditionally called src) to that given as its first (dest); it will produce undefined behaviour if either string is not null-terminated or if the destination buffer is not large enough.
The cppreference site gives better documentation (for both C and C++) than the website you linked. From that site's strcat page:
(1) … The character src[0] replaces the null terminator at the
end of dest. The resulting byte string is null-terminated.
And:
Notes
Because strcat needs to seek to the end of dest on each call, it is inefficient to concatenate many strings into one using strcat.
So, in the code you show, calling strcat(dest+1, src); has the same effect as calling strcat(dest, src);. However, calling strcpy(dest+1, src); will produce the result you want (printing Hchar).
strcat will write src string at the end of dst.
If you want to override dst with strcat, you first need to make dst "end" where you want to override it.
Take a look at this code sample:
#include <stdio.h>
#include <string.h>
int main()
{
char dst[20] = "Hello world";
char src[] = "char";
dst[1] = '\0';
strcat(dst, src);
printf("%s\n", dst);
return (0);
}
However, this is not the aim of strcat, and as said in the comments, the use of strcpy would be more appropriate here.
#include <stdio.h>
#include <string.h>
int main()
{
char dst[20] = "Hello world";
char src[] = "char";
strcpy(dst + 1, src);
printf("%s\n", dst);
return (0);
}
I have the following simple program which creates a pointer to the first character of a string:
char str[] = "Hello world";
char *p = &str[0];
How can I then get this string back into a variable using only the pointer?
Dereferencing the pointer just gives the first character of the string - as somewhat expected - so I'm assuming that there is no 'simple' way to achieve this and it will instead require writing extra code.
The current way I would approach this would be as follows:
Iterate from the pointer until a null terminator is reached to find the length of the string
Create a new char array with this length
Iterate through again inserting characters into this array
Is there a library function to achieve this, or if not, a simpler way that doesn't involve iterating twice?
Yes you have to "do it by hand". Because there are no objects in C - you need to take care of all that happens in the code.
You can use malloc, strlen and memcpy:
char str[] = "Hello world";
char *p = malloc(strlen(str) + 1);
if (!p) { abort(); }
memcpy(p, str, strlen(str) + 1);
You can use strcpy and forget about one strlen:
char *p = malloc(strlen(str) + 1);
if (!p) { abort(); }
strcpy(p, str);
Or you can use strdup from POSIX or a C extension:
char *p = strdup(str);
if (!p) { abort(); }
...
Is there a library function to achieve this, or if not, a simpler way that doesn't involve iterating twice?
As said in comment, strdup() will do exactly what you want. But here there is another problem (by your point of view): strcpy() will iterate the string twice, because there is no other way to duplicate a string.
By definition, strings in C are a sequence of characters somewhere in memory, with the last one character being a NUL (with single L), the value 0 (in a char). References to strings are pointers to the first character in the sequence depicted above. Note that two different strings can point to the same memory (they are not so different then...), or a string can point into the middle of another. These two cases are somewhat particular but not uncommon. The memory for strings must be managed by the programmer, who is the only one to know where allocate and deallocate space for strings; functions like strcpy() do nothing special in this regard, they are (presumably) well written and optimized, so maybe to copy a string the behavior is not plain as I depicted it before, but the idea is the same.
try this code:
#include "stdio.h"
int main(){
char str[] = "Hello world";
int count = 12;
char (*p)[12] = &str;
printf("%c\n",(*p)[0]);
printf("%c\n",(*p)[1]);
printf("%c\n",(*p)[2]);
printf("%c\n",(*p)[3]);
printf("%s\n",(*p));
}
Here's how I would make a copy of a string using only the standard library functions:
#include <stdio.h> // printf
#include <stdlib.h> // malloc
#include <string.h> // strcpy
int main(void)
{
char str[] = "Hello world"; // your original string
char *p = (char *)malloc(strlen(str) + 1); // allocate enough space to hold the copy in p
if (!p) { // malloc returns a NULL pointer when it fails
puts("malloc failed.");
exit(-1);
}
strcpy(p, str); // now we can safely use strcpy to put a duplicate of str into p
printf("%s\n", p); // print out this duplicate to verify
return 0;
}
All of the code below on C.
Both the code snippet below are compiled, but the difference is that the second program crashes at startup.
One:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str[80];;
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
Two:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str="";
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
The difference is that in the first case, said the size of the str string, while the second is not. How to make string concatenation without a direct indication of the size of the string str?
The difference is that in the first case, said the size of the str
string, while the second is not.
No. In the first program, the following statement
char *str[80];
defines str to be an array of 80 pointers to characters. What you need is a character array -
char str[80];
In the second program,
char *str="";
defines str to be a pointer to the string literal "", not an array. Arrays and pointers are different types.
Now, the second program crashes because
char *str="";
defines str to be a pointer to a string literal. The first argument of strcpy should be a pointer to a buffer which is large enough for the string to be copied which is pointed to by its second argument.
However, str points to the string literal "" which is allocated in read-only memory. By passing str to strcpy, it invoked undefined behaviour because strcpy tries to modify it which is illegal. Undefined behaviour means the behaviour is unpredictable and anything can happen from program crash to due to segfault (illegal memory access) or your hard drive getting formatted. You should always avoid code which invoked undefined behaviour.
How to make string concatenation without a direct indication of the
size of the string str?
The destination string must be large enough to store the source string else strcpy will overrun the buffer pointed to by its first argument and invoke undefined behaviour due to illegal memory access. Again, the destination string must have enough space for the source string to be appended to it else strcat will overrun the buffer and again cause undefined behaviour. You should ensure against this by specifying the correct size of the string str in this case.
Change to:
One:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
Two:
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char str[80]="";
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
}
#include <stdio.h>
#include <string.h>
void main() {
char *foo = "foo";
char *bar = "bar";
char *str=NULL;
size_t strSize = strlen(foo)+strlen(bar)+strlen("TEXT ")+1;
str=malloc(strSize);
if(NULL==str)
{
fprintf(stderr, "malloc() failed.\n");
goto CLEANUP;
}
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
CLEANUP
if(str)
free(str);
}
size_t len1 = strlen(first);
size_t len2 = strlen(second);
char * s = malloc(len1 + len2 + 2);
memcpy(s, first, len1);
s[len1] = ' ';
memcpy(s + len1 + 1, second, len2 + 1); // includes terminating null
Did I do good?
In the second version you have set char *str=""; this is equivalent to allocating an empty string on the stack with 1 byte which contains null for end of string. Had you written char*str="0123456789", you would have allocated 11 bytes on the stack the first 10 of which would have been "0123456789" and the 11th byte would have been null. If you try to copy more than allocated bytes to the str, your program might crash. So either allocate dynamically enough memory, or statically.
Both programs are wrong, the first provokes undefined behavior exactly as the second one.
char *str[80]; is array of pointers which you pass to functions ( strcpy, strcat) as first argument, while the first argument for those functions should be char *. Possible solution for this issue to define str as char str[80];
The issue with the second program is that char *str=""; is a pointer to read only piece of memory, which can't be changed.In this case one of possible solutions can be :
char* str = malloc(80);
strcpy(str,"");
strcpy (str, "TEXT ");
strcat (str, foo);
strcat (str, bar);
You'll have to allocate memory before copying. The first defines the size so as 80
char *str = new char[10]; could also be a method of allocation. malloc function could also be used to allocate memory.
Here are some references that might help you
http://www.cplusplus.com/reference/cstdlib/malloc/
http://www.cplusplus.com/reference/cstdlib/calloc/
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!
Below is my code
#import <stdio.h>
#import <string.h>
int main(int argc, const char *argv[])
{
char *str = "First string";
char *str2 = "Second string";
strcpy(str, str2);
return 0;
}
It compiles just fine without any warning or errors, but when I run the code I get the error below
Bus error: 10
What did I miss ?
For one, you can't modify string literals. It's undefined behavior.
To fix that you can make str a local array:
char str[] = "First string";
Now, you will have a second problem, is that str isn't large enough to hold str2. So you will need to increase the length of it. Otherwise, you will overrun str - which is also undefined behavior.
To get around this second problem, you either need to make str at least as long as str2. Or allocate it dynamically:
char *str2 = "Second string";
char *str = malloc(strlen(str2) + 1); // Allocate memory
// Maybe check for NULL.
strcpy(str, str2);
// Always remember to free it.
free(str);
There are other more elegant ways to do this involving VLAs (in C99) and stack allocation, but I won't go into those as their use is somewhat questionable.
As #SangeethSaravanaraj pointed out in the comments, everyone missed the #import. It should be #include:
#include <stdio.h>
#include <string.h>
There is no space allocated for the strings. use array (or) pointers with malloc() and free()
Other than that
#import <stdio.h>
#import <string.h>
should be
#include <stdio.h>
#include <string.h>
NOTE:
anything that is malloc()ed must be free()'ed
you need to allocate n + 1 bytes for a string which is of length n (the last byte is for \0)
Please you the following code as a reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
//char *str1 = "First string";
char *str1 = "First string is a big string";
char *str2 = NULL;
if ((str2 = (char *) malloc(sizeof(char) * strlen(str1) + 1)) == NULL) {
printf("unable to allocate memory \n");
return -1;
}
strcpy(str2, str1);
printf("str1 : %s \n", str1);
printf("str2 : %s \n", str2);
free(str2);
return 0;
}
str2 is pointing to a statically allocated constant character array. You can't write to it/over it. You need to dynamically allocate space via the *alloc family of functions.
string literals are non-modifiable in C
Your code attempts to overwrite a string literal. This is undefined behaviour.
There are several ways to fix this:
use malloc() then strcpy() then free();
turn str into an array and use strcpy();
use strdup().
this is because str is pointing to a string literal means a constant string ...but you are trying to modify it by copying .
Note : if it would have been an error due to memory allocation it would have been given segmentation fault at the run time .But this error is coming due to constant string modification or you can go through the below for more details abt bus error :
Bus errors are rare nowadays on x86 and occur when your processor cannot even attempt the memory access requested, typically:
using a processor instruction with an address that does not satisfy
its alignment requirements.
Segmentation faults occur when accessing memory which does not belong to your process, they are very common and are typically the result of:
using a pointer to something that was deallocated.
using an uninitialized hence bogus pointer.
using a null pointer.
overflowing a buffer.
To be more precise this is not manipulating the pointer itself that will cause issues, it's accessing the memory it points to (dereferencing).
Let me explain why you do you got this error "Bus error: 10"
char *str1 = "First string";
// for this statement the memory will be allocated into the CODE/TEXT segment which is READ-ONLY
char *str2 = "Second string";
// for this statement the memory will be allocated into the CODE/TEXT segment which is READ-ONLY
strcpy(str1, str2);
// This function will copy the content from str2 into str1, this is not possible because you are try to perform READ WRITE operation inside the READ-ONLY segment.Which was the root cause
If you want to perform string manipulation use automatic variables(STACK segment) or dynamic variables(HEAP segment)
Vasanth
Whenever you are using pointer variables ( the asterix ) such as
char *str = "First string";
you need to asign memory to it
str = malloc(strlen(*str))
None of the mentioned solution, worked for me as I couldn't find where the error was coming from. So, I simply deleted my node_modules and re-installed it. And the error disappeared; my code started working again