strcpy pass initialized null pointer c [duplicate] - c

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 6 years ago.
I'm trying out the following code:
int main()
{
char *yo = "yo";
char *whaddup = NULL;
strcpy(whaddup,yo);
}
and I get a segfault. Complete C noob here - other places say I should initialize whaddup as an array. Why can't I pass in a pointer to null?

Just any strcpy documentation will tell you that the destination string should be a char array large enough to hold the string and the NUL terminator.
So what you need is something like
char* yo = "yo";
char* whaddup = malloc(strlen(yo)+1);
strcpy(whaddup, yo);
Or alternatively you could use strdup function which does this for you, but it's not standard as it's POSIX only.

You have to either declare whaddup as a character array or ideally allocate space for it with malloc.
int main()
{
char *yo = "yo";
char *whaddup = malloc(sizeof(char) * 8); // buffer for 8 characters
strcpy(whaddup,yo);
}
By initializing whaddup to NULL you are not giving it any space in memory, so even copying one character into it will result in a segmentation fault.

You can pass in a pointer to null, but you can not copy string from pointer to null.
The function char* strcpy(char* dest, const char* src) is copy string from address src to address dest, your dest is null.

Related

Why doesn't fgets take a char pointer as the first argument? [duplicate]

This question already has answers here:
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 1 year ago.
Why does fgets segfault when I pass a char pointer as the first argument? For example:
char *p;
fgets(p, 10, stdin); // segmentation fault
What's with the char pointer p, when we just declare it as char *p (as in the above example)?
thanks!
p contains a garbage value. You need to initialize it first.
char *p = (char*)malloc(10);
if (p == NULL) {
// handle error
}
//use p
// Once you're done with p
free(p);
or
char p[10]; // Automatic storage
Pointer p must point to a buffer.
char buf[10];
char *p = buf;
fgets(p, 10, stdin);
should work now. Note that array expressions decays to pointers so the code could be simpified to:
char p[10];
fgets(p, 10, stdin);
fgets can and does take a valid pointer to a character buffer as the first argument. In your case, your char *p is not valid. It has not been initialised and probably points to a junk value.
You can either initialise it to a static string or a character array which contains some sensible value.
Here p is just a pointer and it doesn't point to anything since it has not been initialized yet. You can initialize it via allocating memory to it.
char *p = (char*)malloc(10);

String with Variables Concatenation Issue [duplicate]

This question already has answers here:
How can I correctly assign a new string value?
(4 answers)
Closed 1 year ago.
#include<stdio.h>
int main() {
char R_FPD[] = "+00393E33mm/go";
char R_FPH[] = "+00393E33mm/go";
char R_Vel[] = "+00393E33mm/go";
char R_Tot[] = "+00393E33mm/go";
char str_msg[] = "{"+"flow_rate_per_day"+":"+R_FPD+","+"flow_rate_per_hour"+":"+R_FPH+","+"velocity"+":"+R_Vel+","+"totalizer"+":"+R_Tot+"}";
printf("%s", str_msg);
return 0;
}
i want to make it like a json object but its not working
Arrays in C decay to pointers to their first elements and adding pointers is not defined in C standard.
The simplest way to concatenate string like this is using sprintf function. It works like printf but it prints into a C-string.
In your case the pattern could be following:
char str_msg[BIG_ENOUGH];
sprintf(str_msg, "{flow_rate_per_day:%s,flow_rate_per_hour:%s,velocity:%s,totalizer:%s}", R_FPD,R_FPH,R_Vel,R_Tot);
BIG_ENOUGH should be larger then the longest string that can be formed. 256 should be enough in your case.
Alternatively you can use asprintf function that will automatically allocated a buffer of the right size. Remember to use free when the buffer is no longer needed.
char *str_msg;
asprintf(&str_msg, "{flow_rate_per_day:%s,flow_rate_per_hour:%s,velocity:%s,totalizer:%s}", R_FPD,R_FPH,R_Vel,R_Tot);
... use str_msg
free(str_msg);

Why the difference between char* and char[x] matter when using the & operator [duplicate]

This question already has answers here:
Pointer to Integer Array versus Double Pointer to Integer
(3 answers)
Is an array name a pointer?
(8 answers)
Why should I always enable compiler warnings?
(20 answers)
Closed 3 years ago.
The following code will segfault.
char* input = "12.34"; //< this is only to simplify the example.
char buffer[30] = { 0 };
memcpy(buffer, input, strlen(input));
char* part1 = strsep(&buffer, ".");
The following code will not.
char* input = "12.34"; //< this is only to simplify the example.
char buffer[30] = { 0 };
memcpy(buffer, input, strlen(input));
char* ptr = buffer; //< Only diff.
char* part1 = strsep(&ptr , ".");
When passed by reference (&) as a function argument, why does the difference between char** and char*[30] matter?
If you look at the man for strsep, it needs the double pointer because it tries to assign the pointer.
"char *strsep(char **stringp, const char *delim);
...
and *stringp is updated to point past the token"
Basically if you have an array, you can't just tell the head of the array to be in a new place. You can however make a pointer to any element in that array and then change the value of the pointer (thereby making it point to a different element if you so wish).

char* leads to segfault but char[] doesn't [duplicate]

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.

recursive strcpy function [duplicate]

This question already has answers here:
Access violation when using strcpy?
(8 answers)
Closed 9 years ago.
#include <stdio.h>
char *strcpy_r(char* s, char* t);
int main()
{
char *s = {"Bob"};
char *t = {"Billy"};
char *ptr;
ptr = strcpy_r(s, t);
printf("%s\n", ptr);
return 0;
}
char* strcpy_r(char* s, char* t)
{
if((*s = *t) != '\0')
strcpy_r(s + 1, t + 1);
return s;
}
I'm just doing this for practice, but when I compiled it. I got a seg fault from main. Could someone tell me what might've caused this seg fault?
Congratulations, you have invoked undefined behavior twice within one line.
First, you can't modify the contents of a string literal. So strcpy()ing onto "foo" is wrong.
Two, even if you could: you're copying a string to a buffer that is shorter than the string. This is UB again.
You are trying to modify a constant string. This is wrong! Chances of segfault live when you modify a constant string.
Instead do this:
char s[10] = "Bob";
char t[10] = "Billy";
char *ptr;
You can't overwrite the memory that's used to hold a quoted string. That'll segfault instantly.
String literals are constant, i.e. they cant change. You're also trying to copy a longer string into a shorter string, which will write beyond the bounds of the destination string.
Both of these problems leads to undefined behavior which can cause a crash.
To solve the first problem, you have to use an array for the destination string. To solve the other problem, you have to make sure the destination array is at least as large as the source string (including its terminating '\0').

Resources