我有一个字符串函数,它接受指向源字符串的指针并返回指向目标字符串的指针.这个功能目前有效,但我担心我没有遵循重新编写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 …Run Code Online (Sandbox Code Playgroud) 我们担心恶意程序会尝试从RAM中读取密码.所以我们写了一个函数来覆盖密码变量,然后释放它.我们担心的是像clang或gcc这样的智能编译器会优化这个函数中的代码.该函数将字符串中的每个字符更改为空字节,然后释放该变量.
void free_pword(char* pword) {
char* pword_original = pword;
char c;
while ((c = *(pword++))) {
*pword = '\0';
}
free(pword_original);
}
Run Code Online (Sandbox Code Playgroud)
现在我们的问题.我们需要这样做吗?如果没有,为什么?如果我们确实需要这样做,我们怎样才能确保覆盖不会被优化掉?
###########编辑1:(2015年2月11日)来自未来的亲爱的人:这是我们到目前为止已经想到的......
我查看了原始汇编代码(来自gcc)以确定代码是否被优化掉了,事实并非如此.我决定添加volatile,以防优化器在更新中发生变化.
测试了gcc的版本.
$ gcc -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/c++/4.2.1
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)
我没有接受我自己的答案,因为我不是100%确定这对所有编译器都是安全的.编译专家可能会肯定地回答.
如果您需要像释放前那样安全地删除密码,请使用编译器测试此函数并查看原始程序集.您不必了解程序集,只需确保调用___bzero函数(memset)和_free函数.
目前的工作版本:
void free_pword(char * pword) {
//instead of changing the argument to the function, I added a volatile variable
//this was I don't have to change the calls to this …Run Code Online (Sandbox Code Playgroud)