views:

1974

answers:

6

Trying to copy a char *str to char c[] but getting segmentation fault or invalid initializer error.

Why is this code is giving me a seg fault?

char *token = "some random string";
char c[80];  
strcpy( c, token);
strncpy(c, token, sizeof c - 1); 
c[79] = '\0';
char *broken = strtok(c, "#");
A: 
char *str = "Hello";
char c[6];
strcpy( c, str );
Paul Mitchell
or use strncpy for added safety. strncpy(c, str, sizeof(str));
Tobias Wärre
If str length is bigger than c length this will fail
Patrice Bernassola
What a strange comment Patrice. Str length is NOT bigger than c length. str length is 5. Plus one for the null terminator makes 6. The original question wasn't about safety or anything like that, it was simply "How to copy a char* to char[]." I gave the simplest solution to that question. Now he's changed the question entirely to " why does my code crash".
Paul Mitchell
+3  A: 

use strncpy() rather than strcpy()

/* code not tested */
#include <string.h>

int main(void) {
  char *src = "gkjsdh fkdshfkjsdhfksdjghf ewi7tr weigrfdhf gsdjfsd jfgsdjf gsdjfgwe";
  char dst[10]; /* not enough for all of src */

  strcpy(dst, src); /* BANG!!! */
  strncpy(dst, src, sizeof dst - 1); /* OK ... but `dst` needs to be NUL terminated */
      dst[9] = '\0';
  return 0;
}
pmg
Why is this code is giving me a **seg fault**? char c[80]; strcpy( c, token); strncpy(c, token, sizeof c - 1); c[79] = '\0'; char *broken = strtok(c, "#");
Alex Xander
I gave an upvote because your code explicily does BANG!!It made me giggle.
Gerrit
reason for my downvote: unfortunatly, his given string fits in his destination array.
@dstibbe: just so you know ... the first version of the question (which was current when I answered) had no code at all :)
pmg
strncpy is horribly inefficient and most importantly does not nul-terminate if the destination buffers is smaller than the source. Please don't use it.
kmm
A: 

use strncpy to be sure to not copy more charachters than the char[] can contains

char *s = "abcdef";
char c[6];

strncpy(c, s, sizeof(c)-1);
// strncpy is not adding a \0 at the end of the string after copying it so you need to add it by yourself
c[sizeof(c)-1] = '\0';

Edit: Code added to question

Viewing your code the segmentation fault could be by the line

strcpy(c, token)

The problem is if token length is bigger than c length then memory is filled out of the c var and that cause troubles.

Patrice Bernassola
A: 

char c[] must have some size;

for example

char c[]= "example init string";

// that set up table c to c[19]; You can allocate it directly at the begginign of Your program;

char c[19] = {0}; // null filled table

char c[i] is the pointer so You don't need to copy anything; char c[19] ; c = "example init string"; // now &c[0] points the same address;

Copy can be done wiht

 strcpy(dst, src);

but MS force You to use secure function:

strcpy_s(dst,buffsize,src);
bua
char c[] has the same size as a pointer. char c[]= "example init string"; is exactly the same thing as char *c = "example init string"; On Linux, it would put that string literal in the ELF object file's .rodata section, then move merely the address-of into the pointer variable. It isn't going to allocate a fresh 19 bytes on the heap or stack at that declaration
Sean A.O. Harney
@Sean: sorry, you're wrong. Arrays are not pointers. `char c[] = "test";` creates an array with 5 elements. `char *c = "test"` creates a pointer to an array of 5 elements. Their `sizeof`s are different too!
pmg
@pmg Perhaps my compiler is optimizing it, when I have that declaration in gdb shows that it does a mov instruction to move the address of the string into %eax. For the sizeof(c) that is done at compile time and not run-time, but you are correct they are not exactly equivalent then. But it does not actually memcpy the string from .rodata or whereever into the stack, just moves the address so in that respect it is like using a pointer.
Sean A.O. Harney
A: 

Edited: Thanks for adding the code.

Perhaps the segfault occurs here:

strncpy(c, token, sizeof c - 1);

sizeof has a the same precedence as '-' from right to left, so it is probably processed as :

strncpy(c, token, sizeof( c - 1 ) );

instead of

strncpy(c, token, sizeof(c) - 1);

which is probably what you wanted

(reference: http://en.wikipedia.org/wiki/Operators%5Fin%5FC%5Fand%5FC%2B%2B#Operator%5Fprecedence)

You probably want to post that sort of thing as a comment rather than an answer.
Dominic Rodger
Yes posted the code.
Alex Xander
@alex-xander thanks for the code. Modified my answer based on the code.
A: 

It's been a while since i coded in c/c++, but c[80] is probably allocated on the stack. If you use char *c and strdup or similiar you get it allocated on the heap where strtok can access it.

Try something like this.

char *token = "some random string";
char *c;
c = strdup(token);
char *broken = strtok(c, "#");
free(c);
Johan Soderberg
strtok doesn't care whether the strings it operates on are in the stack or the heap.
Paul Mitchell
Ok, here's someone who had a similiar problem.http://refactormycode.com/codes/912-strtok-wtf
Johan Soderberg
Similar, but not the same. His problem was that the source string to strtok was a string literal which cannot be modified. strtok likes to modify the input string by replacing matched characters with nulls.
Paul Mitchell
strtok()'s issue isn't whether the string is on the stack or the heap, it's whether the string is readonly. If you have char* thing = "String"; then the compiler may give you a pointer to a readonly address. I'm not sure what the strict C/C++ rules on this are, and it will depend also on your hardware whether trying to write to the read-only memory just silently fails or faults.
AAT