free variable when use malloc in c - c

char **loadValues()
{
char **toReturn;
int i;
toReturn = malloc(5 * sizeof(char *));
for (i = 0; i < 5; i++)
{
toReturn[i] = malloc(25); //Change the size as per your need
strncpy(toReturn[i], "string", i + 1); //Something to copy
}
return toReturn;
}
I copied above part of the code. In it, the "toReturn" variable is initialized by using malloc. Don't we have to "free" this "toReturn" variable?
Don't we have to free these variables when we return them in C. I still couldn't find a clear answer and I can't find a way to free it when I return it. Can someone explain it to me?

I assume that your question is: how does the function that calls loadValues and receives the pointer it returns, can free the loaded values.
If we leave loadValues as it is now, the best solution is to create another function, called freeValues and call it when we are done with the values:
void freeValues(char **values)
{
for (i = 0; i < 5; i++)
{
free(values[i]);
}
free(values);
}
Then you can do something like this in your main program:
char **values = loadValues();
// ... use values for something
freeValues(values);
Another option, is to allocate toReturn using a single call to malloc, in which case it can be freed simply by calling to free.

You cannot free the allocated memory inside the function and return that data so that it can be used outside the function. But you still can free() the memory outside the function.

Don't we have to "free" this "toReturn" variable?
Yes, eventually you'd want to free the memory after you're done with it.
I still couldn't find clear answer and I can't find a way to free it when I return it. Can someone explain it to me?
When you use the function you assign it to a new pointer, you can use this pointer, not only to access the memory block you returned, but also to free it, example:
int main()
{
char** values = loadValues();
// do something with values
// don't need them anymore
for (int i = 0; i < 5; i++){
free(values[i]);
}
free(values);
}
Note that strncpy(toReturn[i], "string", i + 1); is likely not what you want, in each iteration you are copying only from 1 to 5 characters respectively, not the entire string, and more importantly, not the null terminator.
The third argument of strncpy should be the length of "string" plus 1 more byte for the null terminator, so 7 in this case. Alternatively, if want to copy only part of ther string, you have to null-terminate it yourself.
If the goal is to copy the entire string, you can let the compiler do that for you:
//...
toReturn = malloc(5 * sizeof(char *));
for (i = 0; i < 5; i++)
{
toReturn[i] = strdup("string"); // duplicate string and store it in toReturn[i]
}
//...
Of course you still need to free it yourself like in the first situation.

Related

Memory leak in c due to the malloc

I am getting the memory leak due to first malloc call. I tried to comment out and free but there is no way that I can fix it.
The code wants to parse the query than put the information inside the map. At the same time it is going to update struct too
row_ = atoi(strtok(NULL,",:"));
col_ = atoi(strtok(NULL,",:"));
}
}
For starters this for loop
for(int j = 0; j < strlen(query); j++){
if(!strcmp(&query[j], ",")){
count++;
}
}
does not make a sense. It seems you mean instead
for(int j = 0; j < strlen(query); j++){
if( query[j] == ',')){
count++;
}
}
You allocated memory and its address is assigned to the pointer type.
char* type = malloc(sizeof(char *));
// char* char_name= (char *)malloc(1);
then the pointer was reassigned
type = strtok(query, ",:");
So the address of the allocated memory is lost and you have a memory leak.
This commented declaration
char* char_name= (char *)malloc(1);
also invokes a memory leak due to the statement
char_name = strtok(NULL,",:");
This statement
char_name = realloc(char_name, sizeof(char_name)+1);
does not make a sense at least because sizeof( char_name ) is equivalent to sizeof( char * ). It seems you mean at least
char_name = realloc(char_name, strlen(char_name) + 2 );
But in any case you may not reallocate the memory using the pointer because it does not point to a dynamically allocated memory after this statement
char_name = strtok(NULL,",:");
examine these 2 lines of code
char* type=malloc(sizeof(char *)); <<<<<<=======
// char* char_name= (char *)malloc(1);
int row_,col_;
int count =0;
for(int j=0;j<strlen(query);j++){
if(!strcmp(&query[j],",")){
count++;
}
}
count=(count+1)/3;
type = strtok(query, ",:"); <<<<<<=======
You malloc some memory, do nothing with it and then overwrite the pointer. So now there is no way to free it or use it.
As far as I can see you just need
char*type = NULL;
and take out the frees of type too.
Note - I have not verified the rest of the code. Just answered your leak question. The way you are using strtok is certainly not idiomatic. And I suspect that you think
type = strtok(query, ",:");
copies the first token into the buffer pointed at by type. It does not, what you need is this
type = strdup(strtok(query, ",:"));
Likewise the assignments in the loop
char_name = strtok(NULL,",:");
char_name = realloc(char_name, sizeof(char_name)+1);
are very wrong. You cannot realloc the return of strtok. Again you need
char_name = strdup(strtok(NULL,",:"));

