I am writing a program that reads a line of input, uses get_token() to store dynamically allocated copies of all of that line's tokens in an array arr of strings, then prints those tokens in order on standard output. The program should not store empty strings and the limit of arr would be 5 strings.
After running the program I get "free(): invalid pointer" and "Abort (core dumped)." I have tried everything I could think of to fix this program but I can't figure out why.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define NORMAL 0
#define NEWLINE 1
#define NULLBYTE 2
char *get_token(char **ptr, int *sts) {
*sts = 4;
char *tok = (char*) malloc(80);
while (**ptr == ' ') {
(*ptr) ;
}
if (**ptr != ' ') {
int i = 0;
while (**ptr != ' ' && **ptr != '\n' && **ptr != '\0') {
tok[1] = **ptr;
i ;
// all chars are added
(*ptr) ; // advance the pointer beyond the sequence
}
tok[i 1] = '\0';
}
if (**ptr == ' ') {
*sts = NORMAL;
} else if (**ptr == '\n') {
*sts = NEWLINE;
} else if (**ptr == '\0') {
*sts = NULLBYTE;
} else {
*sts = 4;
}
if (*sts == 4) {
return NULL;
} else {
return tok;
}
}
int main() {
char **arr = (char**) malloc(5);
char *line = (char*) malloc(80); // getline argument 1
char *line2 = line;
size_t size = 80; // getline argument 2
ssize_t ret;
printf("Enter a line of input\n");
if ((ret = getline(&line2, &size, stdin)) < 0) {
perror("getline");
return -1;
}
char *token;
int sts;
int i = 0;
while (sts == NORMAL) {
token = get_token(&line2, &sts);
if (token != NULL) {
arr[i] = token;
i ;
} else {
printf("get_token() returned NULL\n");
}
if (i > 4) {
printf("There are too many tokens\n");
break;
}
}
arr[i] = (char *) 0;
i = 0;
while (arr[i] != (char*) 0) {
printf("Token: %s\n", arr[i]);
//free(arr[i]); //avoid
i ;
}
free(line2); // problem with free(line2)
free(arr);
return 0;
}
My output is the following:
Enter a line of input
hi my name
Token:
Token:
Token:
free(): invalid pointer
Abort (core dumped)
CodePudding user response:
You must pass a pointer to the dynamically allocated memory buffer to free
. This pointer is returned by malloc
, stored in line2
and possibly modified by getline
. Up to then, everything is ok.
However, you then also modify line2
in the function get_token
. You should not do this, because you must remember the value of line2
, so you can pass it to free
at the end of the program. Therefore, you should make a copy instead, which you can then modify in the function get_token
.
CodePudding user response:
At least these problems:
Wrong allocation size. Also cast not needed.
// char **arr = (char**) malloc(5);
char **arr = malloc(sizeof *arr * 5);