strcpy crash with char *[] (ARGV Structure) [duplicate] - c

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 9 years ago.
I have a problem with the c function 'strcpy' that I have not been able to figure out.
it involves copying to a char *[] like Argv (but not actually Argv). I can copy out of the structure but not in. But only if I initially declare the entire Argv Structure in a single go.
I assume that a char *[] is and array of char*.
Here is a simple demo program of the issue:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char FN[]="BBBB";
char *TL[]={
"a0 ",
"a1 ",
"a2 ",
"a3 ",
"a4 ",
"a5 "};
char BN[]="c1 ";
char N0[]="N0 ";
char N1[]="N1 ";
char N2[]="N2 ";
char N3[]="N3 ";
char N4[]="N4 ";
char N5[]="N5 ";
char* TD[6];
int main ( int argc, char *argv[] )
{
// FN is a pointer to an array of chars
// BN is the same
//TL is an array of pointers (that each point to an array of chars)
//TL[1] is thus a pointer to an array of chars
//TL is the same structure as Argv
//TD is the same structure as Argv (but built up from parts)
// but is spread out across the globals and the main func.
// thus less easy to read and understand then TL.
//TL[i], TD[i], and BN are initially allocated significantly larger than FN
// to remove the worry of overruns.
//copy "a1 \0" into the space held by "c1 "
strcpy(BN,TL[1]); //works
//copy "BBBB\0" into the space held by "c1 "
strcpy(BN,FN); //works
TD[0]=N0;
TD[1]=N1;
TD[2]=N2;
TD[3]=N3;
TD[4]=N4;
TD[5]=N5;
//copy "BBBB\0" into the space held by "a1 "
strcpy(TD[1],FN); //works
//copy "BBBB\0" into the space held by "a1 "
//strcpy(TL[1],FN); //dies
}

Your char pointers point to string literals. Those are not writable. Even though their type is char* for historical reasons, you should always treat them as char const *.
Either malloc space for your char buffers, or use an array of arrays.

As the link posted by dasblinkenlight in comments above,
char * p = "xyz"; is different from
char p[] = "xyz";
The first is immutable, second is mutable.
Why do I get a segmentation fault when writing to a string initialized with "char *s" but not "char s[]"?

Related

Create an array of string to run tests over them with string related functions in C [duplicate]

This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 1 year ago.
I am trying to understand what is wrong with my code and my understanding of pointers, arrays and string in C.
I tried to create an array of strings, to be able to loop over it and to test any functions that take a string as a parameter.
In this case, i'm trying to check my private implantation of memset called Memset.
This is my code:
#include <stdio.h>
#include <string.h>
/*First Try, did not work: */
/*const char * strings_array[] = {*/
/* "First string",*/
/* "213123Second_string3",*/
/* "",*/
/* "-3",*/
/* "s",*/
/*};*/
/* Second try, also does not work: */
const char **strings_array = (char *[]){"a", "b", "c"};
int main ()
{
while(*strings_array)
{
char *string = strings_array;
printf( "Before Memset, target is \"%s\"\n", *string );
if (NULL == Memset(*string, '$', 4))
{
fprintf(stderr,"Memset failed!\n");
}
printf( "After Memset, target is \"%s\"\n\n", *string );
++strings_array;
}
return (0);
}
I know that a string in C is not a type but a char *.
But it is also a string literal, which means I can't change it, and can only read it.
That's why it's not working?
Because I'm passing it to Memset and Memset tries to change it while it can not be changed because it's a string literal?
This is my implantation of my Memset function:
void *Memset(void *str, int c, size_t n)
{
unsigned char *string = str;
if (NULL == str)
{
return (NULL);
}
while(n > 0)
{
*string++ = (unsigned char) c;
--n;
}
return (str);
}
Your assesment is correct. You're creating an array of char * and initializing those pointers the the address of string constants, and string constants cannot be modified.
Instead of defining an array of char *, define a 2D array of char. While you use string constants to initialize the array, the array itself it writable.
char strings_array[][50] = {
"First string",
"213123Second_string3",
"",
"-3",
"s",
};
Note that for a multidimensional array, only the first dimension can have the size omitted if there is an initializer.
The first mistake that popped out at me was that in Memset you indirectly cast a void* to unsigned char *. I would change this to an explicit cast: unsigned char *string = (unsigned char *)str;
Secondly, you are absolutely correct: string literals cannot be modified. An attempt to modify a string literal would result in an error.
To test this code, I would try to allocate a string array on the heap, load some test strings into there, and then pass your string pointers from that array into your Memset function.

sprintf crashes but it is unclear why [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 6 years ago.
I tried the following code with sprintf, but it crashes in some cases and works fine in the other. Could anyone explain it to me?
#include <stdio.h>
#include <stdlib.h>
int main()
{
//char *s = malloc(20); //works fine
//char *s = ""; //does not work, no matter what the initial value is
char s[20]; //works fine
sprintf(s, "%s", "hello world");
printf("%s",s);
return 0;
}
When you are doing this:
char *s = "";
or
char *s = "longer string";
You are creating a literal string which is possibly placed in read-only memory. So you cannot change it later.
If you try to do the following syntax:
char s[] = "...";
the array will be initialized with the literal string and you will be able to modify the original array later.
Suggested questions on site:
What is the difference between char s[] and char *s in C?
Why do I get a segmentation fault when writing to a string initialized with “char *s” but not “char s[]”?

how to assign value to pointer string in C [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 6 years ago.
In C language I am trying to assign a value to pointer string. I cannot use char array, I have to use pointer string. So please tell how can I do that?
I am doing something like this (code given), but when I run my code an error is prompted program stopped working.
#include <stdio.h>
int main (void) {
char *myString = " ";
int value = 1;
myString[0] = value+'0';
printf("%s\n",myString);
return 0;
}
You cannot modify a string literal: myString is initialized to point to constant storage for the string literal. Attempting to modify it invokes undefined behavior. Use strdup() to create a copy of the string:
#include <stdio.h>
#include <string.h>
int main(void) {
char *myString = strdup(" ");
int value = 1;
myString[0] = value + '0';
printf("%s\n", myString);
free(myString);
return 0;
}
strdup() is a function standardized in POSIX, that allocates a block of memory from the heap long enough to receive a copy of its string argument. It copies the string into it and returns a pointer to the block. Such a block can be modified, and should be freed with free() when no longer needed.

char* and char[] are not same type? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get a segmentation fault when writing to a string?
I'm experiencing a strange issue with my C code. I'm trying to split string using strtok function, but I get access violation exception. Here's my code:
char *token;
char *line = "LINE TO BE SEPARATED";
char *search = " ";
token = strtok(line, search); <-- this code causes crash
However, if I change char *line to char line[], everything works as expected and I don't get any error.
Anyone can explain why I get that (strange for me) behavior with strtok? I thought char* and char[] was the same and exact type.
UPDATE
I'm using MSVC 2012 compiler.
strtok() modifies the string that it parses. If you use:
char* line = "...";
then a string literal is being modified, which is undefined behaviour. When you use:
char[] line = "...";
then a copy of the string literal is being modified.
When assigning "LINE TO BE SEPARATED" to char *line, you make line point to an constant string written in the program executable. You are not allowed to modify it. You should declare those kind of variable as const char *.
When declared as char[], your string is declared on the stack of your function. Thus, you are able to modify it.
char *s = "any string"
is a definition of pointer which point to string or array of char(s). in the above example s is pointing to a constant string
char s[] = "any string"
is a definition of array of char(s). in the above example s is an array of char(s) which contains the charcters {'a','n','y',' ','s','t','r,'i','n','g','\0'}
strtock changes the content of your input string. it replaces the delimators in your string by the '\0' (null).
So, you can not use strtok with constant strings like this:
char *s="any string"
you can use strtok with dynamic memory or static memory like:
char *s = malloc(20 * sizeof(char)); //dynamic allocation for string
strcpy(s,"any string");
char s[20] = "any string"; //static allocation for string
char s[] = "any string"; //static allocation for string
To answer your question: char* and char[] are not same type?
This:
char *line = "LINE TO BE SEPARATED";
Is a string literal defined in read only memory. You can't change this string.
This, however:
char line[] = "LINE TO BE SEPARATED";
Is now a character array (the quoted text was copied into the array) placed on the stack. You are allowed to modify the characters in this array.
So they are both character arrays, but placed in different parts of memory.

Segmentation fault (core dumped) in strtok [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Memory Allocation char* and char[]
Why does the following program give a Segmentation fault in run-time ?
#include <stdio.h>
#include <string.h>
#include <malloc.h>
main()
{
char * str = "Have a. nice, day :)";
char * ptr;
ptr = strtok( str, " .,");
printf("%s",ptr);
}
But if I use char str[] = "Have a. nice, day :)"; it gives me the output. Why is that i get the error even though strtok definition is char* strcpy( char * , const char * ) ???~
strtok modifies the argument, str points to a string literal, modifying a string literal causes undefined behavior. Initializing a non-const char* with a string literal is in fact deprecated.
When you write str[], str becomes a mutable array initialized with the string.
strtok modifies the string passed to it. I suspect it has something to do with char * = "literal string" giving you a pointer to the string in the .data section, while char[] = "literal string" allocates a buffer on the stack, and copies the initial contents from the .data section.

Resources