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.
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.
Related
I have this function split_text that takes in a char array text and attempts to split it into sub-arrays using the token as the split value, res is an array of pointers to each of the sub-strings
int split_text(char * text, char * token, char ** res)
{
int x =0;
char * tmp = strtok(text , token);
while (tmp != NULL)
{
res[x] = malloc(1024);
strcpy(res[x], tmp);
x++;
*res = realloc(*res, sizeof(char*)*(x+1));
tmp = strtok(NULL , token);
}
return x;
}
int main()
{
char text[] = "Hello world this is elliot";
char ** ptr = (char**)malloc(sizeof(char*));
int x = split_text(text, " ", ptr);
for (int i =0; i< x; i++)
printf("%s\n", ptr[i]);
return 0;
}
when compiling this code it works fine as in it displays the sub-strings each on a new line but when ran with valgrind, I get many Invalid write of size 8 and Invalid read of size 8
Here is the full valgrind output
==74210== Memcheck, a memory error detector
==74210== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==74210== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==74210== Command: ./a.out
==74210==
==74210== Invalid write of size 8
==74210== at 0x1091D0: split_text (split.c:23)
==74210== by 0x1092B2: main (split.c:38)
==74210== Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210== at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210== by 0x109294: main (split.c:36)
==74210==
==74210== Invalid read of size 8
==74210== at 0x1091E7: split_text (split.c:24)
==74210== by 0x1092B2: main (split.c:38)
==74210== Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210== at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210== by 0x109294: main (split.c:36)
==74210==
Hello
==74210== Invalid read of size 8
==74210== at 0x1092D3: main (split.c:42)
==74210== Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210== at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210== by 0x109294: main (split.c:36)
==74210==
world
this
is
elliot
==74210==
==74210== HEAP SUMMARY:
==74210== in use at exit: 4,152 bytes in 6 blocks
==74210== total heap usage: 12 allocs, 6 frees, 6,312 bytes allocated
==74210==
==74210== LEAK SUMMARY:
==74210== definitely lost: 4,104 bytes in 5 blocks
==74210== indirectly lost: 48 bytes in 1 blocks
==74210== possibly lost: 0 bytes in 0 blocks
==74210== still reachable: 0 bytes in 0 blocks
==74210== suppressed: 0 bytes in 0 blocks
==74210== Rerun with --leak-check=full to see details of leaked memory
==74210==
==74210== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)
==74210==
==74210== 4 errors in context 1 of 3:
==74210== Invalid read of size 8
==74210== at 0x1092D3: main (split.c:42)
==74210== Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210== at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210== by 0x109294: main (split.c:36)
==74210==
==74210==
==74210== 4 errors in context 2 of 3:
==74210== Invalid read of size 8
==74210== at 0x1091E7: split_text (split.c:24)
==74210== by 0x1092B2: main (split.c:38)
==74210== Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210== at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210== by 0x109294: main (split.c:36)
==74210==
==74210==
==74210== 4 errors in context 3 of 3:
==74210== Invalid write of size 8
==74210== at 0x1091D0: split_text (split.c:23)
==74210== by 0x1092B2: main (split.c:38)
==74210== Address 0x4a3f048 is 0 bytes after a block of size 8 alloc'd
==74210== at 0x483F7B5: malloc (vg_replace_malloc.c:381)
==74210== by 0x109294: main (split.c:36)
==74210==
==74210== ERROR SUMMARY: 12 errors from 3 contexts (suppressed: 0 from 0)
I know that it is reading and writing from invalid memory places but it still outputs the split-ed text as sub-strings
Why do I get these errors and how do I fix them?
At least this statement
*res = realloc(*res, sizeof(char*)*(x+1))
that is equivalent to
res[0] = realloc(res[0], sizeof(char*)*(x+1))
does not make a sense.
It always reallocates the first element of the array of pointers pointed to by the pointer res.
As a result the array pointed to by the pointer res has only one element allocated in main.
So this call strcpy
strcpy(res[x], tmp);
invokes undefined behavior at least when x is not equal to 0.
Pay attention to that if you want to change the pointer ptr declared in main within the function split_text then you need to pass it to the function by reference. That is the third parameter of the function should be declared like
int split_text(char * text, char * token, char *** res);
As for the function definition then you need to allocate memory for a pointer for each new element and also to allocate a character array pointed to by the pointer where a substring will be copied.
I have searched high and low for an applicable answer, but I couldn't find one. I am well aware my inability to solve this issue is due to a unfamiliarity of C.
I am working on a function to concatenate one dynamically allocated string onto another, and it seems to work outside the realm of memory leaks and valgrind; however, when I run it with valgrind it is evident I have some glaring memory leaks I just cannot find. It seems to be a issue with how I am using realloc.
here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void dynamCat(char *dest, const char *src) {
size_t len = strlen(dest) + strlen(src) + 1;
printf("strLen: %ld\n", len);
char *tmp = realloc(dest, len);
if(tmp == NULL){
fprintf(stderr, "strAppend: realloc messed up\n");
free(tmp);
return;
} else {
dest = tmp;
}
strcat(dest, src);
}
int main (int argc, char *argv[]) {
char *one = malloc(4);
strcpy(one, "tee");
char *two = malloc(4);
strcpy(two, "hee");
printf("one: %s\n", one);
printf("two: %s\n", two);
dynamCat(one, two);
printf("one: %s\n", one);
printf("two: %s\n", two);
//freeee
free(one);
free(two);
return 0;
}
the output on the command line:
$ ./dynamCat
one: tee
two: hee
strLen: 7
one: teehee
two: hee
here's where the bad stuff comes.
output with valgrind on the commandline:
==28804== Memcheck, a memory error detector
==28804== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==28804== Using Valgrind-3.16.1 and LibVEX; rerun with -h for copyright info
==28804== Command: ./dynamCat
==28804==
==28804== Invalid read of size 1
==28804== at 0x4841C72: strlen (vg_replace_strmem.c:459)
==28804== by 0x48D9407: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c040 is 0 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid read of size 1
==28804== at 0x4841C84: strlen (vg_replace_strmem.c:459)
==28804== by 0x48D9407: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c041 is 1 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid read of size 1
==28804== at 0x48460D0: mempcpy (vg_replace_strmem.c:1536)
==28804== by 0x48ED211: _IO_file_xsputn##GLIBC_2.2.5 (in /usr/lib/libc-2.33.so)
==28804== by 0x48D915A: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c042 is 2 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid read of size 1
==28804== at 0x48460DE: mempcpy (vg_replace_strmem.c:1536)
==28804== by 0x48ED211: _IO_file_xsputn##GLIBC_2.2.5 (in /usr/lib/libc-2.33.so)
==28804== by 0x48D915A: __vfprintf_internal (in /usr/lib/libc-2.33.so)
==28804== by 0x48C463E: printf (in /usr/lib/libc-2.33.so)
==28804== by 0x1092EE: main (dynamCat.c:37)
==28804== Address 0x4a3c040 is 0 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804== Invalid free() / delete / delete[] / realloc()
==28804== at 0x483F9AB: free (vg_replace_malloc.c:538)
==28804== by 0x109312: main (dynamCat.c:41)
==28804== Address 0x4a3c040 is 0 bytes inside a block of size 4 free'd
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804== Block was alloc'd at
==28804== at 0x483E77F: malloc (vg_replace_malloc.c:307)
==28804== by 0x10926D: main (dynamCat.c:26)
==28804==
==28804==
==28804== HEAP SUMMARY:
==28804== in use at exit: 7 bytes in 1 blocks
==28804== total heap usage: 4 allocs, 4 frees, 4,111 bytes allocated
==28804==
==28804== 7 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28804== at 0x4840D7B: realloc (vg_replace_malloc.c:834)
==28804== by 0x1091FA: dynamCat (dynamCat.c:11)
==28804== by 0x1092D6: main (dynamCat.c:35)
==28804==
==28804== LEAK SUMMARY:
==28804== definitely lost: 7 bytes in 1 blocks
==28804== indirectly lost: 0 bytes in 0 blocks
==28804== possibly lost: 0 bytes in 0 blocks
==28804== still reachable: 0 bytes in 0 blocks
==28804== suppressed: 0 bytes in 0 blocks
==28804==
==28804== For lists of detected and suppressed errors, rerun with: -s
==28804== ERROR SUMMARY: 9 errors from 6 contexts (suppressed: 0 from 0)
thank you so much for your help. I am still very new to C and really appreciate your help.
If realloc returns a null pointer, do not free its return value; there is no point in passing a null pointer to free:
char *tmp = realloc(dest, len);
if(tmp == NULL){
fprintf(stderr, "strAppend: realloc messed up\n");
free(tmp); // This does nothing.
dest is a parameter, so assigning to it changes only the parameter. It does not change the original argument:
dest = tmp; // This changes only the dest inside dynamCat.
To give the caller a new address, you must either return it as a pointer:
char *dynamCat(char *dest, const char *src)
{
…
dest = something;
…
return dest;
}
or you must put it into a pointer passed by the caller:
void dynamCat(char **dest, const char *src)
{
…
char *tmp = realloc(*dest, len);
…
*dest = tmp;
}
strcat(*dest, src);
}
In the latter case, when calling dynamCat, you must pass it the address of a pointer:
dynamCat(&one, two);
In the former case, you must take the new pointer from the return value of dynamCat:
one = dynamCat(one, two);
The realloc function can change the address of the object. When he object is being made bigger, the need for this is obvious: there may not be space at the original location. It's potentially true when shrinking the object also.
In abstract terms, when we call realloc(x, newsize), the pointer x becomes indeterminate. We must capture the returned pointer y = realloc(x, newsize) and then use that in all places that previously referred to x.
In your program the catenating function returns void, and main keeps referring to the old string.
Your dynamCat should be like this:
/* dest is destroyed: use the return value
* in place of dest!
*/
char *dynamCat(char *dest, const char *src) {
size_t len = strlen(dest) + strlen(src) + 1;
printf("strLen: %ld\n", len);
char *tmp = realloc(dest, len);
if(tmp == NULL){
fprintf(stderr, "strAppend: realloc messed up\n");
/* better handling needed here, too */
}
strcat(tmp, src);
return tmp;
}
I should dynamically allocate an array of pointers to structure, passing from time to time parameters for a single structure.
sorry if I can not explain, here is the code
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
typedef struct _DROP_DOWN_MENU_LABELS
{
char *title;
char **items;
} MenuLabels;
MenuLabels ** ml_init(void)
{
MenuLabels **ml;
ml=(MenuLabels **)calloc(2,sizeof(MenuLabels*));
ml[1]=NULL;
return ml;
}
void addit(MenuLabels **mlabels, char *title, char *elems,...)
{
int j;
for (j=0; mlabels[j]!=NULL ; j++ );
printf("\n\nCHECK:MenuLabels has %d menu",j);
mlabels=(MenuLabels **)realloc(mlabels,(j+2)*sizeof(MenuLabels*));
mlabels[j]=(MenuLabels *)malloc(1*sizeof(MenuLabels));
mlabels[j+1]=NULL;
mlabels[j]->title=title;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int i=0;
char **mitems=NULL;
mitems=(char **)malloc(sizeof(char*));
mitems[i]=elems;
va_list argP;
va_start(argP, elems);
char *p;
for (i=1; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=p;
}
if (!p)
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=NULL;
}
va_end(argP);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
mlabels[j]->items=mitems;
}
int main()
{
MenuLabels **ml;
ml=ml_init();
addit(ml,"FILE","new","open","save","backup","print","setup","exit",NULL);
addit(ml,"AFILE","Anew","Asave","Abackup","Aexit",NULL);
addit(ml,"BFILE","Bnew","Bopen","Bsave","Bprint","Bexit",NULL);
free(ml);
fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
return 0;
}
starting the program seems to be executed without errors:
CHECK:MenuLabels has 0 menu
CHECK:MenuLabels has 1 menu
CHECK:MenuLabels has 2 menu
***END***
Process returned 0 (0x0) execution time : 0.001 s
Press ENTER to continue.
but checking with valgrind:
==5572== Memcheck, a memory error detector
==5572== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5572== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5572== Command: ./prove
==5572==
==5572== Invalid read of size 8
==5572== at 0x400812: addit (main.c:26)
==5572== by 0x400B27: main (main.c:75)
==5572== Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400AF1: main (main.c:74)
==5572== Block was alloc'd at
==5572== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x40075C: ml_init (main.c:15)
==5572== by 0x400AB0: main (main.c:73)
==5572==
CHECK:MenuLabels has 0 menu
==5572== Invalid free() / delete / delete[] / realloc()
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400B27: main (main.c:75)
==5572== Address 0x5204040 is 0 bytes inside a block of size 16 free'd
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400AF1: main (main.c:74)
==5572== Block was alloc'd at
==5572== at 0x4C2FB55: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x40075C: ml_init (main.c:15)
==5572== by 0x400AB0: main (main.c:73)
==5572==
==5572== Invalid write of size 8
==5572== at 0x400882: addit (main.c:31)
==5572== by 0x400B27: main (main.c:75)
==5572== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==5572==
==5572==
==5572== Process terminating with default action of signal 11 (SIGSEGV)
==5572== Access not within mapped region at address 0x0
==5572== at 0x400882: addit (main.c:31)
==5572== by 0x400B27: main (main.c:75)
==5572== If you believe this happened as a result of a stack
==5572== overflow in your program's main thread (unlikely but
==5572== possible), you can try to increase the size of the
==5572== main thread stack using the --main-stacksize= flag.
==5572== The main thread stack size used in this run was 8388608.
CHECK:MenuLabels has 0 menu==5572==
==5572== HEAP SUMMARY:
==5572== in use at exit: 112 bytes in 4 blocks
==5572== total heap usage: 14 allocs, 10 frees, 1,392 bytes allocated
==5572==
==5572== 16 bytes in 1 blocks are definitely lost in loss record 2 of 4
==5572== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400881: addit (main.c:31)
==5572== by 0x400B27: main (main.c:75)
==5572==
==5572== 96 (16 direct, 80 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==5572== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5572== by 0x400855: addit (main.c:29)
==5572== by 0x400AF1: main (main.c:74)
==5572==
==5572== LEAK SUMMARY:
==5572== definitely lost: 32 bytes in 2 blocks
==5572== indirectly lost: 80 bytes in 2 blocks
==5572== possibly lost: 0 bytes in 0 blocks
==5572== still reachable: 0 bytes in 0 blocks
==5572== suppressed: 0 bytes in 0 blocks
==5572==
==5572== For counts of detected and suppressed errors, rerun with: -v
==5572== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 0 from 0)
./run_valgrind: riga 4: 5572 Errore di segmentazione (core dump creato) valgrind --leak-check=full --track-origins=yes --tool=memcheck ./prove
and in fact if I try to extract any value from ml at the end (eg ml[n]-> title) it goes into segmentation fault
what am I doing wrong? thank you all in advance
Here's one problem:
char **mitems;
// ... assuming there's a mitems = malloc(...) or similar here...
mlabels[j]->items=mitems;
free(mitems);
Here you have a a pointer, you make it point to some memory you allocate, you copy the pointer (so you have two pointers pointing to the same memory) and then you free the memory that both pointers are pointing to.
The free call makes not only mitems invalid, but also mlabels[j]->items.
I solved ... here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
typedef struct s_drop_down_menu_labels
{
char *title;
char **items;
} MenuLabels;
MenuLabels ** ml_init(void)
{
MenuLabels **ml;
ml=(MenuLabels **)calloc(2,sizeof(MenuLabels*));
ml[1]=NULL;
return ml;
}
void addit(MenuLabels ***mlabels, char *title, char *elems,...)
{
int j;
for (j=0; (*mlabels)[j]!=NULL ; j++ );
printf("\n\nCHECK:MenuLabels has %d menu",j);
*mlabels=(MenuLabels **)realloc(*mlabels,(j+2)*sizeof(MenuLabels*));
(*mlabels)[j]=(MenuLabels *)malloc(1*sizeof(MenuLabels));
(*mlabels)[j+1]=NULL;
(*mlabels)[j]->title=title;
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
int i=0;
char **mitems=NULL;
mitems=(char **)malloc(sizeof(char*));
mitems[i]=elems;
va_list argP;
va_start(argP, elems);
char *p;
for (i=1; ((p=va_arg(argP,char*)) !=NULL) ; i++ )
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=p;
}
if (!p)
{
mitems=(char **)realloc(mitems,(i+1)*sizeof(char*));
mitems[i]=NULL;
}
va_end(argP);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
(*mlabels)[j]->items=mitems;
free(mitems);
}
int main()
{
MenuLabels **ml;
ml=ml_init();
addit(&ml,"FILE","new","open","save","backup","print","setup","exit",NULL);
addit(&ml,"AFILE","Anew","Asave","Abackup","Aexit",NULL);
addit(&ml,"BFILE","Bnew","Bopen","Bsave","Bprint","Bexit",NULL);
addit(&ml,"CFILE","Cnew","Copen","Csave","Cbackup","Cprint","Csetup","Cexit",NULL);
addit(&ml,"DFILE","Dnew","Dsave","Dbackup","Dexit",NULL);
addit(&ml,"EFILE","Enew","Eopen","Esave","Eprint","Eexit",NULL);
printf("\n**********CHECK: %s",ml[3]->title);
for (int i=0;ml[i]!=NULL ;i++ )
free(ml[i]);
fprintf(stdout,"\n\033[1;91m***END***\033[0m\n");
return 0;
}
#Some_programmer_dude, if not free mitems then there will be no more accessible memory allocated ...thank you all
I want to read in from the arguments a file with a name of format filename.in and output a file with the exact same filename but with .out extension instead of .in (filename.out). The key is that filename can be anything.
This code compiles correctly and does the job I want, but when I run it with valgrind I get a bunch of errors. Can anyone tell me what's causing the errors?
int main(int argc, char * argv[])
{
int i, dotIndex;
char extOut[] = ".out";
char *filenameIn, *filenameOut, *aux;
FILE *fpIn, *fpOut;
filenameIn = argv[1];
aux = strchr(filenameIn, '.');
dotIndex = aux - filenameIn;
aux = (char *)malloc((strlen(filenameIn) - 1)*sizeof(char));
for(i = 0; i < dotIndex; i++)
aux[i] = filenameIn[i];
filenameOut = (char *)malloc((strlen(aux) + 5)*sizeof(char));
strcat(aux, extOut);
strcpy(filenameOut, aux);
/* open input file */
fpIn = fopen(filenameIn,"r");
if(fpIn == NULL) {
printf("Open error of input file\n");
exit(2);
}
/* open output file */
fpOut = fopen(filenameOut,"w");
if(fpOut == NULL) {
printf("Open error of output file\n");
exit(3);
}
fclose(fpOut);
fclose(fpIn);
free(aux);
free(filenameOut);
exit(0);
}
The valgrind report:
Command: ./doorsmaze text.in
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C36B: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C390: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef030 is 2 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid read of size 1
==3493== at 0x402C6C5: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487BF: main (main.c:65)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493==
==3493== HEAP SUMMARY:
==3493== in use at exit: 0 bytes in 0 blocks
==3493== total heap usage: 4 allocs, 4 frees, 719 bytes allocated
==3493==
==3493== All heap blocks were freed -- no leaks are possible
==3493== Command: ./doorsmaze text.in
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C36B: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid write of size 1
==3493== at 0x402C390: strcat (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487AB: main (main.c:64)
==3493== Address 0x41ef030 is 2 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493== Invalid read of size 1
==3493== at 0x402C6C5: strcpy (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x80487BF: main (main.c:65)
==3493== Address 0x41ef02e is 0 bytes after a block of size 6 alloc'd
==3493== at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==3493== by 0x8048716: main (main.c:55)
==3493==
==3493==
==3493== HEAP SUMMARY:
==3493== in use at exit: 0 bytes in 0 blocks
==3493== total heap usage: 4 allocs, 4 frees, 719 bytes allocated
==3493==
==3493== All heap blocks were freed -- no leaks are possible
==3493==
==3493== For counts of detected and suppressed errors, rerun with: -v
==3493== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
==3493== For counts of detected and suppressed errors, rerun with: -v
==3493== ERROR SUMMARY: 6 errors from 3 contexts (suppressed: 0 from 0)
You have some issues in your code
You might not get the last . in the filename
aux = strchr(filenameIn, '.');
better use strrchr. You should also check for NULL, just in case the filename doesn't include an extension.
You allocate memory large enough to hold filename.in (excluding the nul byte)
aux = (char *)malloc((strlen(filenameIn) - 1)*sizeof(char));
You do your own version of strncpy(aux, filenameIn, dotIndex)
for(i = 0; i < dotIndex; i++)
aux[i] = filenameIn[i];`
You write beyond the allocated buffer, because you miss the space for the last character plus the nul byte
strcat(aux, extOut);
To fix this, you must allocate enough memory, which is the length of filename.in plus 1 char ("out" is one longer than "in") plus nul byte
aux = (char *)malloc((strlen(filenameIn) + 2)*sizeof(char));
I'm implementing a hash table. The following is my function for initializing it.
Im getting some errors which I cant understand why. I have also quoted what valgrind says.
typedef struct HashTable
{
int size ;
struct List *head;
struct List *tail;
}HashTable;
typedef struct List
{
char *number;
char *name;
int time;
struct List *next;
}List;
#define size_of_table 211
HashTable *createHashTable(void)
{
HashTable *new_table = malloc(sizeof(*new_table)*size_of_table); //line 606
if (new_table == NULL)
{ return NULL;
}
int i=0;
for(i; i<size_of_table; i++)
{
new_table[i].size=0;
new_table[i].head=NULL;
new_table[i].tail=NULL;
}
return NULL;
}
Invalid write of size 8
==7738== at 0x401707: createHashTable (project2.c:617)
==7738== by 0x401AF6: main (project.c:739)
==7738== Address 0x51996e0 is 8 bytes after a block of size 1,688 alloc'd
==7738== at 0x4C25153: malloc (vg_replace_malloc.c:195)
==7738== by 0x401698: createHashTable (project2.c:606)
==7738== by 0x401AF6: main (project.c:739)
==7738==
==7738==
==7738== 141 errors in context 3 of 4:
==7738== Invalid write of size 8
==7738== at 0x4016E8: createHashTable (project2.c:616)
==7738== by 0x401AF6: main (project.c:739)
==7738== Address 0x51996d8 is 0 bytes after a block of size 1,688 alloc'd
==7738== at 0x4C25153: malloc (vg_replace_malloc.c:195)
==7738== by 0x401698: createHashTable (project2.c:606)
==7738== by 0x401AF6: main (project.c:739)
Works fine for me. I added const int size_of_table = 12 and invoked createHashTable() from main.
$ valgrind ./a.out
==30237== Memcheck, a memory error detector
==30237== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==30237== Using Valgrind-3.6.0.SVN and LibVEX; rerun with -h for copyright info
==30237== Command: ./a.out
==30237==
--30237-- ./a.out:
--30237-- dSYM directory is missing; consider using --dsymutil=yes
==30237==
==30237== HEAP SUMMARY:
==30237== in use at exit: 376 bytes in 2 blocks
==30237== total heap usage: 2 allocs, 0 frees, 376 bytes allocated
==30237==
==30237== LEAK SUMMARY:
==30237== definitely lost: 288 bytes in 1 blocks
==30237== indirectly lost: 0 bytes in 0 blocks
==30237== possibly lost: 0 bytes in 0 blocks
==30237== still reachable: 88 bytes in 1 blocks
==30237== suppressed: 0 bytes in 0 blocks
==30237== Rerun with --leak-check=full to see details of leaked memory
==30237==
==30237== For counts of detected and suppressed errors, rerun with: -v
==30237== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
Are you sure that's the code you're testing? 1688 bytes divided into 211 array elements gives 8 bytes each.
It's rather unlikely that a modern environment would only give you 8 bytes for a structure holding an int and two pointers.
By way of testing, the following code:
#include <stdio.h>
#include <stdlib.h>
typedef struct HashTable {
int size ;
struct List *head;
struct List *tail;
} HashTable;
typedef struct List {
char *number;
char *name;
int time;
struct List *next;
} List;
#define size_of_table 211
HashTable *createHashTable(void) {
HashTable *new_table = malloc(sizeof(*new_table)*size_of_table); //line 606
printf ("%d\n", sizeof(*new_table));
printf ("%d\n", sizeof(new_table));
if (new_table == NULL) {
return NULL;
}
int i=0;
for(i; i<size_of_table; i++) {
new_table[i].size=0;
new_table[i].head=NULL;
new_table[i].tail=NULL;
}
return new_table;
}
int main(void) {
HashTable *x = createHashTable();
free (x);
return 0;
}
outputs:
==3569== Memcheck, a memory error detector
==3569== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3569== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3569== Command: ./qq
==3569==
12
4
==3569==
==3569== HEAP SUMMARY:
==3569== in use at exit: 0 bytes in 0 blocks
==3569== total heap usage: 1 allocs, 1 frees, 2,532 bytes allocated
==3569==
==3569== All heap blocks were freed -- no leaks are possible
==3569==
==3569== For counts of detected and suppressed errors, rerun with: -v
==3569== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 13 from 8)
What does that program give you when you run it through valgrind on your system?
That code I supply above also fixes your problem with returning NULL on success by the way (a definite memory leak). Your final return in the function should not be returning NULL, it should be:
return new_table;
Based on your 24,8 output from the sample code I provided, make sure you're really using:
HashTable *new_table = malloc(sizeof(*new_table)*size_of_table); //line 606
rather than:
HashTable *new_table = malloc(sizeof(new_table)*size_of_table); //line 606
The latter will use the pointer size of 8 rather than the structure size of 24 and, when I do it that way, I get:
==3637== Memcheck, a memory error detector
==3637== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==3637== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==3637== Command: ./qq
==3637==
12
4
==3637== Invalid write of size 4
==3637== at 0x80484CD: createHashTable (in /home/allan/qq)
==3637== by 0x8048509: main (in /home/allan/qq)
==3637== Address 0x419a374 is 0 bytes after a block of size 844 alloc'd
==3637== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==3637== by 0x8048465: createHashTable (in /home/allan/qq)
==3637== by 0x8048509: main (in /home/allan/qq)
==3637==
==3637== Invalid write of size 4
==3637== at 0x80484E3: createHashTable (in /home/allan/qq)
==3637== by 0x8048509: main (in /home/allan/qq)
==3637== Address 0x419a378 is 4 bytes after a block of size 844 alloc'd
==3637== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==3637== by 0x8048465: createHashTable (in /home/allan/qq)
==3637== by 0x8048509: main (in /home/allan/qq)
==3637==
==3637== Invalid write of size 4
==3637== at 0x80484B8: createHashTable (in /home/allan/qq)
==3637== by 0x8048509: main (in /home/allan/qq)
==3637== Address 0x419a37c is 8 bytes after a block of size 844 alloc'd
==3637== at 0x4024F20: malloc (vg_replace_malloc.c:236)
==3637== by 0x8048465: createHashTable (in /home/allan/qq)
==3637== by 0x8048509: main (in /home/allan/qq)
==3637==
==3637==
==3637== HEAP SUMMARY:
==3637== in use at exit: 0 bytes in 0 blocks
==3637== total heap usage: 1 allocs, 1 frees, 844 bytes allocated
==3637==
==3637== All heap blocks were freed -- no leaks are possible
==3637==
==3637== For counts of detected and suppressed errors, rerun with: -v
==3637== ERROR SUMMARY: 422 errors from 3 contexts (suppressed: 13 from 8)
If you are sure you're using the 24 value, place the line:
printf ("%d\n", sizeof(*new_table)*size_of_table);
after the malloc line and see what it outputs.