Memory leaks

So I am looking at a few Arduino libraries that I downloaded, and making some minor changes to them,
to meet my project requirements,
and I came to the realisation that they can't possibly be working because of memory leaks.
But they do work.

I usually use Java for other things and don't have to worry about garbage collection and memory
leaks.

But I did use C++ for many years, when I look at these Arduino libraries carefully with C in my brain,
it looks like these libraries cannot work reliably. But it appears that they do.

Do Arduino C libraries have to comply with normal C rules about the scope, allocation and deallocation
of data ? Or can you be slack like Java and it just works ?

Do Arduino C libraries have to comply with normal C rules about the scope, allocation and deallocation
of data ?

Yes.

Or can you be slack like Java and it just works ?

Nope.

I came to the realisation that they can't possibly be working because of memory leaks.

Got some examples?

There is a known bug with free(), that's the only thing I know of.


Rob

Please post the code of a library that "shouldn't work but does", and point out what's wrong with it. :slight_smile:

Well I don't want to be critical of other people's library.

One function is supposed to return an int. It returns some non-zero ints for error conditions. For the normal exit, there is no return statement. The function actually returns the value 768. This gets understood by the calling function as an error, because it is apparently expecting a return of 0 for the non-error condition. This results in error messages from the demo program for the library.

This is such an obvious problem, the person who wrote and published this library could not have failed to have noticed. So I would assume my system works different to his. Maybe on his system a function returning an int returns 0 if there is no return statement. On mine it doesn't.

Next oddity:

In the h file

struct myStruct
{ float a;
int b;
};

In the cpp file:

myStruct getData()
{
myStruct s = myStruct() ;
// get some data
// put the data in s.a and s.b
return s ;
}

I am bamboozled by this . what exactly is myStruct() ?? A constructor ? This is some syntax for a struct I don't know. It is neither a function nor an object constructor. Does this allocate an object and if so, where does it get deallocated ?

Next oddity

uint8_t* myFun()
{
unit8_t buf[7] ;
// put some data in it
return buf ;
}

If buf is a local variable in myFun, does it's address have any validity after the function returns ?
Maybe this is valid but not the way I would ever do it.

One function is supposed to return an int. It returns some non-zero ints for error conditions. For the normal exit, there is no return statement. The function actually returns the value 768. This gets understood by the calling function as an error, because it is apparently expecting a return of 0 for the non-error condition. This results in error messages from the demo program for the library.

Libraries are contributed. Not all of them have been peer reviewed. Not all the suggestions made during the peer reviews are incorporated. So, libraries, like sketches, are not necessarily perfect. If you don't tell us what library you are talking about, though, we can't help.

Maybe on his system a function returning an int returns 0 if there is no return statement. On mine it doesn't.

What gets returned is garbage in either case. The garbage on the developer's system could well have been 0. On yours, obviously not.

I am bamboozled by this . what exactly is myStruct() ?? A constructor ?

A call to the constructor, yes.

This is some syntax for a struct I don't know.

The definition of the struct is perfectly normal.

It is neither a function nor an object constructor.

What is? What does "it" refer to in that sentence?

The code you referenced IS calling the constructor to create an object.

Does this allocate an object and if so, where does it get deallocated ?

Yes, it is allocating an object. It gets deallocated when the returned object goes out of scope.

does it's address have any validity after the function returns ?

No, it does not. That function is completely wrong.

Please use code tags (# button in the comment editor toolbar).

uint8_t*   myFun()
{
     unit8_t buf[7] ;
     //  put some data in it
     return buf;
}

As soon as that function returns, the stack space for buf is deallocated, and the pointer suddenly points to unallocated memory. If you read from it in the calling code, you'll read garbage. If you write to it, you'll corrupt memory and almost certainly crash the program.

Rule of thumb: never return pointers to local variables.

I have never seen a "constructor" for a struct type before. For classes and objects, not for structs. Must be some innovation that passed me by.
Even if that is a legitimate way of creating a struct, its not clear how that object ever gets legimitately deallocated.

The third example, I agree, looks wrong. When I ran the demo program for the library using that, i noticed that about every 20th call returned something odd. The rest worked. Whether this was due to the bad C or some other communication problem, hard to say. I replaced it with something else like this:

calling function:

uint8_t buf[7] ;

int res = myFun( buf ) ;

myFun( buf )
{
// put some data in buf
return 0 ;
}

And the intermittetent data errors went away. The original code must have been "lucky" to work.

michinyon:
I have never seen a "constructor" for a struct type before. For classes and objects, not for structs. Must be some innovation that passed me by.

In C++ the only difference between a class and a struct is the default access permissions. With struct it's 'public', with class it's 'private'.

You can keep a separation between the two in your head (and that's a good thing) but technically they're almost identical.

structs with constructors make sense because Plain Old Data types like ints don't initialize themselves automatically. They can have random values without a constructor.

So there is no code for this "constructor" so it must be some default thing created for it by the compiler. Does it set all the bytes of the struct to zero, or is it still undefined ?

Anyway, even if that constructor is OK, it would appear that the memory for it is not deallocated, those structs may be accumulating in huge numbers somewhere.

it would appear that the memory for it is not deallocated

You could add a constructor and a destructor to the struct, and see that the destructor IS called when the object goes out of scope.

michinyon:
Even if that is a legitimate way of creating a struct, its not clear how that object ever gets legimitately deallocated.

The struct gets created on the stack, so it is automatically deallocated when the function returns, just as if you had declared "int s;" instead.. The "return s;" statement causes the function to return a copy of the struct. The copy will be created on the calling function's stack, so likewise will be deallocated automatically when the calling function returns.

In Java you don't have the option of creating objects of non-primitive type on the stack, so I can see why you find this confusing.

If you wanted to mimic what you would have to do in Java, you would have to create the struct on the heap like this:

myStruct *getData()
{
    myStruct *s = new myStruct() ; 
    // get some data
    // put the data in s.a and s.b
    return s ;
}

The function returns a pointer to the struct (which is allocated on the heap) and the caller would be responsible for deallocating the struct. BTW it's generally bad practice to allocate anything on heap (except perhaps during the initialization phase) when writing programs for microcontrollers with limited memory.