Using strcat inside another function: Segmentation fault (core dumped) - c

static void foo(unsigned char *cmd)
{
strcat(cmd, "\r\n");
printf("\r\nfoo: #%s#", cmd);
}
int main()
{
foo("test");
return 0;
}
Compiler says Segmentation fault (core dumped)
What is the actual problem here?

You have undefined behaviour. You are not allowed to modify string literals. cmd points to a string literal and strcat() attempts concatenate to it, which is the problem.
int main(void)
{
char arr[256] = "test";
foo(arr);
return 0;
}
You generally need to be careful when using strcpy() and strcat() etc in C as there's a possibility that you could overflow the buffer.
In my example, I used an array size of 256 which is more than enough for your example. But if you are concatenating something of unknown size, you need to be careful.

In C string literals (like "test") are read-only arrays of characters. As they are read-only they can't be modified. As they are arrays they have a fixed size. You both try to modify the string literal, and extend it.

You are trying to append something to the string literal test which cannot be modified. It's undefined behaviour.
You want this:
static void foo(unsigned char *cmd)
{
strcat(cmd, "\r\n");
printf("\r\nfoo: #%s#", cmd);
}
int main()
{
char test[50] = "test";
foo(test);
printf("test after calling foo: %s\n", test);
return 0;
}

Other people have explained why you cannot do this operation in place.
You have basically two options:
Either you modify the string in place (with realloc() to allow you to add your suffix ("\r\n"). But you have to be careful and use a malloc allocated data.
Otherwise, allocate a new string of the size of the input, plus the size of your suffix, and copy the input string and the prefix there, and return it. In that case, the caller will need to free() the returned string (and possibly the one passed to the function, but this would have been handled eitherway).
Edit: if you use a statically allocated buffer, you'll probably have to add an additional parameter to the function indicating the size of the buffer available.

To work with I changed the program like:
static void foo(unsigned char *cmd)
{
unsigned char local[10];
strcpy(local, cmd);
strcat(local, "\r\n");
printf("\r\nfoo: #%s#", local);
}
int main()
{
foo("test");
return 0;
}

Related

Getting seg fault when trying to decrement my environment variable in C

Total C noob here. I know there is something wrong with my sprintf_wrapper method because before I introduced it everything was working fine. The point of the function is to take a string buffer and a number and change the string buffers value to "WHALE=[num]". I then use this new string with putenv method.
The code results in "Segmentation fault (core dumped)", I believe it occurs after sprintf_wrapper is called.
Main Method
int main(void) {
getP0Info();
putenv("WHALE=7");
forkProcesses();
int whale = atoi(getenv("WHALE"));
char new_env[50];
sleep(1);
printf("P0: %d\n", whale);
whale = whale - 1;
sprintf_wrapper(new_env, whale);
putenv(new_env);
return 0;
}
sprintf_wrapper
void sprintf_wrapper(char* str, int num) {
char buffer[10];
str = "WHALE=";
sprintf(buffer,"%d", num);
strcat(str,buffer);
}
You're assigning a string constant to the str variable, then attempting to to append to it. Because string constants typically live in read only memory, this commonly causes a core dump.
Do this instead:
void sprintf_wrapper(char* str, int num) {
sprintf(str,"WHALE=%d", num);
}
sprintf_wrapper(new_env, whale);
You are appending to a string literal, which is read-only memory.
This generates a segmentation fault because you write into memory that is not supposed to be written into.
str = "WHALE=";
Thats a read only string literal.

Passing string by value in C

After going through multiple examples of passing a string by value in C, I still don't understand why the following code does not work
int main(void){
char *fileList;
strcpy(fileList,"This is a test line\n");
char type = 'F';
if(checkFileList(fileList, type)){
printf("Proper File list\n");
}
else{
printf("Improper File list\n");
}
}
int checkFileList(char *string, char type){
// Do something with string
}
This program works if I define the variable fileList in the main function as-
char fileList[128];
But I can't provide a fixed size to this string as I get the string only at runtime and hence don't know how long it'll be.
What am I doing wrong here? Please note that I don't want to pass the string by reference as I'll be changing the string in the function and don't want this to be reflected in the original string.
In your code
char *fileList;
strcpy(fileList,"This is a test line\n");
invokes undefined behaviour
, as , fileList is used uninitialized.
You need to allocate memory to fileList before using it. Maybe malloc() and family of functions will help you into that. Also, read about free().
FWIW,
This program works if I define the variable fileList in the main function as-
char fileList[128];
because, the fileList is an array here and the memory allocation is already done by the compiler. So, it is ok to use that.
BTW "Passing string by value" is misuse of the terms. C uses pass-by-value for any function parameter passing.
In order to allocate the memory for the string at runtime you better get to know the size of the string first:
int main(void){
const char *str = "This is a test line\n";
int len = strlen(str);
char *fileList = malloc(len);
// then later you also have to take care for releasing the allocated memory:
free(fileList);
}

C programming strcat using pointer

I am a beginner in C. I wanted to make strcat function using pointers. I made it but don't know what is wrong with it. I used gcc compiler and it gave segmentation fault output.
#include<stdio.h>
#include<string.h>
char scat(char *,char *);
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
while(*q!='\0') printf("the concatenated string is %c",*q);
}
char *scat(char *s,char *t)
{
char *p=s;
while(*p!='\0'){
p++;
}
while(*t!='\0'){
*p=*t;
p++;
t++;
}
return p-s-t;
}
This one works:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *scat(char *,char *); /* 1: your prototype was wrong */
void main()
{
char *s="james";
char *t="bond";
char *q=scat(s,t);
printf("cat: %s\n", q); /* 2: you can use %s to print a string */
free(q);
}
char *scat(char *s,char *t)
{
char *p=malloc(strlen(s)+strlen(t)+1); /* 3: you will have to reserve memory to hold the copy. */
int ptr =0, temp = 0; /* 4 initialise some helpers */
while(s[temp]!='\0'){ /* 5. use the temp to "walk" over string 1 */
p[ptr++] = s[temp++];
}
temp=0;
while(t[temp]!='\0'){ /* and string two */
p[ptr++]=t[temp++];
}
return p;
}
You have to allocate new space to copy at the end of s. Otherwise, your while loo[ will go in memory you don't have access to.
You shoul learn about malloc() here.
It is undefined behaviour to modify a string literal and s, and eventually p, is pointing to a string literal:
char* s = "james";
s is passed as first argument to scat() to which the local char* p is assigned and then:
*p=*t;
which on first invocation is attempting to overwite the null character an the end of the string literal "james".
A possible solution would be to use malloc() to allocate a buffer large enough to contain the concatentation of the two input strings:
char* result = malloc(strlen(s) + strlen(p) + 1); /* + 1 for null terminator. */
and copy them into it. The caller must remember to free() the returned char*.
You may find the list of frequently asked pointer questions useful.
Because p goes till the end of the string and then it starts advancing to illegal memory.
That is why you get segmentation fault.
It's because s points to "james\0", string literal & you cannot modify constant.
Change char *s="james"; to char s[50]="james";.
You need to understand the basics of pointers.
a char * is not a string or array of characters, it's the address of the beginning of the data.
you can't do a char * - char* !!
This is a good tutorial to start with
you will have to use malloc
You get a segmentation fault because you move the pointer to the end of s and then just start writing the data of p to the memory directly following s. What makes you believe there is writable memory available after s? Any attempt to write data to non-writable memory results in a segmentation fault and it looks like the memory following s is not writable (which is to expect, since "string constants" are usually stored in read-only memory).
Several things look out of order.
First keep in mind that when you want to return a pointer to something created within a function it needs to have been malloc'ed somewhere. Much easier if you pass the destination as an argument to the function. If you follow the former approach, don't forget to free() it when you're done with it.
Also, the function scat has to return a pointer in the declaration i.e. char *scat, not char scat.
Finally you don't need that loop to print the string, printf("%s", string); will take care of printing the string for you (provided it's terminated).
At first, your code will be in infinte loop because of the below line. you were supposed to use curely braces by including "p++; t++ " statements.
while(*t!='\0')
*p=*t;
though you do like this, you are trying to alter the content of the string literal. which will result in undefined behavior like segmentation fault.
A sequence of characters enclosed with in double quotes are called as string literal. it is also called as "string". String is fixed in size. once you created, you can't extend its size and alter the contents. Doing so will lead to undefined behavior.
To solve this problem , you need to allocate a new character array whose size is sum of the length of two strings passed. then append the two strings into the new array. finally return the address of the new array.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* scat(char *,char *);
void append(char *t , char *s);
int main(void)
{
char *s="james";
char *t="bond";
char *n = scat(s,t);
printf("the concatenated string is %s",n);
return 0;
}
char* scat(char *s,char *t)
{
int len = strlen(s) + strlen(t);
char *tmp = (char *)malloc(sizeof(char)* len);
append(tmp,s);
append(tmp,t);
return tmp;
}
void append(char *t , char *s)
{
//move pointer t to end of the string it points.
while(*t != '\0'){
t++;
}
while( *s != '\0' ){
*t = *s;
t++;
s++;
}
}

