Using snprintf to concatenate giving segmentation fault in c - c

I am trying to compare szFileName1 and szFileName2 , if they are not same, then I am renaming it, but when I am trying to concatenate using snprintf it's giving segmentation fault.what mistake am I doing here?
typedef struct{
char filePath[100];
} filectx;
void filename1(filectx *ctx, const char ** szFileName1){
*szFileName1 = ctx->filepath;
}
void filename2(const char ** szFileName2){
char buf[20] = "/usr/bin/abb.txt";
snprintf(szFileName2, sizeof(szFileName2), "%s%s", szFileName2, buf);
}
int main(){
const char* szFileName1 = NULL;
const char *szFileName2 = malloc(100);
filectx ctx;
ctx.filePath = "/usr/bin/abc.txt";
filename1(&ctx, &szFileName1);
filename2(&szFileName2);
if(strcmp(szFileName1, szFileName2) != 0){
const char szFilePath1[200] = "/local/";
const char szFilePath2[200] = "/local/";
snprintf(szFilePath1, sizeof(szFilePath1), "%s%s", szFilePath1, szFileName1);
snprintf(szFilePath2, sizeof(szFilePath2), "%s%s", szFilePath2, szFileName2);
int ret = rename(szFilePath1, szFilePath2);
}
free(szFileName2);
return 0;
}

I think the problem here is with the arguments you pass to snprintf().
snprintf() expects an argument of type string ("char *"), but not "char **".
Here you are passing a pointer instead of the actual string. So when it tries to access the address it gives segmentation fault.
Change the parameters in the functions filename1() and filename2() to "char *" type and see. It should work.
Hope this helps.
Kranthi

With
const char szFilePath1[200] = "/local/";
const char szFilePath2[200] = "/local/";
as well as others as your function arguments, you declare those variables const. You then try to write to them with snprintf. Don't make these const.
You also can't reuse a variable as source and destination in snprintf.
I'm surprised that the compiler allowed you to compile this.

Although snprintf() doesn't work in your case, why don't you use strcat() or strncat()?
Instead of
snprintf(szFilePath1, sizeof(szFilePath1), "%s%s", szFilePath1, szFileName1);
you can write
strncat(szFilePath1, szFileName1, strlen(szFilePath1));
And by the way:
WHY did you write
sizeof(szFilePath1)
?
So, points to improve
In the very beginning:
*szFileName1 = ctx->filepath;
Not a nice thing to do. It's better to use strcpy()/strncpy(). And passing char ** argument also looks pretty strange.
Stated above. Usage of snprintf's

Related

char* and char[] with strcat()

My Question is char *string1 cannot be modified, then why they have syntax like
char *strcat(char *string1, const char *string2) ??
#include<stdio.h>
#include<string.h>
int main(void)
{
const char *p="Everyone";
char *a="Hello ";
printf("%s",strcat(a,p));
return 0;
}
Output: Segmentation fault (core dumped)
#include<stdio.h>
#include<string.h>
int main(void)
{
const char *p="Everyone";
char a[20]="Hello ";
printf("%s",strcat(a,p));
return 0;
}
Output: Hello Everyone
In snippet 1,char* stores in read-only memory, so we cannot modify(Here the modification is concatenation) I think that's why it shows segmentation fault
but syntax for strcat() is char *strcat(char *string1, const char *string2) .
The problem is not in strcat. The problem is that C90, due to backwards compatibility, decided to type the string literals as arrays of non-const characters, but specified that the behaviour when attempting to modify the characters in the said arrays would be undefined. After all, the entire const keyword was introduced in 80s being adopted from C++!
Even today, many compilers, like GCC, have a (questionable) option -fwritable-strings that makes string literals modifiable, just like in some early C compilers.
Notice that nothing stops you from writing
const char *a = "Hello ";
and then the strcat would complain loudly.
My Question is char *string1 cannot be modified, then why they have syntax like
char *strcat(char *string1, const char *string2) ??
Well, it depends on the argument you pass as the first parameter to the call. It's the requirement of the function and responsibility of the programmer to ensure to pass the first parameter as a pointer to memory which
can be modified (writable)
has enough memory to store the concatenated value.
The function signature is fine, it accepts a pointer to a char (array, long enough as per requirement).

Expected expression before char in C

I am doing a word search program and keep getting the same error that doesn't give me much information about whats wrong. Specifically it says this...
wordSearch.c:38:32: error: expected
expression
returnWord = (char *) strstr(char const *sentence, char const *phrase);
^
^
what could this be?
returnWord = char *strstr(const char *sentence, const char *phrase);
is not how you call a function. Get rid of the return type, simply use
returnWord = strstr(sentence, phrase);
assuming sentence and phrase are variables are defined and having proper values.
Based on the pictures, it looks as if something is wrong with strstr. This makes sense because of the way you are passing arguments. strstr expects two const char * arguments, however you have casted them incorrectly. Additionally, since strstr already returns a char * there is no need to cast that. Thus, line 38 should be returnword = strstr((const char *) sentence, (const char *) phrase);

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

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;
}

