I am developing a program that is supposed to take a string as a parameter and display the number of occurrences of each word in their order of appearance.
I have a problem when the string contains more than 3 different words.
The error:
double free or corruption (out)
[1] 189175 IOT instruction (core dumped) ./test "like test test love love like pop"
valgrind:
==189553== Memcheck, a memory error detector
==189553== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==189553== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==189553== Command: ./test like\ test\ test\ love\ love\ like\ pop
==189553== Parent PID: 185694
==189553==
==189553== Invalid write of size 8
==189553== at 0x10930B: handle_word (test.c:32)
==189553== by 0x1093F6: count_word_occurrences (test.c:49)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74048 is 0 bytes after a block of size 8 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x10938B: count_word_occurrences (test.c:43)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid write of size 4
==189553== at 0x109324: handle_word (test.c:33)
==189553== by 0x1093F6: count_word_occurrences (test.c:49)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74094 is 0 bytes after a block of size 4 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x109399: count_word_occurrences (test.c:44)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid read of size 8
==189553== at 0x10925B: word_exists (test.c:19)
==189553== by 0x1092BE: handle_word (test.c:27)
==189553== by 0x1093F6: count_word_occurrences (test.c:49)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74048 is 0 bytes after a block of size 8 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x10938B: count_word_occurrences (test.c:43)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid read of size 4
==189553== at 0x1092DC: handle_word (test.c:29)
==189553== by 0x1093F6: count_word_occurrences (test.c:49)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74094 is 0 bytes after a block of size 4 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x109399: count_word_occurrences (test.c:44)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid write of size 4
==189553== at 0x1092E1: handle_word (test.c:29)
==189553== by 0x1093F6: count_word_occurrences (test.c:49)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74094 is 0 bytes after a block of size 4 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x109399: count_word_occurrences (test.c:44)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid read of size 4
==189553== at 0x10943E: count_word_occurrences (test.c:58)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74094 is 0 bytes after a block of size 4 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x109399: count_word_occurrences (test.c:44)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid read of size 8
==189553== at 0x109453: count_word_occurrences (test.c:58)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74048 is 0 bytes after a block of size 8 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x10938B: count_word_occurrences (test.c:43)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553== Invalid read of size 8
==189553== at 0x109499: count_word_occurrences (test.c:61)
==189553== by 0x109523: main (test.c:75)
==189553== Address 0x4a74048 is 0 bytes after a block of size 8 alloc'd
==189553== at 0x4841888: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==189553== by 0x10938B: count_word_occurrences (test.c:43)
==189553== by 0x109523: main (test.c:75)
==189553==
==189553==
==189553== HEAP SUMMARY:
==189553== in use at exit: 0 bytes in 0 blocks
==189553== total heap usage: 10 allocs, 10 frees, 1,070 bytes allocated
==189553==
==189553== All heap blocks were freed -- no leaks are possible
==189553==
==189553== For lists of detected and suppressed errors, rerun with: -s
==189553== ERROR SUMMARY: 25 errors from 8 contexts (suppressed: 0 from 0)
Code:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool is_separator(char c)
{
return c == ' ' || c == '\0' || c == '\t';
}
char *extract_word(char *str, size_t start, size_t len)
{
char *curr_word = malloc(len 1);
strncpy(curr_word, str start, len);
curr_word[len] = '\0';
return curr_word;
}
int word_exists(char **words, size_t word_count, char *word)
{
for (size_t i = 0; i < word_count; i ) {
if (strcmp(words[i], word) == 0) {
return i;
}
}
return -1;
}
void handle_word(char **words, int *counts, size_t *word_count, char *curr_word)
{
int found_index = word_exists(words, *word_count, curr_word);
if (found_index != -1) {
counts[found_index] ;
free(curr_word);
} else {
words[*word_count] = curr_word;
counts[*word_count] = 1;
(*word_count) ;
}
}
size_t count_word_occurrences(char *str)
{
size_t len = strlen(str);
size_t curr_word_start = 0;
size_t curr_word_len = 0;
size_t word_count = 0;
char **words = malloc(sizeof(char*));
int *counts = malloc(sizeof(int));
size_t i = 0;
while (i <= len) {
if (is_separator(str[i])) {
char *curr_word = extract_word(str, curr_word_start, curr_word_len);
handle_word(words, counts, &word_count, curr_word);
curr_word_start = i 1;
curr_word_len = 0;
} else {
curr_word_len ;
}
i ;
}
for (size_t i = 0; i < word_count; i ) {
printf("%s %d\n", words[i], counts[i]);
}
for (size_t i = 0; i < word_count; i ) {
free(words[i]);
}
free(words);
free(counts);
return 0;
}
int main(int argc, char **argv)
{
if (argc != 2) {
printf("\n");
return 0;
}
char *str = argv[1];
count_word_occurrences(str);
return 0;
}
Thanks in advance.
CodePudding user response:
Thank you all,
The error came from the malloc() linked to the double dimensional array :
char **words = malloc(sizeof(char*));
So I replaced the line with :
char **words = malloc(len * sizeof(char*))
And it's ok.