Is it risky to use freed memory - c

Suppose I have a char pointer which points to some string in memory.
and suppose I want to copy that string to some other place in memory.
void cpy(char **dst, char *src)
{
*dst = (char *) realloc(*dst, strlen(src) + 1);
memcpy(*dst, src, strlen(src) + 1);
}
(Assume memory allocation is successful, and src is not NULL)
What if I call this function like this:
char *str = malloc(14);
memcpy(str,"hello, world!", 14);
cpy(&str,str+7);
Now I would expect srt to point to the string "world!" (Which it does in my tests).
But what concerns me is that in this call to cpy, *dst and src actually point to different locations of the same string. And, when calling realloc on *dst, it's possible that this memory will be freed. But in the next line I'm trying to copy from that place with memcpy.
So the questions is: Is there something wrong with it?
Or to put it another way - is it okay to free memory, and use it immediately afterwards?
Thanks.
Note: The example was updated so that realloc is called on memory that was obtained with malloc.

Everything is wrong with this. It is outright undefined behaviour to call realloc on a pointer that was not obtained with malloc etc.
As #Daniel Fischer points out, it is also undefined behaviour to use memcpy on overlapping regions of memory (in which case you should use memmove), so you have to be careful.
Update: After your substantial edit, the question is quite different. It is now equivalent to this condensed version:
char * s = malloc(14);
strcpy(s, "hello, world!");
char * p = realloc(s, 14);
memcpy(p, s, 14);
This is also undefined behaviour, because you are not allowed to access the memory pointed to by s anymore after a successful realloc, and you're not allowed to access the memory pointed to by p after an unsuccessful realloc.

The implicit assumption in your example is that it is permitted for cpy to free memory it didn't allocate. It's kind of a dodgy assumption, but as long it's intentional, that's OK. Use malloc and free separately rather than realloc in that case:
void cpy(char **dst, char *src)
{
// obtain completely new memory (realloc might do this anyway)
char* new = malloc(strlen(src) + 1);
// duplicate the string
memcpy(new, src, strlen(src) + 1);
// release the original memory now that we know we are done with it
free(*dst);
// indicate where to find the new string
*dst = new;
}
This still isn't a great idea, because there's no way to know what other variables might be pointing at that memory that you're freeing, but if you have a way to make that guarantee, this is the kind of code you need.

Related

Typedef char pointer allocation of string

I am trying to understand a code that has the typedef char * I am supposed to allocate memory enough for the string "Pointer of" and "Redundancy".
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
typedef char* DString;
DString dstring_initialize(const char* str);
int main(void)
{
DString str1, str2;
str1 = dstring_initialize("Pointer of ");
str2 = dstring_initialize("Redundancy ");
return 0;
}
DString dstring_initialize(const char* str)
{
str = malloc((strlen(str)+1)*sizeof(DString));//mycode
return str;//mycode
}
I am 100% sure that I am doing it completely wrong. The only thing I am supposed to do is change the part where it says mycode. It was sent to me like that, but as I said before, I don't know how it works, and if someone could explain it to me in detail, I would appreciate it
In the code below you allocate too much memory:
str = malloc((strlen(str)+1)*sizeof(DString));//mycode
^^^^^^^^^^^^^^
Not needed
Also you assign the return value from malloc to the input argument, i.e. you "destroy" the input.
Further, you never copy the value of the input string to the allocated memory.
Instead of the above, you need:
char* res = malloc(strlen(str) + 1);
if (res != NULL)
{
strcpy(res, str);
}
return res;
There are two areas of memory, the stack where local things exist, and the heap where other things exist. The stack is automatic in that your compiler manages it for you, and the heap is something that you have to manage through calls to malloc, realloc, and free, etc.
Things that are known at compile can exist in the stack, whereas things that you don't know at compile time can exist in the heap and be allocated, reallocated, freed, etc., with calls to malloc, realloc, and free.
And that basically all comes down to the size of the memory allocated. If you declare, for example, an int, that int can change in value as your program executes because it always exists in a space that is the sizeof an int.
But you might want to place your string in the heap if it changes length while the program runs and you don't want to allocate something big enough to always be able to hold it. For example, you don't need to allocate space on the heap for str if you always made it big enough with something like char str[64] or something like that because you allocate that space ahead of time.
In terms of malloc, you ask it to allocate memory of a certain size, and if it can it returns a pointer to it, if it can't it returns NULL. So the variable that holds the pointer returned by malloc exists in the stack, and the memory allocated by malloc exists in the heap and is not automatic. Ie: when your program terminates the pointer variable in the stack is released but not the actual memory stored in the heap, so you have to free it with free.
In the case of sizeof, well, that tells malloc how much you want to allocate, in this case a char, but it can be anything that can be resolved to a size, for example a structure that you define, etc. So what you're basically saying when you call malloc is "give me something this big and give me this many of them". In this case, "give me something as big as a char" and give me "strlen(str) + 1 of them".
And because the size of a character is always 1 byte and strlen returns a value of type size_t which malloc takes you can simply do it as char *ptr = malloc(strlen(str) + 1). But keep in mind that malloc returns a pointer of type void so you need to cast it to the type you are requesting. In this case you would cast it to a char* like this: ptr = (char*)malloc(strlen(str) + 1).
The other error is described in the other answer. But that is basically in a nutshell how malloc works. I'm not a teacher and I apologize if I'm not 100% clear.

