简体   繁体   English

使用malloc在C中正确使用/创建动态cstrings?

[英]Properly using/creating dynamic cstrings in C with malloc?

The following code always segfaults: 以下代码总是段错误:

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

The following code does not segfault: 以下代码不会出现段错误:

  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);

I guess the question may be how do I assign a cstring literal to dynamically created cstring? 我想问题可能是如何将cstring文字分配给动态创建的cstring?

The correct way to "fill" a string is: “填充”字符串的正确方法是:

 strcpy(test3, "abcd"); 

However, I would strongly recommend that you don't use malloc [and DEFINITELY don't use (char *) malloc(...) - since that can hide some rather nasty bugs that jump up and bite you at least opportune moment, as bugs do have a tendency to do that - you are probably doing that because you are compiling your C-code as C++-code, which is wrong, and teaches you bad habits like this one]. 但是,我强烈建议你不要使用malloc [和DEFINITELY不要使用(char *) malloc(...) - 因为这样可以隐藏一些相当讨厌的错误,这些错误会在最短的时刻跳起来咬你,因为bug确实有这样的倾向 - 你可能正在这样做,因为你正在编译你的C代码作为C ++代码,这是错误的,并教你像这样的坏习惯]。

Using malloc to allocate small strings is a large waste of space. 使用malloc分配小字符串是一个很大的空间浪费。 Your 5 character string probably has an overhead of 16-32 bytes, and will be rounded to 8 or 16 bytes. 您的5个字符的字符串可能有16-32字节的开销,并将四舍五入为8或16个字节。 So in total it could be using 48 bytes, to store 5 bytes - that's a BIG waste of space. 所以总共可以使用48个字节来存储5个字节 - 这是一个很大的空间浪费。

You can't assign a string value with a "=" in your case. 在您的情况下,您不能为字符串值指定“=”。

You need to use the strcpy or sprintf function. 您需要使用strcpy或sprintf函数。 At the end of the program (or when the string is not used anymore) do not forget to free it ! 在程序结束时(或不再使用字符串时)不要忘记释放它! For example : 例如 :

#define BUFSIZE 5

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

Or you can just write : 或者你可以写:

int main(void) {
    char buf[BUFSIZE] = "test";
    printf("%s\n", buf);
    return 0;
}

Others have (correctly) suggested you copy the string into the allocated memory. 其他人(正确地)建议您将字符串复制到分配的内存中。

Here's why your approach is segfaulting: The string "asdf" is a string literal, and at compile time it gets stored in rodata, or read-only data. 这就是你的方法是segfaulting的原因:字符串“asdf”是一个字符串文字,在编译时它存储在rodata或只读数据中。 When your program tries 当你的程序尝试

test3 = "asdf";

It attempts to create a pointer to rodata. 它试图创建一个指向rodata的指针。 C does not allow pointers into rodata, and so your statement not only doesn't work, but seg faults. C不允许指向rodata,所以你的语句不仅不起作用,而且是seg错误。

The second method was fine, because you're not modifying the pointer, but rather what it points to. 第二种方法很好,因为你没有修改指针,而是指向它。

First of all, thank-you for this question it has an interesting wrinkle. 首先,谢谢你对这个问题有一个有趣的皱纹。

I ran your code with Eclipse/Microsoft C and did NOT get a segmentation error and it printed "asdf" as expected. 我用Eclipse / Microsoft C运行你的代码并没有得到分段错误,它按预期打印“asdf”。

However, this does NOT mean or imply that you are not getting a segmentation fault. 但是,这并不意味着或暗示您没有得到分段错误。 Your result implies an examination of how a compiler implements the two statements: 您的结果意味着检查编译器如何实现这两个语句:

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

Allocates storage on the heap and sets the pointer, test3 , to point to that location. 在堆上分配存储并将指针test3设置为指向该位置。 The next statement also updates the same pointer. 下一个语句也会更新相同的指针。

   test3 = "asdf";

However, in this case test3 points to the literal "asdf" where-ever that literal is stored. 但是,在这种情况下, test3指向文字“asdf”,其中存储了文字。 Some compilers generate a literal pool of strings and store them somewhere in the executable, as such for some compilers these literals cannot be modified. 一些编译器生成一个字符串字符串并将它们存储在可执行文件中的某个位置,因此对于某些编译器,这些文字无法修改。

So why would the compiler store a literal where it cannot be accessed? 那么为什么编译器会存储无法访问的文字呢? Doesn't make sense, hence the question: what C compiler are you using? 没有意义,因此问题是:你使用什么C编译器? And what version of C is it adhering to?? 什么版本的C坚持?

To work around what might be a compiler bug, and still point test3 at a literal, try?? 要解决可能是编译器错误,并仍然将test3指向文字,请尝试? (Again, C compilers do differ on what and how they implement language constructs.) (同样,C编译器在实现语言结构的方式和方式方面也有所不同。)

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

Finally, in the second example the storage on the heap that was malloc ed is being modified and is obviously addressable. 最后,在第二个示例中,正在修改malloc ed的堆上的存储,并且显然是可寻址的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM