开发者

Bus error while running a simple string C program [duplicate]

This question already has answers here: 开发者_运维问答 Difference between char *str="STRING" and char str[] = "STRING"? (6 answers) Closed 5 years ago.

I was running this simple program, the output i get is a "bus error". using some debugging statements i found the point at which it occurs was at the strcat() call.

#include<stdio.h>
#include<string.h>
main()
{
char *s = "this is ";
char *s1 = "me";  
strcat(s,s1); 
printf("%s",s);
return 0;
}

I run it using a gcc compiler on a MAC, 64-bit OS. Please let me know if i need to provide any more specification.

Thanks!


A little background:

The expressions "this is " and "me" are string literals; they are 9- and 3-element arrays of char (const char in C++) respectively with static extent (meaning the memory for them is allocated at program startup and held until the program exits). That memory may or may not be writable, depending on the platform, so attempting to modify a string literal results in undefined behavior (meaning the compiler can literally do anything it wants to). In short, you cannot write to a string literal.

When you write strcat(s, s1);, you're running into two problems: first, the target array is a string literal, which as I mentioned above is not writable. Secondly, it's not large enough to hold the additional characters; it's sized to hold 9 characters (including the 0 terminator), but you're attempting to store 11 characters to it. This is a buffer overflow, which can lead to Bad Things if you clobber something important.

You'll have to allocate a target buffer that is writable. You have several choices:

  1. You can declare an array that's big enough to hold the resulting string, although in general you're not going to know how big "big enough" is at compile time:

    
    char *s = "this is ";
    char *s1 = "me";
    char target[11];
    strcpy(target, s);
    strcat(target, s1);
    // alternately, sprintf(target, "%s%s", s, s1);
    

  2. In C99, you can declare a variable-length array (VLA) whose size isn't known until runtime:

    
    char *s = "this is ";
    char *s1 = "me";
    char target[strlen(s) + strlen(s1) + 1];
    strcpy(target, s);
    strcat(target, s1);
    // alternately, sprintf(target, "%s%s", s, s1);
    

  3. You can dynamically allocate a target buffer using malloc or calloc (this is actually the preferred method, since the buffer can be resized as necessary, unlike a VLA):

    
    char *s = "this is ";
    char *s1 = "me";
    char *target = malloc(strlen(s) + strlen(s1) + 1);
    strcpy(target, s);
    strcat(target, s1); 
    // or sprintf(target, "%s%s", s, s1);
    ...
    free(target); // when you're finished with the buffer
    


"this is " and "me" are string literals which may reside in a read-only part of your address space. You should not attempt to modify these.

char s[] = "this is ";
char s1[] = "me";  

This will ensure the literals are copied to stack - which is writable. Then your following strcat will overflow the stack buffers, which is just as bad.

The below will work - even though using strcat and not strncat is in general bad practice.

#include <stdio.h>
#include <string.h>
int main()
{
  char s[100] = "this is ";
  char *s1 = "me";  
  strcat(s,s1); 
  printf("%s",s);
  return 0;
}


You need to read up more on how strings work in C, and the difference between character arrays and string literals.

To make this work, rewrite it for instance as follows:

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

int main(void)
{
  char s[100] = "this is ";
  char *s1 = "me";  

  strcat(s, s1); 

  printf("%s", s);

  return EXIT_SUCCESS;
}

A few more points:

  1. main() returns int.
  2. The symbol EXIT_SUCCESS (from <stdlib.h> is clearer than 0).
  3. A function taking no arguments should be declared as void in C. For main(), empty parenthesis is not valid.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