LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   segmentation fault in strcpy (https://www.linuxquestions.org/questions/programming-9/segmentation-fault-in-strcpy-511057/)

dayalan_cse 12-16-2006 09:17 AM

segmentation fault in strcpy
 
#include<stdio.h>
#include<string.h>
#include<malloc.h>

int main()
{
char *dest;
char *in="String1";

dest=(char*) malloc(20);
dest="data1";
strcpy(dest,in);
printf("%s",dest);
free(dest);
return 0;
}

output:
Segmentation fault


thanks & regards
dayalan

pigsa 12-16-2006 09:46 AM

By assignment "data1" to dest, dest points to a buffer with 6 bytes, not 20 bytes.

eerok 12-16-2006 10:12 AM

Well, the problem is here:
Code:

dest=(char*) malloc(20);
dest="data1";

The buffer addr value dest gets from malloc() is trashed by the string assignment, so you might as well not have used malloc() at all.

This is the kind of thing you need to do:
Code:

#include<stdio.h>
#include<string.h>
#include<malloc.h>

int main (void)          /* don't use empty main() as per standard */
{
  char *dest;
  char *in = "String1";

  dest = malloc (20);    /* don't cast malloc */
  strcpy (dest,"data1");
  strcpy (dest,in);
  printf ("%s\n", dest);
  free (dest);
  return 0;
}


dayalan_cse 12-17-2006 02:22 AM

Quote:

Originally Posted by pigsa
By assignment "data1" to dest, dest points to a buffer with 6 bytes, not 20 bytes.

#include<stdio.h>
#include<string.h>
#include<malloc.h>

int main()
{
char *dest;
char *in="String1";

dest=(char*) malloc(20);
dest="data1 data1 data1 da"; --> now it is 20 bytes now also i am getting segmentation fault
strcpy(dest,in);
printf("%s",dest);
free(dest);
return 0;
}

output:
Segmentation fault

please give me some more information.

dayalan_cse 12-17-2006 02:36 AM

i have doubt in your answers can you please explain
 
Quote:

Originally Posted by eerok
Well, the problem is here:
Code:

dest=(char*) malloc(20);
dest="data1";

The buffer addr value dest gets from malloc() is trashed by the string assignment, so you might as well not have used malloc() at all.

i accept your point malloc address has been changed due to "data1" string assignment why i have to remove the "data1" initilize to dest variable. i have some reason by assigning some string to pointer the pointer address is pointed to where the string kept in memory. why the strcpy is not copying to this address from source to destination address.

This is the kind of thing you need to do:
Code:

#include<stdio.h>
#include<string.h>
#include<malloc.h>

int main (void)          /* don't use empty main() as per standard */
{
  char *dest;
  char *in = "String1";

  dest = malloc (20);   

/* don't cast malloc */ MALLOC WILL RETURN VOID* i think its better to  have (char*) typecasting. what do you say.


  strcpy (dest,"data1");
  strcpy (dest,in);
  printf ("%s\n", dest);
  free (dest);
  return 0;
}


please send me your answers.

BiThian 12-17-2006 02:55 AM

Here's my explanation:
Code:

dest="data1 data1 data1 da";
Tiil now, all is correct. You've just made pointer dest to point to location where the string "data1 data1 data1 da" is (statically) stored.
Code:

strcpy(dest,in);
Now, you made the mistake. You're trying to modify the string "data1 data1 data1 da", by using a pointer. This is WRONG! To alter the string content, dest must be an array.
Code:

char dest[n];
, where n is a value, works.

introuble 12-17-2006 03:12 AM

:-/ The OP doesn't contain any questions.. just a piece of code, the output and

Quote:

thanks & regards
dayalan
I fail to see what the author wants.

eerok 12-17-2006 08:20 PM

Quote:

Originally Posted by dayalan_cse
i accept your point malloc address has been changed due to "data1" string assignment why i have to remove the "data1" initilize to dest variable. i have some reason by assigning some string to pointer the pointer address is pointed to where the string kept in memory. why the strcpy is not copying to this address from source to destination address.

You don't initialize a buffer you've created with malloc(), you write to it, for the simple reason that only writing to it will work. (Sorry, mistake here: 'Your first try at assignment overwrote the pointer to your buffer because you needed to try '*dest' instead of 'dest' ... but even using the pointer properly in this case will still fail. Try it and see.')

Also you should try turning on warnings (gcc -Wall -Wextra). You will get a warning if you try the assignment above.

Quote:

/* don't cast malloc */ MALLOC WILL RETURN VOID* i think its better to have (char*) typecasting. what do you say.
All that matters with malloc() is the size of the block. Of course it returns a void pointer ... that means you don't have to cast it. The practice of casting malloc() is from the time before 'void' was implemented.

Put another way, once you assign the pointer from malloc to your variable that's been declared as a char pointer, what's left to worry about? Your char pointer is no less a char pointer.

paulsm4 12-17-2006 10:57 PM

More to the point, pigsa already gave you the answer to your original question, in the very first response:
Quote:

By assignment "data1" to dest, dest points to a buffer with 6 bytes, not 20 bytes.
Here is a corrected version of your original program:
Code:

#include <stdio.h>
#include <string.h>
#include <malloc.h>

int
main(int argc, char *argv[])
{
  static char *src = "data1";  /* This is 6 bytes (5 letters + null) of
                                  *READ-ONLY* string data.
                                  Don't even *THINK* of trying to
                                  write into "src"! */
  char *dest = malloc (strlen (src + 1)); /* This is N bytes of uninitialized,
                                          read/write data. */
  if (dest == NULL)
  {
    perror ("malloc failed!");
    return 1;
  }

  strcpy (dest, src);
  printf ("dest: %s\n", dest);

  free (dest);
  return 0;
}


eerok 12-18-2006 01:37 AM

Quote:

Originally Posted by paulsm4
More to the point, pigsa already gave you the answer to your original question, in the very first response:
Quote:

By assignment "data1" to dest, dest points to a buffer with 6 bytes, not 20 bytes.

That's not really the answer. The answer is that the assignment in question creates a string literal, which will cause a segfault when you try to overwrite it no matter how many bytes are involved. (String literals are stored in protected memory.)

I misexplained what was wrong in my remarks above, as I corrected.

Of course, you also get a segfault from 'free (dest);' after dest has been overwritten.

The result of a buffer overrun as mentioned would be "undefined behavior" ... it might work, crash, or segfault. I'm pretty sure the code didn't execute to that point, though.

When there's more than one thing wrong, it's sometimes hard to nail the pertinent one.

duryodhan 12-18-2006 02:42 AM

Quote:

dest="data1";
Therein lies the nub of the error.

use :
Quote:

strcpy(dest,"data1");
This I think, should work fine. Following that , the free will also work correctly.
Some teacher taught me to always use strcpy , use something like what you have done only when variable has been declared.

Someone posted dest should be an array. Thats not true IMHO; cos when you did malloc you did as much.

Sorry , my english is not that good and I dont have access to GCC right now, so all this is from top of my head.

duryodhan 12-18-2006 02:44 AM

Quote:

static char *src = "data1"; /* This is 6 bytes (5 letters + null) of
*READ-ONLY* string data.
Don't even *THINK* of trying to
write into "src"! */
I can think whatever I want :P

Seriously though, why can't I write into src?
from what I read, static is something which doesn't lose value between function calls..

dayalan_cse 12-18-2006 04:51 AM

Quote:

Originally Posted by duryodhan
I can think whatever I want :P

Seriously though, why can't I write into src?
from what I read, static is something which doesn't lose value between function calls..


hai duryodhan,

you are correct static is only preserve the values for the variable. but one thing i just want to remember you


" Someone posted dest should be an array. Thats not true IMHO; cos when you did malloc you did as much "

in the case of array the same code will goes through without segmentation fault. i have reason for you because when compiler does convert to object file that time the array is becomes read and write permissions but in the case of pointer i am assigning "data1" constant data this might has read permission but not for write so it causes segmentation fault occur. But still i need more information why pointer gaves me segmentation fault when i assinged "data1".

you want me to give program for the array implemented code?


Thanks & Regards
dayalan

BiThian 12-18-2006 04:59 AM

Quote:

Originally Posted by BiThian
Here's my explanation:
dest must be an array.
Code:

char dest[n];
, where n is a value, works.

I meant to say that:
Code:

char dest[]="this is just a test";
won't cause any segmentation fault.

PS: I really don't understand why some members keep saying stupidities, when I already explained what was the real problem.

matthewg42 12-18-2006 05:35 AM

When you do something like this:
Code:

char* c = "hello world";
...the compiler makes a static string "hello world" in the object file. This is in a read-only data segment (called .data). The variable named c, of type pointer to a char, is set to be the address of the first character of the string in the .data segment.

If you try to modify the address of the static string in the data segment, you get a segfault because that page of memory is marked as read-only.

So, in answer to the question "why does this make a segfault?", see comments here:
Code:

    dest=(char*) malloc(20);    /* After this, dest points to newly allocated
                                    memory from the heap (or NULL on failure) */
 
    dest="data1";                /* oops, you've discarded the address of your
                                    malloc'd memory, and instead set dest to
                                    point at the static string "data1" in the
                                    .data segment (readonly)! */

    strcpy(dest,in);            /* strcpy tries to write to the address of
                                    "data1".  Segfault! */
    ...


dayalan_cse 12-18-2006 06:24 AM

Quote:

Originally Posted by eerok
That's not really the answer. The answer is that the assignment in question creates a string literal, which will cause a segfault when you try to overwrite it no matter how many bytes are involved. (String literals are stored in protected memory.)

I misexplained what was wrong in my remarks above, as I corrected.

Of course, you also get a segfault from 'free (dest);' after dest has been overwritten.

The result of a buffer overrun as mentioned would be "undefined behavior" ... it might work, crash, or segfault. I'm pretty sure the code didn't execute to that point, though.

When there's more than one thing wrong, it's sometimes hard to nail the pertinent one.


hai eerok,

your correct. thank you.

" (String literals are stored in protected memory.) " --> this i am able to understand ( your correct )
and is there any way to see this string in protected memory ? in elf. is there any tool for that.

but the core dump results shows strcpy raises segmentation fault. i am sure it is happening in this point. but my question is if you take the same concept program with array then you will not get segmentation problem then why it is for pointer? if your answer is "protected" means how can i make sure myself is there any way to make it conform using the linux tools? can you please help me to understand the problem.

Thanks & Regards
dayalan

eerok 12-18-2006 09:52 AM

Quote:

Originally Posted by dayalan_cse
is there any way to see this string in protected memory ? in elf. is there any tool for that.

but the core dump results shows strcpy raises segmentation fault. i am sure it is happening in this point. but my question is if you take the same concept program with array then you will not get segmentation problem then why it is for pointer? if your answer is "protected" means how can i make sure myself is there any way to make it conform using the linux tools? can you please help me to understand the problem.

Have you been using gdb to investigate this? I'm not an expert with this kind of thing, though I've used gdb occasionally. It's probably easier to research this less directly.

It's true that an array doesn't create the problem of the string literal; a string literal is defined in the standard as a preprocessing token, so it's processed before user data areas are initialized. The standard says string literals are used to "initialize an array of static storage duration and length just sufficient to contain the sequence." (n1124.pdf "6.4.5 String literals")

Perhaps it's faster to use string literals in the case where the contents don't need to be modified, or perhaps it's sometimes desirable to protect these strings for other reasons, but I admit that the larger questions here are beyond my technical competence :)

dayalan_cse 12-19-2006 01:52 AM

Quote:

Originally Posted by matthewg42
When you do something like this:
Code:

char* c = "hello world";
...the compiler makes a static string "hello world" in the object file. This is in a read-only data segment (called .data). The variable named c, of type pointer to a char, is set to be the address of the first character of the string in the .data segment.

If you try to modify the address of the static string in the data segment, you get a segfault because that page of memory is marked as read-only.

So, in answer to the question "why does this make a segfault?", see comments here:
Code:

    dest=(char*) malloc(20);    /* After this, dest points to newly allocated
                                    memory from the heap (or NULL on failure) */
 
    dest="data1";                /* oops, you've discarded the address of your
                                    malloc'd memory, and instead set dest to
                                    point at the static string "data1" in the
                                    .data segment (readonly)! */

    strcpy(dest,in);            /* strcpy tries to write to the address of
                                    "data1".  Segfault! */
    ...


hai matthew,

thanks for your good explanation. i understand the concept thank you once again.
but can you tell me is there any tools in linux to trace these kind of problems other than gdb?

thank you.
Thanks & Regards
dayalan

matthewg42 12-19-2006 02:15 AM

gdb is an excellent tool for this sort of work. If you don't like the text-mode interface, there are several GUI front-ends to gdb which might be more appealing, e.g. kdbg, insight and DDD (which is a really amazing tool for debugging and learning about data structures).


All times are GMT -5. The time now is 12:30 AM.