纯 C (C 11) 中有一个任务,用原型编写函数: void *to_upper(const char *str) 应该返回指向字符串 str 副本的指针,其中所有字符都转换为大写。我是这样实现的:
void *to_upper(const char *str) {
void *res = NULL;
ssize_t len = strlen(str) + 1;
char *str1 = (char*) malloc(sizeof(char) * (len + 1));
for (size_t i = 0; i < len; i++) {
if (*(str + i) > 96 && *(str + i) < 123)
*(str1 + i) = *(str + i) - 32;
else
*(str1 + i) = *(str + i);
res = (void*) str1;
}
*(str1 + len) = '\0';
return res;
}
但我知道,通过为新行动态分配内存而不是释放它,每次使用此函数时都会发生泄漏。有没有办法在没有内存泄漏的情况下实现这个功能?
不严肃的回答:
在上面添加评论:
更严肃的回答:
在古老的《DOOM》中,一种称为区域记忆的机制负责这一点。当时的想法是,内存是从公共池中动态分配的,然后,当游戏在关卡之间转换时,肯定不需要数据时,内存就被一次性清除了。
您也可以这样做 - 在应用程序中选择一个时刻,当所有选定的行肯定都失去了相关性时 - 并一次将它们全部拆除。
没有人会费心制作一个静态缓冲区并返回一个指向它的指针。的确,退出函数后,最好立即将其复制给自己。此外,该技术用于系统库中的某些功能。我已经以与问题中的代码相同的样式绘制了一个示例
在这里,和往常一样,4kb 对每个人来说都足够了 :) 我还用真实字符替换了魔法常数。
此外,这种技术通常用于“加载”代码中,不需要额外的内存分配。
这样的函数根本不能同时在两个线程中使用。但这可以解决。
- - 更新 - -
但如果这是一次采访,@avp 在那里问:“我想要这样的代码
工作正常。好吧,至少它几乎总是正确的。”
让我们回答这个代码。
我们现在没有一个缓冲区,而是 16 个。每个新请求都由一个单独的缓冲区提供服务。是的,当它们绕圈子时,但在大多数情况下,即使是多线程也可以工作(如果您提供线程安全的增量和正确的缓冲区选择。但是这些调整是老先生们无事可做时的任务.