Reputation: 6987
I'm trying to build a str_replace function in C (so as to learn C). To make things a little easier, I've decided to create two helper functions, one of which has the following prototype:
char * str_shift_right(const char * string, char fill, int32_t n);
It takes a string and adds the character fill
at the n
th position in the given string. Here is the full code:
// 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;
}
I wanted to make sure this function was not leaking memory, so I've tried executing the following code:
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;
}
However, when watching memory usage with the activity monitor (a Mac OSX application, for those not familiar, kind of like the Process Manager on Windows), it seems like RAM gets eaten up pretty fast and it does not become available when the program stops executing.
Is that what a memory leak is? If so, what have I done wrong? Isn't the free(new_str)
call supposed to free up memory?
Thanks for your help.
Edit 1: Fixed off by one error spotted by PaulR. The problem remains.
Upvotes: 2
Views: 156
Reputation: 2216
Although has been mentioned, I think it's worth to emphasize that if you suspect there is a memory leak in your program, don't make conclusions just by watch system monitors but using valgrind instead.
Download it from here:
http://valgrind.org/downloads/current.html
Upvotes: 0
Reputation: 77454
Update: how are you measuring? This should not be possible on UNIX: "[memory] does not become available when the program stops executing". Maybe you are just looking at the wrong number?!?
I don't see where there should be a memory. Try using tools such as valgrind
!
The aforementioned invalid write has been discussed a number of times. Maybe you are destroying memory management information with this. I've seen C libraries use bytes just infront and/or after each allocated memory chunk for keeping track of allocated memory fragments. So maybe you are zeroing out the size this way and crippling memory management this way. So really, use valgrind
and similar tools.
However, you may also want to simplify your code.
\0
.size_t
, which is unsigned. Your code above will not warn if fill
is negative. With size_t
it must not be negative.So this should be sufficient (I did not compile test this - you may want to):
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;
}
The last memcpy
will also copy the trailing \0
here. Overall, the C compiler may optimize this code better, memcpy
is usually quite well taken care of. Plus, it actually is much easier to read.
Upvotes: 2
Reputation: 1
free
is not supposed to release memory to the system (e.g. using munmap(2), because malloc
usually prefer to re-use previously free
-d memory instead of acquiring it from the kernel (e.g. using mmap
)
The intuition is that syscalls managing memory address space(i.e. mmap
& munmap
) are quite expensive, so most malloc
& free
implementation try to reuse memory internally, when possible.
If you suspect a memory leak, try valgrind (recent versions have been ported to MacOSX). Of course compile your code with debugging information and all warnings (e.g. gcc -Wall -g
or perhaps clang -Wall -g
)
Upvotes: 2
Reputation: 45568
it seems like RAM gets eaten up pretty fast and it does not become available when the program stops executing.
Which RAM usage are you looking at? Total RAM usage in the system?
If so, what you're seeing is probably the memory that your terminal uses – every character your program prints out will be stored in RAM by the terminal (although it'll probably start dropping stuff at a certain limit). Try it again, but this time, prevent the output from showing up in the terminal:
./program > /dev/null
As a general rule, no matter how much memory you're leaking, it'll always be freed automatically when your program is terminated. And I can't spot any leaks in your program.
Upvotes: 6