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
Related
I just started to learn memory management in C, and I didn't understand something. I want to allocate memory to a buffer that holds 12 bytes. which is the exact size of Hello World! without null terminator.
Then I want to append a string to the current string with strcat, and of course I cannot do that because I will get core dumped error.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char mystr[12] = "Hello World!";
# allocate memory to mystr?
char *ptr = (char*) malloc(13 * sizeof(char));
strcat(mystr, "Hello");
return 0;
}
So, I don't know how can I allocate memory to the mystr variable if malloc doesn't take any other arguments except the target size.
I don't know how can I allocate memory to the mystr variable if malloc doesn't take any other arguments except the target size.
It is not possible to allocate extra memory to an array. Instead, what you want to do is allocate a new block of memory, copying the original string into the beginning of that memory (strcpy), then append the rest (strcat):
char *p = (char*) malloc((12 + 5 + 1) * sizeof(char));
strcpy(p, myptr);
strcat(p, "Hello");
12 for the first string, plus 5 for the second, plus one for the null-terminator.
Of course, since you know the final size, you could also simply allocate a big enough array instead of using malloc (and you can also use memcpy, too).
The problem should be that a string in C always end with a NULL character (also noted '\0'), so your string is actually 13 characters long. (That character is always automatically added with string literals and serves at telling where the string stops, because a string doesn't have a fixed length.)
So the strcat tries to read the string Hello world! followed by garbage (since the null-terminator is not included in the string).
P.S.: the error is not the core dumped but the Segmentation fault that precedes it, and this tells you that you are trying to change something in a segment you are not supposed to change (or execute/read something you are not supposed to -- this is a security feature).
Edit: after modifying the string mystr, you also need to change the length you allocate (in the malloc: use 13 * sizeof(char), or more simply here in this case sizeof(mystr)).
P.S. 2: also comments in C are started by //, not # (those are preprocessor directives).
you cant change the size of the array. mystr has to be also dynamically allocated.
int main(int argc, char const *argv[])
{
const char *ptr = "Hello World!";
const char *ptr2 = "hello";
char *mystr = malloc(strlen(ptr)+1);
strcpy(mystr, ptr);
mystr = realloc(mystr, strlen(mystr) + strlen(ptr2) + 1);
strcat(mystr, ptr2);
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;
}
This question already has answers here:
Difference between char[] and char * in C [duplicate]
(3 answers)
Closed 7 years ago.
I think I know the answer to my own question but I would like to have confirmation that I understand this perfectly.
I wrote a function that returns a string. I pass a char* as a parameter, and the function modifies the pointer.
It works fine and here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_file_name(char* file_name_out)
{
char file_name[12+1];
char dir_name[50+12+1];
strcpy(file_name, "name.xml");
strcpy(dir_name, "/home/user/foo/bar/");
strcat(dir_name, file_name);
strcpy(file_name_out, dir_name); // Clarity - equivalent to a return
}
int main()
{
char file_name[100];
get_file_name(file_name);
printf(file_name);
return 0;
}
But if I replace char file_name[100]; by char *filename; or char *filename = "";, I get a segmentation fault in strcpy().
I am not sure why ?
My function takes a char* as a parameter and so does strcpy().
As far as I understand, char *filename = ""; creates a read-only string. strcpy() is then trying to write into a read-only variable, which is not allowed so the error makes sense.
But what happens when I write char *filename; ? My guess is that enough space to fit a pointer to a char is allocated on the stack, so I could write only one single character where my file_name_out points. A call to strcpy() would try to write at least 2, hence the error.
It would explain why the following code compiles and yields the expected output:
void foo(char* a, char* b)
{
*a = *b;
}
int main()
{
char a = 'A', b = 'B';
printf("a = %c, b = %c\n", a, b);
foo(&a, &b);
printf("a = %c, b = %c\n", a, b);
return 0;
}
On the other hand, if I use char file_name[100];, I allocate enough room on the stack for 100 characters, so strcpy() can happily write into file_name_out.
Am I right ?
As far as I understand, char *filename = ""; creates a read-only
string. strcpy() is then trying to write into a read-only variable,
which is not allowed so the error makes sense.
Yes, that's right. It is inherently different from declaring a character array. Initializing a character pointer to a string literal makes it read-only; attempting to change the contents of the string leads to UB.
But what happens when I write char *filename; ? My guess is that
enough space to fit a pointer to a char is allocated on the stack, so
I could write only one single character into my file_name_out
variable.
You allocate enough space to store a pointer to a character, and that's it. You can't write to *filename, not even a single character, because you didn't allocate space to store the contents pointed to by *filename. If you want to change the contents pointed to by filename, first you must initialize it to point to somewhere valid.
I think the issue here is that
char string[100];
allocates memory to string - which you can access using string as pointer
but
char * string;
does not allocate any memory to string so you get a seg fault.
to get memory you could use
string = calloc(100,sizeo(char));
for example, but you would need to remember at the end to free the memory with
free(string);
or you could get a memory leak.
another memory allocation route is with malloc
So in summary
char string[100];
is equivalent to
char * string;
string = calloc(100,sizeo(char));
...
free(string);
although strictly speaking calloc initializes all elements to zero, whereas in the string[100] decalaration the array elements are undefined unless you use
string[100]={}
if you use malloc instead to grad the memory the contents are undefined.
Another point made by #PaulRooney is that char string[100] gives memory allocation on the stack whereas calloc uses the heap. For more information about the heap and stack see this question and answers...
char file_name[100]; creates a contiguous array of 100 chars. In this case file_name is a pointer of type (char*) which points to the first element in the array.
char* file_name; creates a pointer. However, it is not initialized to a particular memory address. Further, this expression does not allocate memory.
char *filename;
Allocate nothing. Its just a pointer pointing to an unspecified location (the value is whatever was in that memory previously). Using this pointer will never work as it probably points outside the memory range your program is allowed to use.
char *filename = "";
Points to a piece of the programs data segment. As you already said it's read only and so attempting to change it leads to the segfault.
In your final example you are dealing with single char values, not strings of char values and your function foo treats them as such. So there is no issue with the length of buffers the char* values point to.
I'm trying to figure out how to use malloc correctly in C, and have run into an error that I'm having trouble with.
My code:
#include <stdio.h>
#include <stdlib.h>
int main() {
char * str;
str = (char *)malloc(10);
str = "Hello World";
str[0] = 'R';
return EXIT_SUCCESS;
}
My Valgrind output:
==23136== Process terminating with default action of signal 10 (SIGBUS)
==23136== Non-existent physical address at address 0x100000F92
==23136== at 0x100000F66: main (test.c:12)
I know that the issue is due to me trying to allocate the letter 'R' to str, but I was under the impression that the advantage of using malloc in this situation (as opposed to char str[10] = "Hello World"), was the ability to edit the contents of my string.
Thanks!
str = "Hello World"; makes str point to a constant char string "Hello World", and the memory you have malloced will become memory leak.
You copy a string with strcpy from <string.h>, not by re-assigning a pointer.
But take care that the target buffer will actually hold strlen(source) + 1 characters (0-terminator). "Hello World" is 11+1.
Also, trying to modify that improperly assigned string literal is UB.
Anyway, Don't cast the result of malloc (and friends).
Finally, return EXIT_SUCCESS is superfluous (since C99 main has an implicit return 0; at the end).
You are throwing away the return value of malloc. Instead you are setting it to a value in read only memory
Try replacing
str = "Hello World";
with
strcpy(str, "Hello World");
You will need to include the appropriate header file
I have written the following program (it is given as an example in one of the best text books). When I compile it in my Ubuntu machine or at http://www.compileonline.com/compile_c_online.php, I get "segmentation fault"
The problem is with while( *p++ = *str2++)
I feel it is a perfectly legal program. Experts, please explain about this error.
PS: I searched the forum, but I found no convincing answer. Some people even answered wrong, stating that *(unary) has higher precedence than ++ (postfix).
#include <stdio.h>
#include <string.h>
int main()
{
char *str1= "Overflow";
char *str2= "Stack";
char *p = str1;
while(*p)
++p;
while( *p++ = *str2++)
;
printf("%s",str1);
return 0;
}
Thanks
str1 and str2 point to string literals. You aren't allowed to modify those. Even if you could, there isn't enough memory allocated for the string to hold the characters you're trying to append. Instead, initialize a sufficiently large char array from a string literal:
char str1[14] = "Overflow";
I feel it is a perfectly legal program.
Unfortunately, it is not. You have multiple, severe bugs.
First of all, you are creating pointers to string literals char *str1= "Overflow"; and then you try to modify that memory. String literals are allocated in read-only memory and attempting to write to them results in undefined behavior (anything can happen).
Then you have while(*p) ++p; which looks for the end of the string, to find out where to append the next one. Even if you rewrite the pointers to string literals into arrays, you don't have enough free memory at that location. You must allocate enough memory to hold both "Overflow" and "Stack", together with the string null termination.
You should change your program to something like this (not tested):
#include <stdio.h>
int main()
{
char str1[20] = "Overflow"; // allocate an array with enough memory to hold everything
char str2[] = "Stack"; // allocate just enough to hold the string "Stack".
char *p1 = str1;
char *p2 = str2;
while(*p1)
++p1;
while(*p1++ = *p2++)
;
printf("%s",str1); // should print "OverflowStack"
return 0;
}
Or of course, you could just #include <string.h> and then strcat(str1, str2).
Because you are crossing the string boundary of Overflow (str1) is why you are getting sigsegv.
str1 does not have enough memory allocated to accomodate beyond Overflow.