patterncMinor
Command manipulation functions for a toy shell program
Viewed 0 times
toyfunctionsprogramshellmanipulationforcommand
Problem
I am writing a small program that is supposed to act as a shell of some sorts. It operates off of a few basic structures, one of them being a
I have written functions to add new commands, add new history, find aliases in a list and return its index, among other things, but I have a feeling that the command for adding commands,
Command manipulation functions:
```
void addcommand(char str, void fun, command_list* srclist)
{
printdebug("Adding command \"%s\" pointing to function at %p in command list located at %p... ", str, fun, srclist);
srclist -> list = realloc(srclist -> list, sizeof(command) (srclist -> len + 1));
srclist -> list[srclist -> len] = malloc(sizeof(command));
srclist -> list[srclist -> len] -> alias = malloc(sizeof(char) * (strlen(str) + 1));
srclist -> list[srclist -> len] -> function = malloc(sizeof(void*)); // problems here and |
memcpy(srclist -> list[srclist -> len] -> alias, str, sizeof(char) * (strlen(str) + 1)); // |
srclist -> list[srclist -> len] -> function = fun; // len++;
printdebug("Command added.\n");
}
void addhistory(char str, command_list srclist)
{
printdebug("Adding \"%s\" to history list located at %p...", str, srclist -> history);
srclist -> history -> list = realloc(srclist -> history -> list, sizeof(char) (srclist -> history -> len + 1));
srclist -> history -> list[srclist ->
command, a command_list, and a command_history.typedef struct command command;
typedef struct
{
char** list;
int len;
} command_history;
typedef struct
{
command** list;
int len;
command_history* history;
} command_list;
typedef struct command
{
char* alias;
void (*function)(command_list*);
} command;I have written functions to add new commands, add new history, find aliases in a list and return its index, among other things, but I have a feeling that the command for adding commands,
addcommand is leaking memory. I am not very experienced with C and this is just an experiment to acquaint me with pointers. I would appreciate some feedback on the code I have written and how I can improve it. Command manipulation functions:
```
void addcommand(char str, void fun, command_list* srclist)
{
printdebug("Adding command \"%s\" pointing to function at %p in command list located at %p... ", str, fun, srclist);
srclist -> list = realloc(srclist -> list, sizeof(command) (srclist -> len + 1));
srclist -> list[srclist -> len] = malloc(sizeof(command));
srclist -> list[srclist -> len] -> alias = malloc(sizeof(char) * (strlen(str) + 1));
srclist -> list[srclist -> len] -> function = malloc(sizeof(void*)); // problems here and |
memcpy(srclist -> list[srclist -> len] -> alias, str, sizeof(char) * (strlen(str) + 1)); // |
srclist -> list[srclist -> len] -> function = fun; // len++;
printdebug("Command added.\n");
}
void addhistory(char str, command_list srclist)
{
printdebug("Adding \"%s\" to history list located at %p...", str, srclist -> history);
srclist -> history -> list = realloc(srclist -> history -> list, sizeof(char) (srclist -> history -> len + 1));
srclist -> history -> list[srclist ->
Solution
You indeed have a memory leak in your addcommand function, at this line:
The reason is that the pointer that you obtained from malloc stored into
After this point, the pointer to the memory returned by malloc is lost and you cannot free it, hence the memory leak.
In fact, you don't need to malloc anything for that function, since the memory for the function pointer was already allocated by this line:
The command struct already contains the memory for the field function. So you can just set function to the
Note also that the
Another comment: why do you keep a
and adding a new command in the list would look like:
Additionally, you should check the return value for malloc and realloc. They may return a NULL pointer if there is insufficient memory, and the code that dereferences these pointers will cause a segmentation fault and crash the program.
srclist -> list[srclist -> len] -> function = malloc(sizeof(void*));The reason is that the pointer that you obtained from malloc stored into
function gets overwritten later by the following line:srclist -> list[srclist -> len] -> function = fun;After this point, the pointer to the memory returned by malloc is lost and you cannot free it, hence the memory leak.
In fact, you don't need to malloc anything for that function, since the memory for the function pointer was already allocated by this line:
srclist -> list[srclist -> len] = malloc(sizeof(command));The command struct already contains the memory for the field function. So you can just set function to the
fun pointer.Note also that the
fun is not a void pointer, but rather a function pointer, so you should declare it as void (fun)(command_list ) instead of void *fun.Another comment: why do you keep a
command** list instead of command list? You are currently allocating memory twice, once for the command pointer, and then for the actual command struct. A simpler (and less memory-hungry) solution would be to have:typedef struct
{
command* list; // changed command **list to command *list
int len;
command_history* history;
} command_list;and adding a new command in the list would look like:
void addcommand(char* str, void (*fun)(command_list*), command_list* srclist)
{
printdebug("Adding command \"%s\" pointing to function at %p in command list located at %p... ", str, fun, srclist);
srclist -> list = realloc(srclist -> list, sizeof(command) * (srclist -> len + 1));
srclist -> list[srclist -> len] -> alias = malloc(sizeof(char) * (strlen(str) + 1));
memcpy(srclist -> list[srclist -> len] -> alias, str, sizeof(char) * (strlen(str) + 1)); // |
srclist -> list[srclist -> len] -> function = fun; // len++;
printdebug("Command added.\n");
}Additionally, you should check the return value for malloc and realloc. They may return a NULL pointer if there is insufficient memory, and the code that dereferences these pointers will cause a segmentation fault and crash the program.
Code Snippets
srclist -> list[srclist -> len] -> function = malloc(sizeof(void*));srclist -> list[srclist -> len] -> function = fun;srclist -> list[srclist -> len] = malloc(sizeof(command));typedef struct
{
command* list; // changed command **list to command *list
int len;
command_history* history;
} command_list;void addcommand(char* str, void (*fun)(command_list*), command_list* srclist)
{
printdebug("Adding command \"%s\" pointing to function at %p in command list located at %p... ", str, fun, srclist);
srclist -> list = realloc(srclist -> list, sizeof(command) * (srclist -> len + 1));
srclist -> list[srclist -> len] -> alias = malloc(sizeof(char) * (strlen(str) + 1));
memcpy(srclist -> list[srclist -> len] -> alias, str, sizeof(char) * (strlen(str) + 1)); // |
srclist -> list[srclist -> len] -> function = fun; // <|
srclist -> len++;
printdebug("Command added.\n");
}Context
StackExchange Code Review Q#156768, answer score: 2
Revisions (0)
No revisions yet.