I'm new to the use of pointers, and I'm trying to write a program to learn to use them. I have a question for you. I have a file lib.h
, inside which I define all the functions necessary into the main. Inside this file I've a simple data struct
:
struct Slave
{
char **all_samples;
int number_of_samples;
char **last_samples;
int *RSSI;
int *AGC;
int *AUTH;
};
As you can see, the members of this struct are pointers (pointers to int, pointers to pointers etc.). In the same file, I've several functions. Consider one of them, for simplicity. Inside this function, I read several lines from a file and put them into the array string all_samples
(i
is the number of lines previously correctly calculated):
struct Slave *read_slaves_file(char *file_path, char *slave)
{
...
struct Slave *slave_ptr = malloc(sizeof(struct Slave *));
slave_ptr->all_samples = malloc(i * sizeof(char *));
slave_ptr->all_samples = all_samples;
return slave_ptr;
}
I omitted the irrelevant part of code (my question is more theorical, I don't have bugs in my program). As you can see, I return a pointer to the struct, so, inside the main:
#include "lib.h"
int main(){
struct Slave *slave_1 = malloc(sizeof(struct Slave *));
slave_1 = read_slaves_file(FILE_PATH, SLAVE_1);
return 0;
}
Everything seems to work fine...but, I have a doubt. All the memory dynamically allocated inside the previous function:
struct Slave *slave_ptr = malloc(sizeof(struct Slave *));
slave_ptr->all_samples = malloc(i * sizeof(char *));
Where should be deallocated? Should it be deallocated? I suppose I can't deallocate the memory before I return the pointer. So, how to do?
CodePudding user response:
I don't have bugs in my program
You have plenty of bugs.
-
struct Slave *slave_1 = malloc(sizeof(struct Slave *)); slave_1 = read_slaves_file(FILE_PATH, SLAVE_1);
This reassigns
slave_1
creating a memory leak. It doesn't make sense to allocate memory both in the caller and inside the function. Make up your mind where you want to do the allocation. malloc(sizeof(struct Slave *))
This should bemalloc(sizeof(struct Slave))
or if you prefermalloc(sizeof(*slave_1))
. The same bug exists in multiple places.slave_ptr->all_samples = malloc(i * sizeof(char *));
slave_ptr->all_samples = all_samples;
Same bug as before. By using the assignment operator, you either copy a pointer or copy data. It can't do both things unless you change the type of the operands. At this point I'd just back off from dynamic allocation and study how pointers work, particularly what's informally called "soft copy" vs "hard copy".
Where should be deallocated?
The best option is always to have the caller do the allocation and make them provide a pointer to a buffer, for the function to fill up. This separates allocation from the algorithm. However, this might not always be an option.
Another good design is to have the code module which allocates something also take responsibility to clean up its own mess. So if your lib provides a function returning a pointer to dynamically allocated data, the same lib should also provide another function to clean up that data.
Some less well-designed functions return a pointer and expects the caller to clean it up (see for example POSIX getline
). This is questionable but you can get away with it if you properly document that the caller is responsible for cleaning up.