我可以断言这会发生内存泄漏,并且正在寻找改进/解决这类问题的标准方法。
(例如,有经验的C专业人士如何实现此目的)
这是一个简单的案例切换程序。它的目的是给它PizZa并还给您pIZza。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char changeCase(char ch){
if ( (int)ch < 65 || (int)ch > 122){
return ch;
}else if ((int)ch < 91){
return (char)(ch + 32);
}
else{
return (char)(ch - 32);
}
}
char* toUpper(char* string){
size_t size=strlen(string);
char* temp = (char*) malloc(size);
while (*string != '\0'){
*temp = changeCase(*string);
temp++;
string++;
}
return (temp - size);
}
int main() {
char* string = toUpper("PIZa");
printf("%s",string);
return 0;
}
这会导致内存泄漏,因为无法释放malloc中的内存。有什么会更好?在函数外部分配内存,并将指向该内存的指针分配给toUpper函数?有其他想法吗?
答案 0 :(得分:4)
事实上的标准规则是执行动态分配的代码部分也负责释放它。因此,如果您的函数位于某个文件“ toupper.c”中,则该同一C文件中应该有某种可用的清理函数。
但是,最好的解决方案将内存分配和算法分开。这意味着编写此函数的更好方法是:
void toUpper (char* dst, const char* src)
{
while (*src!= '\0')
{
*dst= ...
...
dst++;
src++;
}
}
在这里,调用方可以根据需要为dst
分配空间,这与算法无关。例如:
char str1[] = "hello world";
char* str2 = malloc(strlen(str1) + 1);
toUpper(str2, str1);
...
free(str2);
只需确保记录函数,以便调用者知道他们必须为dst
分配空间-至少与src
一样大。
作为一个旁注,char* temp = (char*) malloc(size);
是错误的,您没有为空终止符分配空间。此外,您的算法还必须确保将空终止符复制到目标缓冲区中。
答案 1 :(得分:1)
由于未释放malloc的内存,因此会导致内存泄漏。
实际上,您的代码中没有内存泄漏。程序终止时,将释放所有分配的内存。
正在运行的程序中,当程序不再保存指向已分配内存的指针时,就会发生内存泄漏。
示例:
int main() {
char* string = toUpper("PIZa");
printf("%s",string);
string = toUpper("BRead"); // This causes a memory leak because after this
// line there is no longer any pointer to the
// memory allocated in the first call of toUpper
string = NULL; // Again this causes a memory leak because after this
// line there is no longer any pointer to the
// memory allocated in the second call of toUpper
return 0;
}
注意:程序终止时,即使泄漏的内存也将被释放。内存泄漏(主要)是“长时间”运行的程序中的问题。
哪个会更好?在功能之外分配内存...
好吧,这是一个品味问题。
例如:广泛使用(但非标准)的strdup
函数处理该函数内部的分配,并要求调用方稍后释放内存。
对于一个函数,它可以读取未知数量的字符作为用户输入,因此可以在函数内部执行malloc
(和realloc
根据需要)。
这里真的没有对与错。您是设计师,因此您可以决定。一切都与“功能合同”有关,即功能的文档-如何调用它以及它将做什么。