C program crashes after freeing the pointers in an array of char *

I'm a student learning C and I was puttering around with arrays of strings and malloc().
I have the following code that is supposed to load an array of strings (statically created) with dynamically created strings (please forgive / correct me if my terminology does not align with the code I have).
The problem is, once I go to free that memory, I get the following error: free(): invalid pointer
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#define RAM_SIZE 5
char* ram [RAM_SIZE];
int next_free_cell = 0;
void freeAndNullRam(){
for (int i = 0 ; i < RAM_SIZE ; i++){
printf("%d\n", i);
free(ram[i]);
ram[i] = NULL;
}
}
int main(int argc, const char *argv[])
{
for (int i= 0; i < RAM_SIZE; i++){
ram[i] = (char*)malloc(sizeof(char*)*5);
ram[i] = "aaaa";
}
for (int i= 0; i < RAM_SIZE; i++){
int empty = (ram[i] ==NULL);
if(!empty){
printf("%s\n", ram[i]);
}
}
freeAndNullRam();
for (int i= 0; i < RAM_SIZE; i++){
int empty = (ram[i] ==NULL);
printf("%d\n", empty);
}
return 0;
}
I know the issue is definitely in the freeAndNullRam() function (obviously), but I don't understand why. My understanding is that at compile time, an array of 5 pointers to char arrays is created, but to actually fill the cells of the array, I need to malloc them some memory. Why does the program complain when I free the pointers in the array, but not when I give them memory?
Thanks!
ram[i] = "aaaa"; reassigns the pointers at a[i] to point to static memory, discarding the result of malloc. Later on you pass those pointers to free, which fails because they were not the result of an *alloc function.
Use strcpy to instead copy the string from static memory into your allocated destination.
strcpy(a[i], "aaaa")
Here's a reworked version of your code to be more idiomatic C:
#include <stdio.h>
#include <stdlib.h>
// Create an array of arbitrary size
char* alloc_array(size_t size) {
// calloc() will give you a pre-zeroed (NULL) allocation, malloc() may not
return calloc(size, sizeof(char*));
}
// Clears out all entries in the array, leaving only NULL
void clear_array(char* array, size_t size) {
for (size_t i = 0; i < size; ++i) {
// free(NULL) doesn't do anything, and is easier than a test
free(array[i]);
array[i] = NULL;
}
}
// Clears, then frees the array
void free_array(char* array, size_t size) {
clear_array(array, size);
free(array);
}
int main(int argc, const char *argv[])
{
// Whenever possible use local variables, not global variables
size_t size = 5;
char* entries = alloc_array(size);
for (size_t i = 0; i < size; ++i) {
// Make a copy with strdup() so this can be released with free()
// later on. A string like "..." is static, it was never allocated.
entries[i] = strdup("aaaa");
}
for (size_t i = 0; i < size; i++) {
// Express conditions in the if statment directly
if (entries[i] != NULL) {
printf("%s\n", ram[i]);
}
}
clear_array(entries);
for (size_t i = 0; i < size; i++) {
printf("%d\n", entries[i] != NULL);
}
// Don't forget to release any allocated memory.
free_array(entries);
return 0;
}
There's a lot of bad habits in your original code you should work to expunge as quickly as possible so these things don't take root. In particular, global variables are a huge problem that need to be avoided.
One thing to remember is unless something was explicitly allocated with malloc() or a variant like calloc(), or was given to your code with an understanding that it was allocated in such a fashion, you should not call free() on it.
Not every pointer was allocated dynamically, and not every dynamically allocated pointer was allocated with malloc(). Some C code can be very confusing as a result of this.
C's syntax strongly suggests that "aaaa" is a "string". People even talk of this syntax that way: they call it "strings". But "aaaa" is nothing such. It's the unfortunately named string literal, which is not a string - neither in C nor in C++. A char * is not a string either - it's a pointer-typed value. It's used to represent strings, but itself is not a string - not even close.
You have quite reasonably expected that "aaaa" might behave like any other rvalue of the "obvious" type. Alas, while 1 is an integer literal of type int, "aaaa" is a string literal of a pointer type const char * - its value is not a string, but a pointer!
It's as if when you wrote 42, C gave you a const int * pointing to 42. That's what "string" literals do. That's the awfully deplorable side of C :(
In C++, there actually is a string type (std::string), and you can even write literals of that type with a new syntax introduced in C++11: "aaaa"s is an rvalue* of type std::string, and you can assign them exactly as you would expect of any other value type like int.
Since you're already thinking a bit like in C++, perhaps you can investigate that language next. It takes much less effort to do plenty of basic things in C++ compared to C.
*technically rvalue reference

How to change a function which returns local variable

How should I change the variable BinaryNumber, so the function will not give me a warning message.
I understand that I can't return a address of a local variable cause of the memory. Should I use malloc or what do you think how should I change the variable BinaryNumber so I can return it?
char *Functoin_chang_string_ToBinary(char *Line) {
char *space = " ", *point = ",";
char BinaryNumber[Array_Size] = { "000000000000000" };
char *word = strtok(Line,"\"");
int num = 0, flag = 2, j = 11;
for (int i = 0; i < strlen(Line) - 1; i++) {
if (word[i] == '"') {
flag--;
i++;
}
num = word[i];
j = 14;
while (num != 0) {
BinaryNumber[j--] += (num % 2);
num /= 2;
}
printf("%s\n", BinaryNumber);
Fill_Struct_Binary_Machine_Code("", BinaryNumber);
strcpy(BinaryNumber, "000000000000000");
}
printf("%s\n", BinaryNumber);
Fill_Struct_Binary_Machine_Code("", BinaryNumber);
return BinaryNumber;
}
Although you can use malloc() to allocate a buffer for the BinaryNumber string (which will, of course, need to be released by the caller using free()), a much simpler method would be to use the strdup() function.
This will allocate the exact amount of memory required to duplicate the string given as its argument (including the nul terminator) and copy the actual string data in one call.
Thus, you could just change your function's return statement to this:
return strdup(BinaryNumber);
Of course, the caller will still need to call free() on the returned data when it's done with it (strdup allocates the memory in a manner compatible with the malloc function).
Yes, you can return a pointer to memory allocated by malloc.
Alternatively, you could change the function prototype of Functoin_chang_string_ToBinary to the following:
void Functoin_chang_string_ToBinary(char *Line, char *BinaryNumber );
That way, the calling function can allocate the memory as a local array and pass a pointer to that array to the function Functoin_chang_string_ToBinary, for example like this:
BinaryNumber[Array_Size];
Functoin_chang_string_ToBinary( Line, BinaryNumber );
However, when passing pointers to memory buffers like this, it is also important to make sure that the called function does not write past the boundary of the buffer. For this reason, it would be better if the called function knew the size of the buffer it is being passed. Therefore, you may want to also pass the size of the buffer to the function, by changing the function prototype to the following:
void Functoin_chang_string_ToBinary(char *Line, char *BinaryNumber, int BinaryNumberSize )
The code of the calling function would then be changed to the following:
BinaryNumber[Array_Size];
Functoin_chang_string_ToBinary( Line, BinaryNumber, ArraySize );
That way, the called function can determine how large the memory buffer is, by accessing its third parameter.
Change your function signature to accept a target to save it to:
char *Function_chang_string_ToBinary_r(char *Line, char *out, size_t out_size )
Whenever you do this it is far safer to provide a maximum output size as not to overrun the target. You would also use size sensitive copies for copying to the target limiting copies to the smaller of the target area our your internal working area.
Look at the strtok() vs strtok_r() function for a model for a function that switched to this model to be thread safe.
Yes, malloc() would work but I tend to consider malloc() calls within a function a bad idea, expecialy for short strings. [1] it leaves callers open to memory leaks if they forget to free the memory you allocated and [2] if the function is called frequently malloc() can have a high overhead. Passing in a NULL pointer could make the function call malloc() anyway to return the new address. This way any memory leak or performance bugs would then be on the caller.

C. The difference between realloc in double array and char array

I have to dynamically increase a length of double array. I know, how to do it with char array, so I tried this:
int main() {
char * tmp = NULL;
for (int i = 1; i <= 4; i++) {
tmp = realloc(tmp, i * sizeof(char));
tmp[i] = 'i';
}
puts("char OK");
double * tmp1 = NULL;
for (int i = 1; i <= 4; i++) {
tmp1 = realloc(tmp1, i * sizeof(double));
tmp1[i] = 0;
}
return 0;
}
The first array works fine. But the second one crushes with message realloc(): invalid next size.
These are my 2 questions:
Why this way doesn't work in a double array?
How to dynamically increase the size of array of doubles?
UPD:
removed a typo
TL;DR: Both the snippets are wrong, the first one appears to work because of undefined behavior.
To elaborate, the problem is with your indexing logic. C uses a 0-based indexing. So, inside the loop which is staring the iteration from value of i as 1, by using
tmp[i] = .......
you're trying to access invalid memory, at this point, only access up to tmp[i-1] is valid.
You need to use tmp1[i-1] = 0;, and likewise.
That said,
Always check for the success of the memory allocator functions before using the returned pointers.
Never use the form
pointer = realloc (pointer, ......)
because, in case realloc call fails, you'll end up losing the original pointer, too.
Quoting C11, chapter ยง7.22.3.5
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
and
[....] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Always use a temporary pointer variable to store the return value of realloc(),
check for the success of the call [not-null return value] and
then assign it back to the original variable, if needed.

freeing substring without doing double free in c

Yesterday I asked a similar question regarding how to free allocated memory for a sub-string. Now I have one more question regarding the same problem (involving a set of conditions), how could I free the following sub-string without doing double free?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st_ex {
char product[16];
float price;
};
struct st_temp {
char *prod;
};
char *temp = NULL;
// from stackoverflow
char* substr( const char* source, size_t start, size_t end )
{
char* dest = malloc( end - start + 1) ;
memcpy( dest, &source[start], end - start ) ;
dest[end - start] = 0 ;
return dest ;
}
int main()
{
struct st_ex structs[] = {{"mp3 player", 2.0f}, {"plasma tv", 20.0f},
{"notebook", 10.0f}, {"smartphone", 49.9f},
{"dvd player", 10.0f}, {"matches", 0.2f }};
struct st_temp **temp_struct;
size_t j, i;
temp_struct = malloc(sizeof *temp_struct * 6);
for (j = 0; j < 6; j++)
temp_struct[j] = malloc(sizeof *temp_struct[j]);
size_t structs_len = sizeof(structs) / sizeof(struct st_ex);
// NOTE: that structs_len may vary in size - not just 6
for(i=0; i<structs_len; i++){
if (i == 0)
temp_struct[i]->prod = "+";
else if(i == 1)
temp_struct[i]->prod = "Bar";
else if(i == 5)
temp_struct[i]->prod = "Foo";
else {
temp = substr(structs[i].product, 0, 4);
temp_struct[i]->prod = temp;
}
}
for(i=0; i<6; i++ )
printf("%s\n",temp_struct[i]->prod);
for(i = 0; i < 6; i++ ){
/* can I do something like this? */
/*if (i != 0 || i != 1 || i != 5)*/
free(temp_struct[i]->prod);
free(temp_struct[i]);
}
free(temp_struct);
return 0;
}
The problem is that sometimes you set temp_struct[i]->prod to a quoted string ("Bar") which you cannot free and sometimes to the result of a substr call, which you must free.
The easiest solution is to always set it to a string that you must free.
temp_struct[i]->prod = new_string("Bar");
where
char* new_string( const char* source )
{
char* dest = malloc( strlen(source) + 1 ) ;
strcpy(dest, source);
return dest ;
}
or, you have to keep track if you need to free or not
struct st_temp {
char *prod;
int prod_must_be_freed;
};
set prod_must_be_freed to 0 or 1 and check that before you free.
And, finally, the whole thing would be improved by using functions to manipulate these structs rather than just fiddling with them directly. Then you could make a free_st_temp(st_temp*) that checked if prod should be freed, and then freed the struct. Your loop would be
for(i = 0; i < 6; i++ ){
free_st_temp(temp_struct[i]);
}
Substrings do not take up extra memory. They are pointers to parts of already existing strings.
Yes, given that your substr is allocating the memory for the substring with malloc, it's reasonable (necessary, really) to free that memory when you're done with it. That said, I think the way you're doing things right now is extremely fragile and error-prone (to put it mildly). If you have any choice at all, I'd allocate the strings for all the prod members the same way -- if you can't allocate them all statically, then allocate them all dynamically, so when you're freeing structures, you can do so uniformly. Trying to assure that you keep the subscripts matched up to free prod if and only if it was allocated dynamically is practically begging for trouble.
You have an additional problem. When you do temp_struct[i]->prod = "Bar"; You are assigning a const char* to prod. That pointer cannot be freed (the most likely outcome is a crash). So if you want to have your code set up this way such that prod can point to either dynamic memory that you got from malloc or to a constant string literal, you need to also keep track of which one it is and only free the dynamic memory.
The condition in your comment would technically work, but would be very poor form. The best idea is to not mix and match string types in the same pointer. But if you insist on doing it that way, then an improvement would be to add another variable to your struct that is set true when prod needs to be freed and false when it does not.
Yes, although you will want to uncomment that if, and change the conditions in the if to be joined with && rather than || (otherwise it will always be true -- every number is either not equal to zero or not equal to one!)
The substrings stored in temp_struct[i]->prod for i other than 0, 1, and 5, were allocated inside the substr function with malloc, so you can and should deallocate them with free.
Similarly, each temp_struct element was allocated with malloc, and so can and should be deallocated with free.
I'm not sure where you think the double free would be coming from. Are you thinking that when you call free(tmp_struct[i]) the memory pointed to by tmp_struct[i]->prod will also be freed? That isn't the case. When you free a pointer to a structure that contains pointers, the memory for the structure's pointers themselves is deallocated (being that it is part of the structure), but the memory being pointed to by those pointers is not, and must be deallocated seperately (since it is external to the structure). Aside from the mistake in the if condition, the way you have it written is the correct way to do this.

Resources