Why is this usage of memset() segfaulting? - c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *str = "This is a string!";
int therealthing = sizeof(str[0]) * 4;
memset(str, 'b', therealthing);
printf("%s\n", str);
return 0;
}
This code causes a segfault, any ideas why?
I have already tried passing it as a memory address and as a pointer.

This is a string literal. It's immutable. Can't be changed.
char *str = "This is a string!";
You're trying to change it with memset. You could use an array of characters
char str[] = "This is a string!";
or
char * str = malloc(sizeof(char) * (strlen("This is a string!") + 1));
strcpy(str, "This is a string!");

You can't modify a string literal. It will invoke undefined behavior.
Try this instead
char str[] = "This is a string!";

Related

Change pointer of pointer in C

I'm trying to write a void function that gets a pointer to a pointer of a string (char**) as a parameter, and changes the original char* so it pointed to another string, lets say "hello".
Below is the code I've written:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void change_ptr(char **str_ptr)
{
char hello[] = "hello";
char *hello_ptr = hello;
*str_ptr = hello_ptr;
}
int main()
{
char str[] = "yay";
char *str_ptr = str;
char **ptr_to_str_ptr = &str_ptr;
change_ptr(ptr_to_str_ptr);
printf("%s\n", str);
return 0;
}
As you can see, Im getting the pointer to the pointer of the char* "yay", delivering it to the function, and in the function I'm getting the pointer to "hello", and changes *str_ptr (which is the pointer to the original string) to the pointer to hello. But when I print str at the end, it prints "yay".
What am I doing wrong?
(when I debug with printing the addresses, everything seems fine.)
This works:
#include <stdio.h>
void change_ptr(const char ** str_ptr)
{
*str_ptr = "hello";
}
int main()
{
char str[] = "yay";
const char * str_ptr = str;
const char ** ptr_to_str_ptr = &str_ptr;
change_ptr(ptr_to_str_ptr);
printf("%s\n", str_ptr);
}
Note that the string "hello" in this example is read-only because it is a string literal. I added const in a few places so you are reminded of this and the compiler will warn you if you try to write to the string. The pointer str_ptr can be modified, but not the string itself.

"initializer element is not constant char" error in C

Here is my code:
#include <stdio.h>
#include<stdlib.h>
char *s = (char *)malloc (40);
int main(void)
{
s="this is a string";
printf("%s",s);
}
I am getting the following error:
error: initializer element is not constant char *s = (char *)malloc
(40);
You don't need to allocate memory in this way if you wanna initialize it in code, I mean:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *s = "this is a string"; // char s[] = "this is a string";
printf("%s",s);
return 0;
}
is just enough in this case. If you really want to assign const char string to your char array, this topic should enlighten you: Dynamically allocating memory for const char string using malloc()
You cannot not do that.
You can do this instead -
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
char *s; // probably should avoid using global variables
int main(void)
{
s=malloc(40);
strcpy(s,"this is a string");
printf("%s",s);
free(s);
}
Other than this inside main you can do this -
char *s="this is a string"; //string literal you can't modify it
Or
char s[]="this is a string"; // modifiable string
You assign a pointer to a string constant to a variable, s, which is not declared to point to a constant. This is what you want:
#include <stdio.h>
int main(void)
{
const char *s = "this is a string";
printf("%s\n", s);
return 0;
}
In C there are basically three ways to declare "string" variables.
String constant pointers
If you need a name for a string that will not change, you can declare and initialize it like
const char *s = "a string";
Character arrays
If you need a string variable and you know in advance how long it needs to be you can declare and initialize it like
char s[] = "a string";
or like
char s[9];
strcpy(s, "a string");
Character sequence pointers
If you don't know in advance how large the array needs to be, you can allocate space during program execution:
char *s;
s = malloc(strlen(someString) + 1);
if (s != NULL) {
strcpy(s, someString);
}
The "+1" is to make room for the null character (\0).

Copying the string of pointer to other pointer

Folks,
I have basic and simple question on pointers. The below is code is giving a segmentation fault.
int main()
{
char *str = "hello, world\n";
char *strc = "good morning\n";
strcpy(strc, str);
printf("%s\n", strc);
return 0;
}
Can't we copy from pointer to other.
if i have char *strc = "good morning\n", can't i do like this
strc[5] = '.';. Why this also giving a seg fault.
You may not change string literals. It is what you are trying to do in statement
strcpy(strc, str);
that is you are trying to overwrite string literal "good morning\n" pointed to by pointer strc.
Of cource you may use pointers in function strcpy. The valid code can look like
#include <stdio.h>
#include <string.h>
int main()
{
char *str = "hello, world\n";
char strc[] = "good morning\n";
strcpy(strc, str);
printf("%s\n", strc);
return 0;
}
Or
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char *str = "hello, world\n";
char *strc = malloc( 14 * sizeof( char ) );
strcpy( strc, "good morning\n" );
//...
strcpy(strc, str);
printf("%s\n", strc);
free( strc );
return 0;
}