strdup and memory leaking

Does strdup allocate another memory zone and create another pointer every time?
For example: does the following code result in a memory leak?
void x(char** d, char* s){
*d = strdup(s);
}
int main(){
char* test = NULL;
x(&test, "abcd");
x(&test, "etc");
return 0;
}
Yes, the program leaks memory because it allocates objects and then loses references to them.
The first time this happens is in the line:
x(&test, "etc");
The variable test holds the one and only copy of a pointer that was allocated in a previous call to x. The new call to x overwrites that pointer. At that point, the pointer leaks.
This is what it means to leak memory: to lose all references to an existing dynamically allocated piece of storage.*
The second leak occurs when the main function returns. At that point, the test variable is destroyed, and that variable holds the one and only copy of a pointer to a duplicate of the "etc" string.
Sometimes in C programs, we sometimes not care about leaks of this second type: memory that is not freed when the program terminates, but that is not allocated over and over again in a loop (so it doesn't cause a runaway memory growth problem).
If the program is ever integrated into another program (for instance as a shared library) where the original main function becomes a startup function that could be invoked repeatedly in the same program environment, both the leaks will turn into problems.
The POSIX strdup function behaves similarly to this:
char *strdup(const char *orig)
{
size_t bytes = strlen(orig) + 1;
char *copy = malloc(bytes);
if (copy != 0)
memcpy(copy, orig, bytes);
return copy;
}
Yes; it allocates new storage each time.
If you have a garbage collector (such as Boehm) in your C image, then it's possible that the leaked storage is recycled, and so strdup is able to re-use the same memory for the second allocation. (However, a garbage collector is not going to kick in after just one allocation, unless it is operated in a stress-test mode for flushing out bugs.)
Now if you want to actually reuse the memory with realloc, then you can change your x function along these lines:
#include <stdlib.h>
#include <string.h>
void *strealloc(char *origptr, char *strdata)
{
size_t nbytes = strlen(strdata) + 1;
char *newptr = (char *) realloc(origptr, nbytes); /* cast needed for C++ */
if (newptr)
memcpy(newptr, strdata, nbytes);
return newptr;
}
(By the way, external names starting with str are in an ISO C reserved namespace, but strealloc is too nice a name to refuse.)
Note that the interface is different. We do not pass in a pointer-to-pointer, but instead present a realloc-like interface. The caller can check the return value for null to detect an allocation error, without having the pointer inconveniently overwritten with null in that case.
The main function now looks like:
int main(void)
{
char *test = strealloc(NULL, "abcd");
test = strealloc(test, "etc");
free(test);
return 0;
}
Like before, there is no error checking. If the first strealloc were to fail, test is then null. That doesn't since it gets overwritten anyway, and the first argument of strealloc may be null.
Only one free is needed to plug the memory leak.
* It's possible to have a semantic memory leak with objects that the program hasn't lost a reference to. For instance, suppose that a program keeps adding information to a list which is never used for any purpose and just keeps growing.
Yes, it allocates memory and leaks if you don't free it. From the man page:
The strdup() function returns a pointer to a new string which is a duplicate of the string s. Memory for the new string is obtained with malloc(3), and can be freed with free(3).
new_s = strdup(s) is essentially equivalent to:
new_s = malloc(strlen(s)+1);
strcpy(new_s, s);
Consider the following definition for strdup:
#include <string.h>
char *strdup(const char *string);
strdup reserves storage space for a copy of string by calling malloc. The string argument to this function is expected to contain a null character (\0) marking the end of the string. Remember to free the storage reserved with the call to strdup.
You must free the string yourself.

Why the free in line2 makes memcpy do nothing?? Is free before malloc is o.k?? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
void str_cpy(char **des,char* src){
if(*des || *des==src)
free(*des);
*des = (char*)malloc(sizeof(char)*(strlen(src)+1));
if(!*des)
return ;
memcpy ( *des, src, (strlen(src)+1)*sizeof(char) );
}
Why the free in the line2 makes memcpy do nothing?? Is the free before malloc is o.k??
No!!! :-) It is not OK for you to free(src) before trying to use it! (In the case where *dest == src, line 2 of your code, namely free(*dest) is essentially the same as free(src) and then you use src which from that point on does not point to a properly allocated memory block.)
Trying to use freed memory leads to undefined behaviour. When something is undefined anything goes! Maybe free has changed the first byte in src to 0 (in which case strlen(src) == 0) or maybe memcpy detects the source memory is not properly allocated or maybe something else is going on. It is not really worth pursuing the question of why you get this behaviour. If you change your build settings (debug/optimise etc.) or build your program on a different system (actually it is the library, not the compiler that you use is what makes a difference here) you will probably get a different result.
At any rate, when *dest == src, you need not free, strlen, malloc, and copy anything; you can just return.
void str_cpy(char **des,char* src){
if(*des==src) return;
...
}
In general, someone using your function would expect that you do not do anything funny with the second argument, src, such as change its contents or, indeed, freeing its memory. I would also change the argument type to const char * src. While this does not stop you from freeing the src memory block, it will make the intended usage of the function clearer.
Actually, there is another, bigger problem with the function signature. *dest may be pointing to previously allocated memory in the heap (the only case in which free(*dest) is OK, assuming *dest != src, of course) or to previously allocated stack memory (in which case free(*dest) is not OK), but is also possible that it is pointing to statically allocated memory (a string literal) or to not be pointing to allocated memory period.
Standard library functions avoid this problem by not using such signatures (i.e. with arguments of type char **).
The signatures of the functions most relevant to what you are doing are:
char * strcpy(char *restrict s1, const char *restrict s2);
char * strncpy(char *restrict s1, const char *restrict s2, size_t n);
char * strdup(const char *s1);
More info at: http://www.manpagez.com/man/3/strncpy/ and http://www.manpagez.com/man/3/strncpy/
None of these functions have to worry about where memory is allocated. All three require that their arguments are valid pointers (to either statically or dynamically allocated (heap/stack) memory. I suspect strdup is actually the most appropriate for what you are doing (you seem to want to allocate new memory for the duplicated string). strcpy and strncpy do not allocate new memory. (See the documentation links above for more details.)
Do you see a pattern there? strdup returns a pointer to the newly allocated memory (exactly as malloc does) and strcpy and strcpy take char * arguments and do not allocate memory. Neither of these functions have to deal with the problem your function has, of determining (impossible to do in C) what kind of memory *dest points to. There is a reason why Kernighan and Ritchie chose to do things that way :-)
You could provide documentation that makes it explicit that *dest must be pointing to a previously allocated memory block in the heap or be equall to NULL. However, good library designers would not do that because it passes responsibility to the users (as users will make mistakes).
Relying on documentation (i.e. having the library designer passing the responsibility to its users) is a treacherous path. It is best to avoid the problem altogether. Good C code starts at function signatures :-)
One last note: you are using strlen() twice in your code. For performance reasons, it is best if you only use it once and store its return value in a local variable and use that variable where you are currently invoking strlen().
In C,You can only free the memory which is allocated by malloc , calloc or realloc.
So freeing the memory other than that is Undefined behaviour
I your case it's not clear that what is *des. and whether it is allocated by the malloc , calloc or realloc.
Or you have done like this in calling enviroment
char des[20]= "hello , world \n";
or may be
char * des= "hello . world \n";
As was pointed out to you in the comments, your function needs documentation. It works exactly as you want it to if the input is correct:
This works:
char * str1 = "hello";
char * str2 = malloc(6); // Of course this is pointless since you'll free it anyway
str_cpy(&str2, str1);
So does this:
char * str1 = "hello";
char * str2 = NULL;
str_cpy(&str2, str1);
But this:
char * str1 = "hello";
char * str2;
str_cpy(&str2, str1);
Or this:
char * str1 = "hello";
char str2[6];
str_cpy(&str2, str1);
Or this:
char * str1 = "hello";
char * str2 = str1;
str_cpy(&str2, str1);
Will crash and burn. You need to note all the pre/post condidtions of your function in the comments.
void str_cpy(char **des,char* src){
if(*des || *des==src)
free(*des);
*des = (char*)malloc(sizeof(char)*(strlen(src)+1));
if(!*des)
return ;
memcpy ( *des, src, (strlen(src)+1)*sizeof(char) );
}
Freeing before malloc is not necessary, it may contain some garbage value, and you are freeing that garbage which results (Core Dumped).
If ( *des == src ) and you free des, which mean 'src' is also freed, and below you are using src in memcpy.
Correct Approach:
void str_cpy(char **des,char* src){
*des = (char*)malloc(sizeof(char)*(strlen(src)+1));
if(!*des)
return ;
memcpy ( *des, src, (strlen(src)+1)*sizeof(char) );
}

