Homebrew Quick question about C memory management

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
39
Location
Kongo Jungle
XP
5,054
Country
Hey guys,

Objective C has spoiled me, especially with ARC, so I need to double check something on C memory management. Take the following example:

Code:
typedef struct myStruct {
    u8 * spriteData;
} myStruct;

myStruct myStructArray[16];

void doStuffWithStruct(int i) {
    myStruct aStruct = myStructArray[i];
    u8 * data = malloc(1024);
    doStuffWithData(data);
    aStruct.spriteData = data;
}

int main() {
    doStuffWithStruct(0);
    doStuffWithStruct(0);
}

I'm assuming that the second call to doStuffWithStruct(0) will cause aStruct.spriteData to leak. I'm wondering about two possible solutions.

Solution 1
Code:
typedef struct myStruct {
    u8 * spriteData;
} myStruct;

myStruct myStructArray[16];

void doStuffWithStruct(int i) {
    myStruct aStruct = myStructArray[i];
    u8 * data = malloc(1024);
    doStuffWithData(data);
    aStruct.spriteData = data;

/*
Free data here. This is like retaining properties in Obj-C, 
but I'm concerned aStruct.spriteData will then point to 
NULL or garbage in this instance
*/

    free(data);
}

int main() {
    doStuffWithStruct(0);
    doStuffWithStruct(0);
}

Solution 2
Code:
typedef struct myStruct {
    u8 * spriteData;
} myStruct;

myStruct myStructArray[16];

void doStuffWithStruct(int i) {
    myStruct aStruct = myStructArray[i];

/*
Free data here if it already exists. Is the if statement needed 
to prevent attempting to free NULL if aStruct.spriteData has 
not yet been allocated, or is freeing a NULL pointer ok?
*/
    if (aStruct.spriteData) {
        free(aStruct.spriteData);
    }

    u8 * data = malloc(1024);
    doStuffWithData(data);
    aStruct.spriteData = data;
}

int main() {
    doStuffWithStruct(0);
    doStuffWithStruct(0);
}


So, which, if either, of these will prevent a memory leak? Also, do I need to go through and free the memory for all of the myStruct objects in myStructArray before terminating the application, or will that be taken care of for me when the array itself is freed?
 
Last edited by mashers,

TheCruel

Developer
Banned
Joined
Dec 6, 2013
Messages
1,350
Trophies
1
XP
3,117
Country
United States
You should be able to free a null pointer:

The free() function deallocates the memory allocation pointed to by ptr. If ptr is a NULL pointer, no operation is performed.

But never free the pointer if you plan on using the data sometime later.
 

Gocario

