作为这个问题的后续行动:
从我所看到的,这应该按预期工作:
void greet(){
char c[] = "Hello";
greetWith(c);
return;
}
Run Code Online (Sandbox Code Playgroud)
但这会导致未定义的行为:
char *greet(){
char c[] = "Hello";
return c;
}
Run Code Online (Sandbox Code Playgroud)
如果我是对的,那么修复第二个问候语功能的最佳方法是什么?在嵌入式环境中?在桌面上?
Cha*_*tin 33
你是绝对正确的.第二个示例中的c数组正在堆栈中分配,因此内存将立即重用.特别是,如果你有像这样的代码
printf("%s\n",greet());
Run Code Online (Sandbox Code Playgroud)
你会得到奇怪的结果,因为对printf的调用会重用你阵列的一些空间.
解决方案是在其他地方分配内存.例如:
char c[] = "Hello";
char * greet() {
return c;
}
Run Code Online (Sandbox Code Playgroud)
会工作.另一种选择是在范围内静态分配它:
char * greet() {
static char c[] = "Hello";
return c;
}
Run Code Online (Sandbox Code Playgroud)
因为静态内存是在数据空间中与堆栈分开分配的.
你的第三个选择是通过malloc在堆上分配它:
char * greet() {
char * c = (char *) malloc(strlen("Hello")+1); /* +1 for the null */
strcpy(c, "Hello");
return c;
}
Run Code Online (Sandbox Code Playgroud)
但现在你必须确保以某种方式释放内存,否则你有内存泄漏.
其中一件似乎比我预期的更令人困惑的是"内存泄漏"到底是什么.泄漏是指您动态分配内存,但丢失地址以便无法释放.这些示例都不一定有漏洞,但只有第三个漏洞甚至可能有漏洞,因为它是唯一一个动态分配内存的漏洞.因此,假设第三个实现,您可以编写此代码:
{
/* stuff happens */
printf("%s\n", greet());
}
Run Code Online (Sandbox Code Playgroud)
这有泄漏; 返回指向malloc的内存的指针,printf使用它,然后丢失; 你不能再释放它了.另一方面,
{
char * cp ;
/* stuff happens */
cp = greet();
printf("%s\n", cp);
free(cp);
}
Run Code Online (Sandbox Code Playgroud)
不会泄漏,因为指针保存在一个自动变量中cp足够长的时间来调用free()它.现在,即使cp在执行完成后立即消失,但由于已经调用了free,因此内存被回收并且没有泄漏.
Gre*_*ill 12
如果您使用的是C++,那么您可能需要考虑使用std::string从第二个函数返回字符串:
std::string greet() {
char c[] = "Hello";
return std::string(c); // note the use of the constructor call is redundant here
}
Run Code Online (Sandbox Code Playgroud)
或者,在单线程环境中,您可以执行以下操作:
char *greet() {
static char c[] = "Hello";
return c;
}
Run Code Online (Sandbox Code Playgroud)
在static这里分配在全局存储区,从未消失空间.不过,这种static方法充满了危险.
取决于嵌入式环境是否有堆,如果是,你应该malloc如下:
char* greet()
{
char* ret = malloc(6 * sizeof(char)); // technically " * sizeof(char)" isn't needed since it is 1 by definition
strcpy(ret,"hello");
return ret;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您应该稍后调用free()进行清理.如果您无权访问动态分配,则需要将其设置为堆栈中的全局变量或变量,但需要进一步调用堆栈.
如果你需要在C++中这样做,那么使用std::stringGreg Hewgill的建议肯定是最简单和可维护的策略.
如果您正在使用C,您可以考虑返回一个指向空间的指针,该空间已经按照malloc()Jesse Pepper的建议动态分配; 但另一种可以避免动态分配的方法是greet()获取char *参数并在其中写入其输出:
void greet(char *buf, int size) {
char c[] = "Hello";
if (strlen(c) + 1 > size) {
printf("Buffer size too small!");
exit(1);
}
strcpy(buf, c);
}
Run Code Online (Sandbox Code Playgroud)
该size参数是为了安全起见,以帮助防止缓冲区溢出.如果您确切知道字符串的长度,则没有必要.
您可以使用以下任一方法:
char const* getIt() {
return "hello";
}
char * getIt() {
static char thing[] = "hello";
return thing;
}
char * getIt() {
char str[] = "hello";
char * thing = new char[sizeof str];
std::strcpy(thing, str);
return thing;
}
shared_array<char> getIt() {
char str[] = "hello";
shared_array<char> thing(new char[sizeof str]);
std::strcpy(thing.get(), str);
return thing;
}
Run Code Online (Sandbox Code Playgroud)
第一个要求您不要写入返回的字符串,但也是最简单的.最后一个使用shared_array,如果对内存的引用丢失(最后一个shared_array超出范围),它会自动清理内存.如果每次调用函数时都需要新字符串,则必须使用最后一个和第二个字符串.
| 归档时间: |
|
| 查看次数: |
18106 次 |
| 最近记录: |