3

以下代码总是段错误:

  char *test3 = (char *) malloc(sizeof(char) * 5);
  test3 = "asdf";
  printf("%s\n", test3);

以下代码没有段错误:

  char *test3 = (char *) malloc(sizeof(char) * 5);
  test3[0] = 'a';
  test3[1] = 'b';
  test3[2] = 'c';
  test3[3] = 'd';
  test3[4] = '\0';
  printf("%s\n", test3);

我想问题可能是如何将 cstring 文字分配给动态创建的 cstring?

4

4 回答 4

2

“填充”字符串的正确方法是:

 strcpy(test3, "abcd"); 

但是,我强烈建议您不要使用malloc[ 并且绝对不要使用(char *) malloc(...)- 因为这可以隐藏一些相当讨厌的错误,这些错误至少会在适当的时候跳起来咬你,因为错误确实有这样做的倾向 - 你这样做可能是因为您将 C 代码编译为 C++ 代码,这是错误的,并且会教您像这样的坏习惯]。

用于malloc分配小字符串是一种很大的空间浪费。您的 5 个字符的字符串可能有 16-32 个字节的开销,并将四舍五入为 8 或 16 个字节。所以总共可以使用 48 个字节来存储 5 个字节——这是对空间的巨大浪费。

于 2013-08-07T23:44:15.300 回答
0

在您的情况下,您不能使用“=”分配字符串值。

您需要使用 strcpy 或 sprintf 函数。在程序结束时(或不再使用字符串时)不要忘记释放它!例如 :

#define BUFSIZE 5

int main(void) {
    char *test3 = malloc(sizeof(char) * BUFSIZE);
    snprintf(test3,BUFSIZE,"test");
    printf("%s\n", test3);
    free(test3);
    return 0;
}

或者你可以写:

int main(void) {
    char buf[BUFSIZE] = "test";
    printf("%s\n", buf);
    return 0;
}
于 2013-08-07T23:56:20.087 回答
0

其他人(正确地)建议您将字符串复制到分配的内存中。

这就是您的方法存在段错误的原因:字符串“asdf”是字符串文字,在编译时它存储在rodata或只读数据中。当你的程序尝试

test3 = "asdf";

它试图创建一个指向rodata 的指针。C不允许指向rodata的指针,因此您的语句不仅不起作用,而且段错误。

第二种方法很好,因为您不是在修改指针,而是在修改它指向的内容。

于 2013-08-08T04:39:45.770 回答
0

首先,谢谢你提出这个问题,它有一个有趣的皱纹。

我用 Eclipse/Microsoft C 运行了你的代码,没有收到分段错误,它按预期打印了“asdf”。

但是,这并不意味着或暗示您没有遇到分段错误。您的结果意味着检查编译器如何实现这两个语句:

   char *test3 = (char *) malloc(sizeof(char) * 5);

在堆上分配存储并将指针 , 设置为指向test3该位置。下一条语句也更新相同的指针。

   test3 = "asdf";

但是,在这种情况下test3,无论该文字存储在哪里,都指向文字“asdf”。一些编译器会生成一个字符串文字池并将它们存储在可执行文件中的某个位置,因此对于某些编译器,这些文字无法修改。

那么为什么编译器会将文字存储在无法访问的地方呢?没有意义,因此问题是:您使用的是什么 C 编译器?它坚持什么版本的C?

要解决可能是编译器错误的问题,并且仍然指向test3文字,试试??(同样,C 编译器在实现语言结构的内容和方式上确实存在差异。)

  const char *literal = "asdf";  // also try without a const stmt 
  // other code here
  test3 = literal;

最后,在第二个示例中,被malloc编辑的堆上的存储正在被修改并且显然是可寻址的。

于 2013-08-08T05:47:13.803 回答