GBAFail'd
Member
Joined
Sep 5, 2015
Messages
640
Trophies
0
Location
Bourg Palette
XP
794
Country
France
The first solution will always free the memory within the function (= no leak IF the pointer data wasn't malloced BEFORE).
The second will need a free function further.


Code:
// If ptr is a null pointer, no action occurs.
void free(void*ptr);

Care:
  • Once freed, spriteData will still be pointing to the address returned by the previous malloc. You should set it manually to NULL after the free.
  • If spriteData isn't initialized to NULL, problems might appear within `if (.spriteData)`.
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
39
Location
Kongo Jungle
XP
5,054
Country
The first solution will always free the memory within the function (= no leak IF the pointer data wasn't malloced BEFORE).
The second will need a free function further.


Code:
// If ptr is a null pointer, no action occurs.
void free(void*ptr);

Care:
  • Once freed, spriteData will still be pointing to the address returned by the previous malloc. You should set it manually to NULL after the free.
  • If spriteData isn't initialized to NULL, problems might appear within `if (.spriteData)`.
Oh right. So I should do

free(aStruct.spriteData);
aStruct.spriteData = NULL;
 

Gocario

GBAFail'd
Member
Joined
Sep 5, 2015
Messages
640
Trophies
0
Location
Bourg Palette
XP
794
Country
France

sarkwalvein

There's hope for a Xenosaga port.
Member
Joined
Jun 29, 2007
Messages
8,400
Trophies
2
Age
40
Location
Niedersachsen
XP
10,704
Country
Germany
I found that I got lock ups when freeing the pointer if I didn't check it was NULL first. Perhaps free() works differently in ctrulib.
Does your example work?
There are many privilege.
First when you write:
"myStruct aStruct = myStructArray;"
You are creating a copy, not a reference.
That copy and all modifications to it will die within the function.

Oh... I will look for a computer to finish this reply, the phone sucks.
 

Gocario

GBAFail'd
Member
Joined
Sep 5, 2015
Messages
640
Trophies
0
Location
Bourg Palette
XP
794
Country
France

sarkwalvein

There's hope for a Xenosaga port.
Member
Joined
Jun 29, 2007
Messages
8,400
Trophies
2
Age
40
Location
Niedersachsen
XP
10,704
Country
Germany
Oh, okay. I was replying based only in the posted example.
Another thing to mention is that free doesn't make the pointer NULL.
So if somebody wants to "check for NULL" in order to assign memory, it is compulsory to set the pointer to null after free manually:
free(pointer);
pointer=NULL;

So:
if(aStruct->spriteData){
free(aStruct->spriteData);
aStruct->spriteData = 0;
}

** But I see this is already being done in the github also.
 
Last edited by sarkwalvein,

Gocario

GBAFail'd
Member
Joined
Sep 5, 2015
Messages
640
Trophies
0
Location
Bourg Palette
XP
794
Country
France
Oh, okay. I was replying based only in the posted example.
Another thing to mention is that free doesn't make the pointer NULL.
So if somebody wants to "check for NULL" in order to assign memory, it is compulsory to set the pointer to null after free manually:
free(pointer);
pointer=NULL;

So:
if(aStruct->spriteData){
free(aStruct->spriteData);
aStruct->spriteData = 0;
}
As he said:
Oh right. So I should do

free(aStruct.spriteData);
aStruct.spriteData = NULL;
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
39
Location
Kongo Jungle
XP
5,054
Country
Heh, you realised which function I was talking about ;) I thought the real function was too complex for this questions so I simplified with an example, but got the referencing wrong in the example!

And yes, I'm setting it to NULL manually now. The gridlauncher is probably so littered with uninitialised variables that it's a miracle it works at all. I've got so used to not having to do this in Obj-C, since everything is initialised to nil, 0 or false automatically when the variable is created.

Is there a static analyser which works with ctrulib? It would be good to run the code through something like clang to check for problems like this.

--------------------- MERGED ---------------------------

Oh and one other question, do I need to go through the array and release any existing objects or will that be taken care of for me?
 

Gocario

GBAFail'd
Member
Joined
Sep 5, 2015
Messages
640
Trophies
0
Location
Bourg Palette
XP
794
Country
France
Is there a static analyser which works with ctrulib? It would be good to run the code through something like clang to check for problems like this.
--------------------- MERGED ---------------------------
Oh and one other question, do I need to go through the array and release any existing objects or will that be taken care of for me?

Analysers? What are they? B-)
> Everytime you use a malloc, a free shall be used.
 

sarkwalvein

There's hope for a Xenosaga port.
Member
Joined
Jun 29, 2007
Messages
8,400
Trophies
2
Age
40
Location
Niedersachsen
XP
10,704
Country
Germany
Oh and one other question, do I need to go through the array and release any existing objects or will that be taken care of for me?
You take care of everything memory related.
If you created an array that contains pointers, and then assigned memory to those pointers, you have to use free for each one of those pointers later on.
 

mashers

Stubborn ape
OP
Member
Joined
Jun 10, 2015
Messages
3,837
Trophies
0
Age
39
Location
Kongo Jungle
XP
5,054
Country
You take care of everything memory related.
If you created an array that contains pointers, and then assigned memory to those pointers, you have to use free for each one of those pointers later on.
Thank you for clarifying. This is different to what I'm used to in Obj-C, even using manual reference counting. Take for example:

