简体   繁体   English

分配缓冲区/字符串

[英]Allocating a buffer/string

Let's say I have a function as follows: 假设我有一个如下功能:

void function(const char * str) {
    // initialize string
}

Is there considered a "standard" way or best practice to initialize a new string for a function? 是否存在为函数初始化新字符串的“标准”方法或最佳实践? For example, what would be the difference in using the following approaches: 例如,使用以下方法会有什么区别:

char * str1;

char * str2 = malloc(len);
char str3[len];

Is there a time when I should use one over the other? 有没有时间我应该一个使用另一个? It seems like using char * str2 = malloc(len); 似乎使用char * str2 = malloc(len); would be the most flexible of the above. 将是以上方法中最灵活的。

char* str1;

This line is declaring a new character array. 这行声明一个新的字符数组。 You can't use this as a string yet, since you need to set its value to an address of a block of memory using malloc, calloc, or realloc. 您还不能将其用作字符串,因为您需要使用malloc,calloc或realloc将其值设置为内存块的地址。 As mentioned, this needs to be freed when you're done using it to avoid memory leaks. 如前所述,使用完此功能后需要释放此功能,以避免内存泄漏。

char str1[];

This line will not compile, since you are trying to declare a static array with no size. 由于您试图声明一个没有大小的静态数组,因此该行将无法编译。

char * str3 = malloc(len);

This line is the same as above, except you are initializing your pointer to a block of memory. 该行与以上相同,除了您正在初始化指向内存块的指针。 This can now be used as a string with a length of len-1 to make space for the null terminator. 现在可以将其用作长度为len-1的字符串,以为空终止符腾出空间。 Again, this needs to be freed at the end of use to avoid memory leaks. 同样,需要在使用结束时释放它,以避免内存泄漏。

char str4[len];

This line is similar to the line above, except this is a static array that can not change size. 该行与上面的行相似,除了这是不能更改大小的静态数组。 'len' needs to be a const integer known during compile time. “ len”必须是在编译期间已知的const整数。 This type of array does not need to be freed and is lost when you leave the scope of where it is declared. 当您离开声明的范围时,不需要释放这种类型的数组,并且会丢失该类型的数组。 This can store a string of len-1 to make space for the null terminator. 这可以存储len-1字符串,以为空终止符腾出空间。

As mentioned above, this type can be initialized like this: char str4[] = {'n', 'e', 'w', ' ', 's', 't', 'r', 'i', 'n', 'g', '\\0'}; 如上所述,可以像这样初始化此类型: char str4[] = {'n', 'e', 'w', ' ', 's', 't', 'r', 'i', 'n', 'g', '\\0'};

char* str3 = "new string";

This line is NOT the same as the above line. 该行与上述行不同。 This line will create a string CONSTANT which can not be changed during runtime. 该行将创建一个字符串CONSTANT,该字符串在运行时不能更改。 Do note however that a null terminator is automatically added to the end of string constants. 但是请注意,空终止符会自动添加到字符串常量的末尾。

We like the following: 我们喜欢以下内容:

void function(char ** str) {
    // initialize string
    *str = malloc(some length calculation);
    if (!str) return;
    strcpy(str, something); // Or maybe it isn't strcpy.
}

int main()
{
    // ...
    char * some_string = NULL;
    // ...
    function(&some_string);
    ///...
    if (some_string) {
        // do something with some_string
    }

    // ...
    free(str);
}

Another well-liked pattern: 另一个受欢迎的模式:

char *function() {
    // initialize string
    char *str = malloc(some length calculation);
    if (!str) return str;
    strcpy(str, something); // Or maybe it isn't strcpy
    return str;
}

int main()
{
    // ...
    char *some_string = function();
    ///...
    if (some_string) {
        // do something with some_string
    }

    // ...
    free(str);
}

If it really is const sometimes we can use this simpler method: 如果确实是const有时我们可以使用以下更简单的方法:

const char *function()
{
    if (condition)
         return "some string";
    // ...
    if (some other condition)
         return "some other string";
    // ...
    return "something completely different";
}

int main()
{
   //...
   const char *str = function();
   //...
}

The comments are all valid points. 这些评论都是有效的观点。

As long as you properly handle freeing the memory and also make sure any memory allocated with malloc is in fact allocated, there's a couple differences I can think of. 只要您正确地处理释放内存的操作,并确保实际上分配了使用malloc分配的任何内存,我就可以想到一些区别。
One is that using malloc() allows you to be more dynamic and allocate strings of different lengths, whereas with char str[10] (or whatever length you need) means you have to know in advance the maximum length of the expected string. 一种是使用malloc()可以使您更加动态并分配不同长度的字符串,而使用char str[10] (或所需的任何长度)意味着您必须提前知道预期字符串的最大长度。 If you're accepting user input, you must make sure you do not accept more than the string will hold or else you open up a security hole. 如果要接受用户输入,则必须确保所接受的内容不超过该字符串所能容纳的范围,否则您将打开一个安全漏洞。

Another possible issue, which may or may not ever be applicable to your situation, is that any string created with char str[10] will be allocated on the stack if it's done within a function. 另一个可能会或可能永远不会适用于您的情况的问题是,如果使用char str[10]创建的任何字符串在函数中完成,则将在堆栈上分配该字符串。 On 8-bit embedded systems, you'll have to make sure that the string doesn't cross a 256 byte memory boundary, or else the stack pointer can wrap around to the beginning of that memory segment and can lead to some difficult to diagnose issues. 在8位嵌入式系统上,您必须确保该字符串未越过256字节的内存边界,否则堆栈指针可能会缠绕到该内存段的开头,并可能导致某些难以诊断的问题。问题。 You'd have to look at the assembly to see if the stack pointer is only 8-bit wide (this bit me one time and was a strange issue to debug. It wasn't a string issue, but a large struct issue, but strings would do it too). 您必须查看程序集,以查看堆栈指针是否只有8位宽(这一次让我感到困惑,这是一个奇怪的调试问题。这不是字符串问题,而是大型结构问题,但是字符串也可以做到)。 Whereas malloc() will be on the heap, that is if your embedded processor has a heap set up (not common on 8-bit but possible). malloc()将位于堆上,也就是说,如果嵌入式处理器设置了堆(在8位上不常见,但有可能)。 Note: the string doesn't have to be 256 bytes long, but you could have more local variables before it, or the function could be far down the call stack, pushing a shorter string across a boundary. 注意:字符串的长度不必为256个字节,但是它之前可以包含更多的局部变量,否则该函数可能位于调用堆栈的下方,从而将一个较短的字符串推入边界。

Manual memory manage is always a fraught issue, so my preference is to use stack allocation as much as possible, but it really depends on your application. 手动内存管理始终是一个棘手的问题,因此我希望尽可能多地使用堆栈分配,但这实际上取决于您的应用程序。

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

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