Can I initialize string after declaration?

Can I initialize string after declaration?
char *s;
s = "test";
instead of
char *s = "test";
You can, but keep in mind that with that statements you are storing in s a pointer to a read-only string allocated elsewhere. Any attempt to modify it will result in undefined behavior (i.e., on some compilers it may work, but often will just crash). That's why usually you use a const char * for that thing.
Yes, you can.
#include <stdio.h>
int
main(void)
{
// `s' is a pointer to `const char' because `s' may point to a string which
// is in read-only memory.
char const *s;
s = "hello";
puts(s);
return 0;
}
NB: It doesn't work with arrays.
#include <stdio.h>
int
main(void)
{
char s[32];
s = "hello"; // Syntax error.
puts(s);
return 0;
}
It is correct for pointers (as mentioned above) because the string inside quotes is allocated from the compiler at compile time, so you can point to this memory address. The problems comes when you try change its contents or when you have a fixed size array that want to point there

Replace a character in a char[] from a function

How would I get my replace_char function to work properly?
The way that I am trying it in the function below returns segmentation faults using gcc in Ubuntu.
I have tried other ways, but each time I try to change the value, I get a fault.
int main (void)
{
char* string = "Hello World!";
printf ("%s\n", string);
replace_char(string, 10, 'a');
printf ("%s\n", string);
}
void replace_char(char str[], int n, char c)
{
str[n] = c;
}
There is nothing wrong with your replace_char function. The problem is that you are trying to modify a string literal ("Hello World!") and that's undefined behavior. Try making a copy of the string instead, like this:
char string[] = "Hello World!";
Edit
To get the 'suggestion' of editing string in place, you can edit the pointer inplace:
void replace_char(char*& str, int n, char c)
{
str = strdup(str);
str[n] = c;
}
int main()
{
char* string = "Hello World!";
string = replace_char(string, 10, 'a');
// ...
free(string);
}
Note you now have to remember to call free on the string after calling this. I suggest, instead, that you do what I suggested before: wrap the literal in strdup if required. That way you don
't incur the cost of allocating a copy all the time (just when necessary).
The problem is that "Hello World' is a const literal char array.
const char* conststr = "Hello World!";
char * string = strdup(conststr);
i assume the problem will be gone
Explanation:
Compilers can allocate string literals in (readonly) data segment.
The conversion to a char* (as opposed to const char*) is actually not valid. If you use use e.g.
gcc -Wall test.c
you'd get a warning.
Fun experiment:
Observe here that (because it is Undefined Behaviour) compilers can do funny stuff in such cases:
http://ideone.com/C39R6 shows that the program wouldn't 'crash' but silently fail to modify the string literal unless the string was copied.
YMMV. Use -Wall, use some kind of lint if you can, and do unit testing :){

Resources