我有一个字符串函数,它接受指向源字符串的指针并返回指向目标字符串的指针.这个功能目前有效,但我担心我没有遵循重新编写malloc,realloc和free的最佳实践.
与我的函数不同的是,目标字符串的长度与源字符串不同,因此必须在我的函数内调用realloc().我从查看文档中了解到......
http://www.cplusplus.com/reference/cstdlib/realloc/
realloc后内存地址可能会改变.这意味着我不能像C程序员那样"通过引用"传递给其他函数,我必须返回新的指针.
所以我的功能原型是:
//decode a uri encoded string
char *net_uri_to_text(char *);
Run Code Online (Sandbox Code Playgroud)
我不喜欢我这样做的方式,因为我必须在运行函数后释放指针:
char * chr_output = net_uri_to_text("testing123%5a%5b%5cabc");
printf("%s\n", chr_output); //testing123Z[\abc
free(chr_output);
Run Code Online (Sandbox Code Playgroud)
这意味着在我的函数中调用malloc()和realloc(),并在函数外部调用free().
我有高级语言的背景,(perl,plpgsql,bash)所以我的直觉是对这些东西的正确封装,但这可能不是C语言中的最佳实践.
问题:我的方式是最佳实践,还是我应该遵循更好的方法?
在未使用的argc和argv参数上编译并运行两个警告,您可以安全地忽略这两个警告.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *net_uri_to_text(char *);
int main(int argc, char ** argv) {
char * chr_input = "testing123%5a%5b%5cabc";
char * chr_output = net_uri_to_text(chr_input);
printf("%s\n", chr_output);
free(chr_output);
return 0;
}
//decodes uri-encoded string
//send pointer to source string
//return pointer to destination string
//WARNING!! YOU MUST USE free(chr_result) AFTER YOU'RE DONE WITH IT OR YOU WILL GET A MEMORY LEAK!
char *net_uri_to_text(char * chr_input) {
//define variables
int int_length = strlen(chr_input);
int int_new_length = int_length;
char * chr_output = malloc(int_length);
char * chr_output_working = chr_output;
char * chr_input_working = chr_input;
int int_output_working = 0;
unsigned int uint_hex_working;
//while not a null byte
while(*chr_input_working != '\0') {
//if %
if (*chr_input_working == *"%") {
//then put correct char in
sscanf(chr_input_working + 1, "%02x", &uint_hex_working);
*chr_output_working = (char)uint_hex_working;
//printf("special char:%c, %c, %d<\n", *chr_output_working, (char)uint_hex_working, uint_hex_working);
//realloc
chr_input_working++;
chr_input_working++;
int_new_length -= 2;
chr_output = realloc(chr_output, int_new_length);
//output working must be the new pointer plys how many chars we've done
chr_output_working = chr_output + int_output_working;
} else {
//put char in
*chr_output_working = *chr_input_working;
}
//increment pointers and number of chars in output working
chr_input_working++;
chr_output_working++;
int_output_working++;
}
//last null byte
*chr_output_working = '\0';
return chr_output;
}
Run Code Online (Sandbox Code Playgroud)
malloc只要您记录它们的事实,就可以从C中的函数返回'd缓冲区.很多库都这样做,即使标准库中没有函数.
如果你可以计算(一个不太悲观的上限)需要廉价地写入缓冲区的字符数,你可以提供一个功能,让用户调用它.
接受要填充的缓冲区也是可能的,但不太方便; 我见过很多像这样的库:
/*
* Decodes uri-encoded string encoded into buf of length len (including NUL).
* Returns the number of characters written. If that number is less than len,
* nothing is written and you should try again with a larger buffer.
*/
size_t net_uri_to_text(char const *encoded, char *buf, size_t len)
{
size_t space_needed = 0;
while (decoding_needs_to_be_done()) {
// decode characters, but only write them to buf
// if it wouldn't overflow;
// increment space_needed regardless
}
return space_needed;
}
Run Code Online (Sandbox Code Playgroud)
现在调用者负责分配,并会做类似的事情
size_t len = SOME_VALUE_THAT_IS_USUALLY_LONG_ENOUGH;
char *result = xmalloc(len);
len = net_uri_to_text(input, result, len);
if (len > SOME_VALUE_THAT_IS_USUALLY_LONG_ENOUGH) {
// try again
result = xrealloc(input, result, len);
}
Run Code Online (Sandbox Code Playgroud)
(这里,xmalloc和xrealloc是我做了跳过NULL检查"安全"的功能分配.)