案例切换程序的实现改进

时间:2019-03-19 08:54:56

标签: c

我可以断言这会发生内存泄漏,并且正在寻找改进/解决这类问题的标准方法。

(例如,有经验的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函数?有其他想法吗?

2 个答案:

答案 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根据需要)。

这里真的没有对与错。您是设计师,因此您可以决定。一切都与“功能合同”有关,即功能的文档-如何调用它以及它将做什么。