c - why convert main() argument to const

(I am a beginner in C, maybe my question is not very smart, but I did google before I ask.)
I saw following code in git source code:
int main(int argc, char **av) {
const char **argv = (const char **) av;
// ... more code ...
}
It converts char **av to const char **argv, I thought it meant to make the argument immutable, but I wrote a program and found that both argv and argv[i] are mutable.
Question 1: What is the purpose & goodness of that line of code?
Question 2: What is the behavior of a const pointer? I did google but didn't find a good answer.
#Update
I test more according to the answers, and it seems that argv[i][j] is immutable, but argv and argv[i] is mutable.
So the const on pointer makes the original value immutable, but the pointer itself is still mutable.
Thus I guess the major purpose of the code from git is also to prevent change of the original arguments.
testing code:
#include <stdio.h>
int main(int argc, char * av[]) {
// modify value pointed by a non-const pointer - ok
av[0][0] = 'h';
printf("argv[0] = %s\n", av[0]);
// modify const pointer itself - ok
const char **argv = (const char **) av;
argv[0] = "fake";
printf("argv[0] = %s\n", argv[0]);
char *arr[] = {"how", "are", "you"};
argv = (const char **)arr;
printf("argv[0] = %s\n", argv[0]);
// modify the value itself which is pointed by a const pointer - bad, an error will be thrown,
/*
argv[0][0] = 'x';
printf("argv[0] = %s\n", argv[0]);
*/
return 0;
}
The current code could compile & run without warning or error, but if un-comment the 2 commented lines at end, then it will throw following error when compile:
error: assignment of read-only location ‘**argv’
In practice it is not very useful here (and the generated code won't change much, if the compiler is optimizing).
However, argv is not mutable, so the compiler would for instance catch as an error an assignment like
argv[1][0] = '_'; // wrong
A const thing cannot be assigned to. So a const pointer can't be assigned, and a pointer to const means that the dereferenced pointer is a location which cannot be assigned. (and you can mix both: having a const pointer to const)
BTW, main  -in standard C99- is a very special function. You cannot declare it in arbitrary ways (it almost always should be declared int main(int, char**) or int main(void) ....) and you perhaps cannot call it (e.g. it cannot be recursive), but that may be different in C and in C++. So declaring int main (int, const char**) would be illegal.
1) There is really no point in using a const pointer to access the parameters later on, except to make sure they are not changed.
2) The purpose of const pointers is to make sure that they are not changed throughout the code. You can live without them, but it helps avoiding bugs.

How to convert const char* to char* in C?

In my project there is a method which only returns a const char*, whereas I need a char* string, as the API doesn't accept const char*.
Any idea how to convert between const char* to char*?
First of all you should do such things only if it is really necessary - e.g. to use some old-style API with char* arguments which are not modified. If an API function modifies the string which was const originally, then this is unspecified behaviour, very likely crash.
Use cast:
(char*)const_char_ptr
To be safe you don't break stuff (for example when these strings are changed in your code or further up), or crash you program (in case the returned string was literal for example like "hello I'm a literal string" and you start to edit it), make a copy of the returned string.
You could use strdup() for this, but read the small print. Or you can of course create your own version if it's not there on your platform.
You can use the strdup function which has the following prototype
char *strdup(const char *s1);
Example of use:
#include <string.h>
char * my_str = strdup("My string literal!");
char * my_other_str = strdup(some_const_str);
or strcpy/strncpy to your buffer
or rewrite your functions to use const char * as parameter instead of char * where possible so you can preserve the const
A const to a pointer indicates a "read-only" memory location. Whereas the ones without const are a read-write memory areas. So, you "cannot" convert a const(read-only location) to a normal(read-write) location.
The alternate is to copy the data to a different read-write location and pass this pointer to the required function. You may use strdup() to perform this action.
To convert a const char* to char* you could create a function like this :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* unconstchar(const char* s) {
if(!s)
return NULL;
int i;
char* res = NULL;
res = (char*) malloc(strlen(s)+1);
if(!res){
fprintf(stderr, "Memory Allocation Failed! Exiting...\n");
exit(EXIT_FAILURE);
} else{
for (i = 0; s[i] != '\0'; i++) {
res[i] = s[i];
}
res[i] = '\0';
return res;
}
}
int main() {
const char* s = "this is bikash";
char* p = unconstchar(s);
printf("%s",p);
free(p);
}
You can cast it by doing (char *)Identifier_Of_Const_char
But as there is probabbly a reason that the api doesn't accept const cahr *,
you should do this only, if you are sure, the function doesn't try to assign any value in range of your const char* which you casted to a non const one.
For example, you could write this way:
const char* a = "art.bin";
char* b = new char[sizeof(a)];
strcpy(b, a);

Resources