C char指针strcpy内存错误

时间:2013-08-08 23:27:05

标签: c memory-management

在C中,为什么这不起作用:

#include <stdio.h>
int main(void)
{
    char * strA = "Hello ";
    strcat(strA, "World!");
    printf("%s", strA);
    return 0;
}

但这样做:

#include <stdio.h>
int main(void)
{
    char strA[6] = "Hello ";
    strcat(strA, "World!");
    printf("%s", strA);
    return 0;
}

我会把错误,但唉我正在使用Xcode,它不喜欢在失败时给我任何可用的东西,只是给我BAD_ACCESS_EXC(代码= 2 ...)根据快速谷歌搜索,只是有内存分配错误的事情。

我认为你在两种情况下都为strA分配了相同数量的内存。有人可以赐教吗?

4 个答案:

答案 0 :(得分:2)

在第一种情况下,您将strA声明为char *,指向包含字符串"Hello "的静态内存。

在第二种情况下,您将创建一个包含6个字符的数组,并使用字符串"Hello "进行初始化。

因此,在第一种情况下,

strcat会尝试写入此静态内存段,从而立即导致错误。

第二个代码仍然无效(因为strA不是一个足够大的数组来存储"Hello World"),可能会也可能不会出现段错误,因为您没有尝试附加到字符串文字

答案 1 :(得分:0)

char * strcat ( char * destination, const char * source );

请参阅Here

该函数会将最终字符串写入第一个参数。在这种情况下,您无法将只读内存传递给它。

答案 2 :(得分:0)

这里实际上有很多事情发生。让我们逐一介绍。请考虑以下两个字符串“Hello”的声明。

char *strA = "Hello "; // #1
char strB[ 7 ] = "Hello "; // #2

第一个表达式是声明一个名为strA的字符指针,它指向内存的只读部分中的一个位置,其中“Hello”(或者是''h','e','l','l','存储o','','\ 0'})。第一个声明通常称为字符串文字

第二个表达式是声明一个名为strB的字符数组,它由七个字符组成,并在堆栈中声明。重要的是要注意C中字符串的约定是在字符串末尾(一个字符数组)有一个 null终止符(0个字符) - 你错过了它。初始化语法(双引号)会自动使用0填充尾随条目,无论它在何处声明。

现在,直接回答你的问题。您不能覆盖只读内存,因此如果您尝试修改strA指向的任何内存(字符串文字),那么它将导致错误。您可以修改strB指向的内存块,但是您需要初始化一个更大的数组以正确容纳字符'w','o','r','l','d'和'!'。编译器将允许您写入您无权访问的内存,但无法保证不会将其分配给同一堆栈帧或其他程序上的其他变量。

这将是正确的代码片段:

#include <stdio.h>

int main( void ) {
  // Declares an array of characters, strA with a length of 13.
  char strA[ 13 ] = "Hello ";

  // Concatenates the characters 'w', 'o', 'l', 'r', 'd' and '!' to strA.
  strcat( strA, "World!" );

  // Outputs to stdout.
  printf( "%s", strA ); // => "Hello World!"

  return 0;
}

答案 3 :(得分:0)

我很惊讶第二个代码有效。为了使它在没有任何运行时错误的情况下工作,您可能希望使用动态内存分配。