Code:
NSString *s1 = [[NSString alloc] initWithString:@"Hello];
NSString *s2 = [[NSString alloc] initWithString:@"World];
NSArray *a = [[NSArray alloc] initWithObjects:s1, s2, nil];

To release everything, all I have to do is call [a release]. This will decrement the retain count of a to 0 causing its dealloc function to be called. [NSArray dealloc] overloads [NSObject dealloc] to iterate through its contents and call release on each object. This causes dealloc to be called on each item within the array, and everything gets deallocated. Of course with ARC you don't have to do anything - just alloc and let the runtime deal with when things get deallocated.

So yeah, long story short, having to loop through an array and manually free anything which might have been allocated feels weird to me (but does make sense).
 

filfat

Musician, Developer & Entrepreneur
Member
Joined
Nov 24, 2012
Messages
1,259
Trophies
0
Location
Göteborg
Website
spsgroup.se
XP
1,718
Country
Sweden
Thank you for clarifying. This is different to what I'm used to in Obj-C, even using manual reference counting. Take for example:

Code:
NSString *s1 = [[NSString alloc] initWithString:@"Hello];
NSString *s2 = [[NSString alloc] initWithString:@"World];
NSArray *a = [[NSArray alloc] initWithObjects:s1, s2, nil];

To release everything, all I have to do is call [a release]. This will decrement the retain count of a to 0 causing its dealloc function to be called. [NSArray dealloc] overloads [NSObject dealloc] to iterate through its contents and call release on each object. This causes dealloc to be called on each item within the array, and everything gets deallocated. Of course with ARC you don't have to do anything - just alloc and let the runtime deal with when things get deallocated.

So yeah, long story short, having to loop through an array and manually free anything which might have been allocated feels weird to me (but does make sense).

Super OT,
but Objective C looks like someone combined C# with a ini config file :P
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • JuanMena @ JuanMena:
    Will you give me mouth to mouth oxygen if my throat closes?
  • K3N1 @ K3N1:
    Nah the air can do that
  • K3N1 @ K3N1:
    Ask @x65943 he's trained for that stuff
  • JuanMena @ JuanMena:
    Kissing random dudes choking in celery? Really? Need to study for that?
  • K3N1 @ K3N1:
    Yes it requires a degree
  • K3N1 @ K3N1:
    I could also yank out the rest of my teeth but theirs professionals for that
  • x65943 @ x65943:
    If your throat closes, putting oxygen in your mouth will not solve anything - as you will be introducing oxygen prior to the area of obstruction
  • JuanMena @ JuanMena:
    Just kiss me Kyle.
  • x65943 @ x65943:
    You either need to be intubated to bypass obstruction or create a stoma inferior to the the area of obstruction to survive
  • x65943 @ x65943:
    "Just kiss me Kyle." And I thought all the godreborn gay stuff was a smear campaign
  • JuanMena @ JuanMena:
    If I die, tell my momma I won't be carrying Baby Jesus this christmas :sad::cry:
  • K3N1 @ K3N1:
    Smear campaigns are in The political section now?
  • JuanMena @ JuanMena:
    Chary! Chary! Chary, Chary, Chary!
  • Sonic Angel Knight @ Sonic Angel Knight:
    Pork Provolone :P
  • Psionic Roshambo @ Psionic Roshambo:
    Sounds yummy
  • K3N1 @ K3N1:
    Sweet found my Wii u PSU right after I ordered a new one :tpi:
  • JuanMena @ JuanMena:
    It was waiting for you to order another one.
    Seems like, your PSU was waiting for a partner.
  • JuanMena @ JuanMena:
    Keep them both
    separated or you'll have more PSUs each year.
  • K3N1 @ K3N1:
    Well one you insert one PSU into the other one you get power
  • JuanMena @ JuanMena:
    It literally turns it on.
  • K3N1 @ K3N1:
    Yeah power supplies are filthy perverts
  • K3N1 @ K3N1:
    @Psionic Roshambo has a new friend
    +1
  • JuanMena @ JuanMena:
    It's Kyle, the guy that went to school to be a Certified man Kisser.
  • Psionic Roshambo @ Psionic Roshambo:
    Cartmans hand has taco flavored kisses
  • A @ abraarukuk:
    hi guys
    A @ abraarukuk: hi guys