strcpy function: C

I am trying to implement
void strcpyy(char *s, char *t){
while(*s++ = *t++){
}
}
which is an example from K&R. The implementation should be fairly easy but for some reason, that is not the case for me at the moment. So I have the following
int main(){
char *mess = "hello world";
char *mess = (char *) malloc(strlen(mess) + 1);
char *aess;
strcpyy(aess, mess);
printf("%s", aess);
return 0;
}
Every time I run the program, I keep on getting a big list of errors each time I run with -Wall. I would think that to implement and use strcpyy, you would have to malloc space to copy the string and once you do so, you should be able to print out aess which theoratically should contain a copy of mess. Any help would be much appreciated!
It is always a good practice to pay attention to the error messages, especially to the first message (others often are the consequences of the first error). The error message surely indicated the line number corresponding to the line with malloc, and most probably told you what's the problem there.
Correct your program to read:
char *mess = "hello world";
char *aess = (char *) malloc(strlen(mess) + 1);
or the complete function is:
int main(){
char *mess = "hello world";
char *aess = (char *) malloc(strlen(mess) + 1);
strcpyy(aess, mess);
printf("%s", aess);
return 0;
}
The problem is that your line
char *mess = (char *) malloc(strlen(mess) + 1);
overwrites the first line
char *mess = "hello world";
and the line
char *aess;
leaves the variable unassigned.
The compile error is because the compiler cannot choose between
char *mess = "hello world";
and
char *mess = (char *) malloc(strlen(mess) + 1);
which introduce a new variable each but with the same name.
The program will look the following way
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void strcpyy( char *s, const char *t )
{
while ( *s++ = *t++ );
}
int main( void )
{
char *t = "hello world";
char *s = ( char * )malloc( strlen( t ) + 1 );
strcpyy( s, t );
printf( "%s\n", s );
free( s );
return 0;
}
change
char *mess = "hello world";
char *mess = (char *) malloc(strlen(mess) + 1);
char *aess;
to
char *mess = "hello world";
char *aess = malloc(strlen(mess) + 1);
mess is a string literal, which is hold in read-only memory. you were overwriting it and losing string that you wanted to copy. you need to assign some space for place where you want to copy characters, in your case aess variable. also, remember to free(aess); at the end of your program. if not, you'll get memory leaks.
why are you declaring and defining mess two times? never declare two variables with the same name if they have the same scope ,by doing this you confuse the compiler;
I'd recommed using strdup like this :
int main(){
char *mess = strdup("hello world");
char *aess;
strcpyy(aess, mess);
printf("%s", aess);
return 0;
}
or just a plain array like this
int main(){
char mess[] = "hello world";
char *aess;
strcpyy(aess, mess);
printf("%s", aess);
return 0;
}

Why char value copy won't work in OS X?

It's a textbook C code
void strcpy_new(char *s, char *t) {
while ((*s = *t) != '\0') {
s++;
t++;
}
}
int main(int argc, const char * argv[])
{
char *s = "this is line a";
char *t = "this is line b";
printf("%s", s);
strcpy_new(s, t);
printf("%s", s);
return 0;
}
when I run it with Xcode, I got EXEC_BAD_ACCESS.
The reason you get EXEC_BAD_ACCESS is because those string literals "this is line a" and "this is line b" are stored in read-only memory. Attempting to write to it (*s = *t) is undefined behavior and you are receiving a crash because of it.
To remedy this code you should allocate some memory for s so that it is large enough to hold the second string (t):
char s[] = "this is line a"; // contrived example, s and t are the same length
char *t = "this is line b";
strcpy_new(s, t);
I'm willing to bet that you're trying to run strcpy_new with a destination char *s that is a string literal
#include <string.h>
int main(int argc, char *argv[])
{
char *a = "Some String";
char *b = "Another string";
strcpy(b, a);
return 0;
}
will give an EXEC_BAD_ACCESS. The following, however, won't
#include <string.h>
int main(int argc, char *argv[])
{
char *a = "Some String";
char b[] = "Another string";
strcpy(b, a);
return 0;
}
The difference is that in the first case, b points to a block of memory in the __TEXT,__cstring,cstring_literals section of the executable, which is write protected. In the second case, it points to a block of memory on the stack.
The problem is that the effect of overwriting a string literal is undefined.
char *s = "this is line a";
char *t = "this is line b";
strcpy_new(s, t);
s and t are both off in the data section of the code, and your particular setup happens to give you an EXEC_BAD_ACCESS when you try changing them.
String literal are read-only. A good answer is found here: http://ubuntuforums.org/showthread.php?t=357869
String literals in C are read-only. In your sample code, "My string" is a string literal.
The str[] declaration copies the literal into writable memory (stack or heap). Therefore, your program can modify the string.
The * declaration initializes a pointer to the literal itself, so you have a pointer to a read-only segment. If you try to overwrite it, you get the SEGV.

Resources