pointers to structs in c

struct TokenizerT_ {
char* separators;
char* tks;
char* cur_pos;
char* next;
};
typedef struct TokenizerT_ TokenizerT;
TokenizerT *TKCreate(char *separators, char *ts)
{
TokenizerT *tokenizer;
tokenizer = (TokenizerT*)malloc(sizeof(TokenizerT));
//some manipulation here
tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char));
tokenizer->tks=str;
printf("size of tokenizer->tks is %zu\n", strlen(tokenizer->tks)); //this prints out the correct number (e.g. 7)
return tokenizer;
}
int main(int argc, char **argv)
{
TokenizerT *tk = TKCreate(argv[1], argv[2]);
printf("tk->tks: %zu\n", strlen(tk->tks)); //HOWEVER, this prints out the wrong number (e.g. 1)
}
As seen from the above code, I'm working with pointers to structs. For some reason I am not receiving back the correct length for tk->tks. I cannot understand this because it should be the same size as tks in my TKCreate function. Can someone explain this please?
I suspect str, the definition of which is not shown in your code snippet, is a local variable defined in TKCreate(). If so, you're assigning tokenizer->tks to have the value of str, which points to a proper string inside the scope of TKCreate() but upon exiting TKCreate(), the stack contents (including parameters and local variables) are freed and wiped out so when you try to reference that pointer outside the scope of TKCreate() all bets are off.
One plausible fix is to allocate the storage for tokenizer->tks dynamically, so it persists after you exit TKCreate(). I see you do that with a call to malloc but then you overwrite that with an explicit assignment from str. Instead you should copy the contents of str (using strcpy) into the dynamically allocated memory via: strcpy(tokenizer->tks, str);
You should strcpy the contents of str to tokenizer->tks, because when you use the assign operator, you're losing the pointer malloc gave you, creating a memory leak and pointing tokenizer->tks to a local variable, which will be destroyed after the function's return.
So, the approach would be something like this:
tokenizer->tks = (char *)malloc ((strlen(str) + 1) * sizeof(char));
strcpy(tokenizer->tks, str);
Another thing:
Don't forget to free ->tks before you free tk itself.
So, after the printf, you should use:
free(tk->tks);
free(tk);
There's no problem in not freeing the structure and the string (which is in another memory location and not inside the structure's memory space, that's why you have to free they both), if your program is that small, because after it's executed, the program's memory will be wiped out anyways. But if you intend to implement this function on a fully-working and big program, freeing the memory is a good action.
It is not clear where str is defined, but if it is a local variable in the function, your problem is likely that it goes out of scope, so the data gets overwritten.
You're leaking memory because you've forgotten to use strcpy() or memcpy() or memmove() to copy the value in str over the allocated space, and you overwrite the only pointer to the newly allocated memory with the pointer str. If you copied, you would be writing out of bounds because you forgot to allocate enough space for the trailing null as well as the string. You should also check that the allocation succeeds.
Bogus code:
tokenizer->tks = (char*) malloc (strlen(str)* sizeof(char));
tokenizer->tks = str;
Fixed code:
size_t len = strlen(str) + 1;
tokenizer->tks = (char *)malloc(len);
if (tokenizer->tks == 0)
...error handling...
memmove(tokenizer->tks, str, len);
Using memmove() or memcpy() can outperform strcpy() handily (see Why is Python faster than C for some illustrations and timing). There are those who would excoriate you (and me) for using the cast on malloc(); I understand why they argue as they do, but I don't fully agree with them (and usually use the cast myself). Since sizeof(char) is 1 by definition, there's no particular need to multiply by it, though there's no harm done in doing so, either.

Can incrementing a pointer cause leaked memory?

Does the following code contain a memory leak of the first three characters in the string?
char * str = (char*)malloc(21 * sizeof(char));
strcpy(str, "01234567890123456879");
str = str + 3;
free(str);
Thanks.
Its worse than a leak, you are not supposed to call free with a pointer not returned from malloc (or realloc/calloc). You could get a leak, or a crash, or who knows what else... What you do is undefined behavior.
Yes, It leaks.
free expects a pointer that was returned by malloc/realloc/calloc. Since, you have changed, it certainly leaks.
You might want to prove this out by testing, but I believe the answer to your question is that incrementing a pointer can cause undefined behaviour, although you are seeing a memory leak.
I am saying this, because nowhere in your example does it appear that you have preserved the original pointer to the allocated memory. It is possible free could do the wrong thing with the pointer pointing to somewhere other than the base address.
To be sure you would need to
1) Look at RAM in use on your system, with as little else running as possible
2) Run the program a few times, and
3) Then look at memory use again.
Then try all that again by altering your code as follows:
char * mem_ptr = (char*)malloc(21 * sizeof(char));
char * str = mem_ptr;
strcpy(str, "01234567890123456879");
str = str + 3;
free(mem_ptr);

Resources