我正在尝试在C中构建一个str_replace函数(以便学习C)。为了使事情变得更容易,我决定创建两个辅助函数,其中一个函数具有以下原型:
char * str_shift_right(const char * string, char fill, int32_t n);
它需要一个字符串,并在给定字符串中的fill
位置添加字符n
。这是完整的代码:
// replace the nth char with 'fill' in 'string', 0-indexed
char * str_shift_right(const char * string, char fill, int32_t n) {
// +1 the null byte, +1 for the new char
int32_t new_size = (int32_t) strlen(string) + 2;
char * new_string = NULL;
new_string = calloc(new_size, sizeof(char));
new_string[new_size - 1] = '\0';
int32_t i = 0;
while (i < strlen(string) + 1) {
// insert replacement char if on the right position
if (i == n) {
new_string[i] = fill;
// if the replacement has been done, shift remaining chars to the right
} else if (i > n) {
new_string[i] = string[i - 1];
// this is the begining of the new string, same as the old one
} else {
new_string[i] = string[i];
}
i++;
}
return new_string;
}
我想确保此功能没有泄漏内存,所以我尝试执行以下代码:
int main(int argc, const char * argv[])
{
do {
char * new_str = str_shift_right("Hello world !", 'x', 4);
printf("%s", new_str);
free(new_str);
} while (1);
return 0;
}
然而,在使用活动监视器(Mac OSX应用程序,对于那些不熟悉的,有点像Windows上的进程管理器)观察内存使用情况时,看起来RAM很快被吃掉了,而且当它不可用时程序停止执行。
这是内存泄漏的原因吗?如果是这样,我做错了什么? free(new_str)
调用不应该释放内存吗?
感谢您的帮助。
编辑1 :修正了PaulR发现的一个错误。问题依然存在。
答案 0 :(得分:6)
似乎RAM很快被吃掉了,当程序停止执行时它就不可用了。
您正在考虑使用哪种RAM?系统中的总RAM使用量?
如果是这样,您所看到的可能是您的终端使用的内存 - 您的程序打印出来的每个字符都将被终端存储在RAM中(虽然它可能会开始丢弃东西在一定的限度)。再试一次,但这一次,阻止输出显示在终端:
./program > /dev/null
作为一般规则,无论您有多少内存泄漏,它都会在程序终止时自动释放。我无法发现你程序中的任何泄漏。
答案 1 :(得分:2)
free
不应该向系统释放内存(例如使用munmap(2),因为malloc
通常更喜欢重新使用以前的free
- d内存而不是获取它来自内核(例如使用mmap
)
直觉是系统调用管理内存地址空间(即mmap
和munmap
)非常昂贵,因此大多数malloc
&amp; free
实现尽可能在内部重用内存。
如果您怀疑内存泄漏,请尝试valgrind(最新版本已移植到MacOSX)。当然,使用调试信息和所有警告(例如gcc -Wall -g
或clang -Wall -g
)编译代码
答案 2 :(得分:2)
更新:您是如何衡量的?这在UNIX上是不可能的:“程序停止执行时”[memory]不可用“。也许你只是看错了号码?!?
我看不出哪里应该有记忆。尝试使用valgrind
!
上述无效写入已多次讨论过。也许你正在破坏内存管理信息。我已经看到C库只是在前面和/或在每个分配的内存块之后使用字节来跟踪分配的内存片段。所以也许你正在以这种方式调整大小并以这种方式削弱内存管理。实际上,使用valgrind
和类似的工具。
但是,您可能还想简化代码。
\0
。size_t
,无符号。如果fill
为否定,则上述代码不会发出警告。使用size_t
时,不得为负数。所以这应该足够了(我没有编译测试这个 - 你可能想要):
char* str_shift_right(const char* string, char fill, size_t n) {
size_t len = strlen(string);
char* new_string = malloc(len + 2, sizeof(char));
memcpy(new_string, string, n);
new_string[n] = fill;
memcpy(new_string + n + 1, string + n, len - n + 1);
return new_string;
}
最后memcpy
也会在此处复制尾随\0
。总的来说,C编译器可以更好地优化此代码,memcpy
通常可以很好地处理。此外,它实际上更容易阅读。
答案 3 :(得分:0)
虽然已经提到过,但我认为值得强调的是,如果您怀疑程序中存在内存泄漏,请不要只是通过监视系统监视器而是使用 valgrind 来得出结论而不是。
从这里下载: