How to free a union array in C? - c

I have a function that return me a union array, I need to free a union array after I use it.
An updated code :
This is a struct
typedef union _data {
float F;
uint8_t B[4];
} floatCharFunction;
This is a Read Function:
void HW_SWversion(version state,floatCharFunction* ver)
{
floatCharFunction fVersionRead[2] = {0,0};//SW-HW
*ver = *fVersionRead;
//floatCharFunction SW,HW;
if(state == SAVE_VERSION)
{
FLASH_ERASE(_4KB,VERSION_BASE_ADDR);
fVersionRead[0].F =VERSION_SW;
fVersionRead[01].F =VERSION_HW;
FLASH_WRITE(fVersionRead[0].B,VERSION_BASE_ADDR,VERSION_SIZE_IN_BYTES/2);
FLASH_WRITE(fVersionRead[1].B,VERSION_BASE_ADDR+VERSION_SIZE_IN_BYTES/2,VERSION_SIZE_IN_BYTES/2);
}else if(state == READ_VERSION)
{
FLASH_READ(VERSION_BASE_ADDR,fVersionRead[0].B, VERSION_SIZE_IN_BYTES/2);
FLASH_READ(VERSION_BASE_ADDR+VERSION_SIZE_IN_BYTES/2,fVersionRead[1].B, VERSION_SIZE_IN_BYTES/2);
//u16VersionRead = (versions[0] << 8) | versions[1];
}else return;
}
This is a Main :
main()
{
floatCharFunction* ver = malloc(2*sizeof(*ver));
if (ver == NULL) {
//printf("out of memory\n");
exit(1);
}
HW_SWversion(READ_VERSION,ver);
free(ver);
}

There are two problems in your code:
ver = HW_SWversion(READ_VERSION); reassigns ver, leaking the memory you allocated in the previous line
HW_SWversion returns a pointer to an automatic variable that immediately goes out of scope. Consequences of accessing this variable are undefined.
The easiest change here would be to change HW_SWversion to update a pointer to a client allocated instance.
void HW_SWversion(version state, floatCharFunction* ver)
{
/* assign version info */
}
int main()
{
floatCharFunction ver[2];
HW_SWversion(READ_VERSION, &ver);
}
Or, if you want to use dynamically allocated memory
void HW_SWversion(version state, floatCharFunction* ver)
{
/* assign version info */
}
int main()
{
floatCharFunction* ver = malloc(2*sizeof(*ver));
if (ver == NULL) {
printf("out of memory\n");
exit(1);
}
HW_SWversion(READ_VERSION, ver);
free(ver);
}

As I can see, the
floatCharFunction fVersionRead[2];//SW-HW
Is a local variable and usage:
ver = HW_SWversion(READ_VERSION);
In this case is an undefined behavior because fVersionRead is allocated on stack. No one guarantees that result will be correct.

Decide, stack or heap? (but not both)
/* Stack (Note static) */
static floatCharFunction fVersionRead[2]; //SW-HW
floatCharFunction *pVersion = fVersionRead;
return pVersion;
/* Heap */
floatCharFunction *ver = (floatCharFunction *)malloc(2*sizeof(floatCharFunction));
The keyword static extends the lifetime of a variable outside the function.
If you go for stack don't call free, else free(ver); is what you need.

i need to free an union array after i use it.
by the time you even get to using it, the array is already "freed". Since it's a local variable with automatic storage duration, it goes out of scope and is deallocated when the function returns. So, you are using a pointer to a nonexistent object, so your code currently invokes undefined behavior.
You'd be better off malloc()ing the array and returning a pointer to its first element. Then, of course, you will need to free() it (just like in your code) afterwards.
But I'm sure any introductory C book could have shown you this.

Problems with your code are::
You are mallocing some memory for floatCharFunction in your main.
You are not giving this memory to your HW_SWversion to populate or modify.
You are using some memory for floatCharFunction on stack in your HW_SWversion,
scope:: local to HW_SWversion.
You are returning the memory address of an automatic variable.
The local variable goes out-of-scope as soon as HW_SWversion exits.
You are trying to free that out-of-scope memory which will cause Undefined Behaviour.
Your malloced memory pointer value is lost, so memory leak.
Solution::
Either do not use malloc and pass the memory as parameter to HW_SWversion like this::
void HW_SWversion(version state, floatCharFunction* ver)
{
*ver = /* assign version info */
}
int main()
{
floatCharFunction ver[2];
HW_SWversion(READ_VERSION, &ver);
}
OR
If you want to use dynamic allocation::
floatCharFunction* HW_SWversion(version state)
{
floatCharFunction *pVersion = malloc(2*sizeof(floatCharFunction));
return pVersion;
}
main()
{
//
floatCharFunction *ver = HW_SWversion(READ_VERSION);
free (ver) ;
}

maybe you can try this
free(ver)
the system remembers the memory location of ver, and knows the size of memory of the this ptr holds

Related

c will a const *char function memory leak? [duplicate]

I am using json-c library to send json-object to client.And I notice there is no native function to release the memory which json_object_to_json_string allocate.Does the library release it automaticlly? OR I have to "free(str)" to avoid memory leak?
I tried to read its source code but it makes me unconscious...So anybody know this?
It seems that you don't need to free it manually.
I see that this buffer comes from within the json_object (see the last line of this function):
const char* json_object_to_json_string_ext(struct json_object *jso, int flags)
{
if (!jso)
return "null";
if ((!jso->_pb) && !(jso->_pb = printbuf_new()))
return NULL;
printbuf_reset(jso->_pb);
if(jso->_to_json_string(jso, jso->_pb, 0, flags) < 0)
return NULL;
return jso->_pb->buf;
}
The delete function frees this buffer:
static void json_object_generic_delete(struct json_object* jso)
{
#ifdef REFCOUNT_DEBUG
MC_DEBUG("json_object_delete_%s: %p\n",
json_type_to_name(jso->o_type), jso);
lh_table_delete(json_object_table, jso);
#endif /* REFCOUNT_DEBUG */
printbuf_free(jso->_pb);
free(jso);
}
It is important to understand that this buffer is only valid while the object is valid. If the object reaches 0 reference count, the string is also freed and if you are using it after it is freed the results are unpredictable.

Why is my structure zeroed out even when I did not return a object?

Ive been dabbling in some c code and initialized a cat structure like so
typedef struct
{
int age;
char *name;
char *favoriteQuote;
} Cat;
I created two functions, one to initialize the cat object and one to zero out the memory that look like so
Cat initialize_cat_object(void)
{
Cat my_cat;
my_cat.age = 3;
my_cat.favorite_quote = "A day without laughter is a day wasted";
my_cat.name = "Chester";
return my_cat;
}
Cat destroy_cat_object(void)
{
Cat my_cat;
memset(&my_cat, 0, sizeof(my_cat));
//--forgot to return 'my_cat' here--
}
my main function looks like so
void main(void)
{
Cat my_cat;
my_cat = initialize_cat_object();
printf("Creating cat\n")
printf("Name: %s\nFavoriteQuote: %s\nAge: %d\n", my_cat.name,
my_cat.favorite_quote, my_cat.age);
my_cat = destroy_cat_obect();
printf("CAT DESTRUCTION\n");
printf("Name: %s\nFavoriteQuote: %s\nAge: %d\n", my_cat.name,
my_cat.favorite_quote, my_cat.age);
}
The output of the program was the expected output of
It wasn't until I went back to the source code that I noticed I had forgotten to return the Cat object who's memory was zeroed out, However the program still shows the expected output, but if I try to omit the return statement of the 'initialize_cat_object' function, the output of the data is corrupt
The only thing I can think of is that 'destroy_cat_object' returns the zeroed out memory, but how could this be?
destroy_cat_object doesn't have a return statement. C11 6.9.1p12 says:
If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.
It is however perfectly OK C-standard-wise to have a function with a return type but which doesn't have a return statement before the closing bracket. Calling such a function is also perfectly OK.
What is not OK however is using the return value of the function call if the function didn't terminate with a return statement that explicitly returns a value.
You might want to enable some extra diagnostics in your compiler settings if you do not get a message for this.
Registers aside. There are three places where your data may be stored in C:
Constant data which is read only and is stored inside your binary;
Data on the stack;
Data stored in dynamic memory retrieved by the means of memory allocation functions.
In your case we are talking about stack. Stack is a LIFO queue elements of which are valid and accessible so long as they are not popped out of it. So if you have a function like this:
typedef struct {
int a_val;
float b_val;
char c_val;
} a_t;
a_t* func(void) {
a_t a = {1, 1., 'a'};
return &a;
}
"a" would be residing in stack until func returns, hence after func returns it's pointer becomes invalid and points someplace in stackspace. On the most systems stack won't be zeroed therefore until some other data overwrites it it may be possible to get some data by that pointer, which may be misleading.
So what should you do? Something like this:
void initialize_cat(Cat*);
void clear_cat(Cat*);
int main() {
Cat my_cat;
initialize_cat(&my_cat);
// do kitty stuff
clear_cat(&my_cat); // cat's private data must not be compromised
}
When function returns a structure this is actually achieved with a cooperation from a caller (I'm talking SysV x64 ABI here and may be wrong for other cases). Basically caller allocates space on stack enough to store the returned structure and passes pointer to it as an implicit first parameter. callee is using this pointer to write data later on.
So the two cases:
Cat callee(void) {
Cat my_cat = { .age = 5 };
return cat;
}
void caller(void) {
Cat my_cat = callee();
}
And:
void callee(Cat *my_cat) {
my_cat->age = 5;
return cat;
}
void caller(void) {
Cat my_cat;
callee(&my_cat);
}
Are pretty much the same.

Data saved in Stack content keep changing, can't increment

So here is my issue, I have been trying to figure this out for the last 5 hours, I have a header file, a tester file, and a c source file. I would really like to understand what is happening and why so I can avoid the issue in the future. The header file declares the struct but does not define it:
typedef struct Stack *StackP;
and in my source file, Stack.c I have defined the stack:
struct Stack
{
int top;
int capacity;
int count;
ItemT items;
};
where ItemT is defined as char *
in the tester file, the call goes:
StackP stackPtr = newStack();
and what I have for my newStack function located in the c source file is:
StackP newStack(void) {
struct Stack stack1;
StackP stackPtr = &stack1;
(stackPtr->items) = (ItemT)malloc(DEFAULT_CAPACITY*sizeof(ItemT));
(stackPtr->top) = -1;
(stackPtr->capacity) = DEFAULT_CAPACITY;
(stackPtr->count) = 0;
fprintf(stderr, "\nSuccesfully allocated memory to items...\n");
return stackPtr;
}
now, my push function is:
void pushStack(StackP stackPtr, ItemT item) {
if ((stackPtr->count) == (stackPtr->capacity)) {
fprintf(stderr, "\nERROR: Full stack.\n");
}
else {
stackPtr->items = item;
fprintf(stderr, "\nSuccessfully pushed %s on to the stack...\n", stackPtr->items);
(stackPtr->items)++;
(stackPtr->top)++;
(stackPtr->count)++;
}
}
My question is this: Have I don't something wrong in any of these blocks of code.
If I call a function that says:
return (stackPtr->count);
it will return a random set of numbers instead of 0, or 1. For instance, if I push 2 strings to the stack, instead of count being 2, count is 479622 or some other random long number. Why is this happening?
Again, I would like to know what I'm doing wrong and not just correct syntax because I really HAVE to understand this.
The program has undefined behaviour as it is returning the address of a local variable from a function:
StackP newStack(void) {
struct Stack stack1;
StackP stackPtr = &stack1;
return stackPtr;
}
stack1 no longer exists when newStack exits. stackPtr must point to dynamically allocated memory if it is to exist beyond the scope of the function:
StackP newStack(void) {
struct Stack stack1;
StackP stackPtr = malloc(sizeof(*stackPtr));
if (stackPtr)
{
}
return stackPtr;
}
See Do I cast the result of malloc?

c - using a pointer returned from function in a function call

Is the following usage of pointers in functions call is a memory leak:
bson_t * parse_json(const char * json_fields){
bson_error_t error;
bson_t *bson_fields = bson_new_from_json((unsigned char *)json_fields, -1, &error);
if (!bson_fields) {
log_die("Error: %s\n", error.message);
} else {
return bson_fields;
}
log_die("Error: something bad happend in parse_columns");
return bson_fields; // this should never be reached ...
}
The following code works, but what happens to the pointer from parse_json here? Is this a memory leak?
bson_concat(fields, parse_json(json_fields));
The mongodb C-API offers the function bson_destory:
bson_destroy(fields);
I am wondering maybe it's better to explicitly free the memory of new_fields:
bson_t *new_fields = parse_json(json_fields);
bson_concat(fields, new_fields);
bson_destroy(new_fields);
While this example uses mongodb c-api, I am also trying to understand the general case.
some_type * pointer_returner(){
some_type *var;
...
return var;
}
do_something(pointer_retuner());
Is the call above causing a memory leak?
Yes, you need to call bson_destroy to deallocate your structure object it is no longer used.
From bson_destroy documentation:
The bson_destroy() function shall free an allocated bson_t structure.
This function should always be called when you are done with a bson_t unless otherwise specified.

How can I view a static variable from outside the function that defines it in Visual Studio?

I am looking at a crash dump, and an important clue to how this crash occurred may be inside the value of a static variable (an integer in this case) inside a function. The problem is that the function with that static variable is is not in my call stack where the crash occurred so I can't just look at it directly. Is there a way to view the contents of this variable from the debugger from outside the function that declares it?
Edit:
Sample code has been requested
int funcitonWithStaticVar()
{
static int iRetVal;
if (iRetVal == 0)
{
iRetVal = initializeValue();
}
return iRetVal
}
void functionThatCrashes()
{
// Crash occurs in this function. The
// static variable in the other function
// may hold an important clue as to why
}
int foo()
{
functionWithStaticVar();
functionThatCrashes();
}
You can determine the address of the static variable by viewing the disassembly of the function that accesses it.

Resources