In the function below I must return a list of all duplicate strings in an hash table, ignoring cases if the parameter's value is equal to 1.
upo_strings_list_t upo_find_idup(const char **strs, size_t n, int ignore_case)
{
upo_strings_list_t list = NULL;
if(ignore_case) //Must lowercase each string of strs
{
size_t i;
size_t j;
size_t size = sizeof(char);
size_t len = 0;
char *aux = malloc(sizeof(char*)); //For each string of strs to lowercase
char **aux_strs = malloc(n * sizeof(char*)); //For store lowercase strings
assert( aux != NULL );
assert( aux_strs != NULL );
for(i = 0; i < n; ++i)
{
len = strlen(strs[i]) + 1;
aux_strs[i] = malloc(len * size);
strcpy(aux, strs[i]);
for(j = 0; aux[j] != '\0'; ++j)
{
aux[j] = tolower(aux[j]);
}
strcpy(aux_strs[i], aux);
}
list = upo_find_dup((const char**)aux_strs, n);
}
else
{
list = upo_find_dup(strs, n);
}
return list;
}
So, ignore case means that each string of strs must become lowercase. I tried to do that by a dynamic array of strings. When all strings are lowercase, the function calls another function (upo_find_dup) that returns a list of duplicate strings (for don't rewrite the same code).
upo_strings_list_t upo_find_dup(const char **strs, size_t n)
{
size_t i;
int val = 1;
upo_strings_list_t list = NULL;
upo_ht_linprob_t ht = upo_ht_linprob_create(UPO_HT_LINPROB_DEFAULT_CAPACITY,
upo_ht_hash_str_kr2e, upo_str_cmp);
assert( ht != NULL );
for(i = 0; i < n; ++i)
{
if(upo_ht_linprob_contains(ht, &strs[i]))
{
upo_strings_list_node_t *ln = malloc(sizeof(upo_strings_list_node_t));
if(ln == NULL)
{
perror("Unable to allocate memory for a new node");
abort();
}
ln->str = (char*)strs[i];
ln->next = list;
list = ln;
}
else
{
upo_ht_linprob_put(ht, &strs[i], &val);
}
}
return list;
}
And it seems work, because if I print every string saved in the list, they are exactly what they must be:
void test_find_idup()
{
const char *ary[] = {"One", "two", "four", "two", "one"};
size_t n = sizeof(ary) / sizeof(ary[0]);
//const char *res[] = {"one","two"};
upo_strings_list_t list;
list = upo_find_idup(ary, n, 1);
assert( list != NULL );
//size_t i = 0;
while(list != NULL)
{
printf("%s\n", list->str);
//assert( list->str == res[i] );
list = list->next;
//++i;
}
/* PRINT: one two :OK*/
}
But, when I try to assert if the string saved in the node of the list is equal to the result string (res[0] = "one" and res[1] = "two"), the assertion fail and a core dumped error appears:
test_hashtable_linprob: test_hashtable_linprob.c:1332: test_find_idup: Assertion `list->str == res[i]' failed.
==13842==
==13842== Process terminating with default action of signal 6 (SIGABRT)
==13842== at 0x4DEC18B: raise (raise.c:51)
==13842== by 0x4DCB858: abort (abort.c:79)
==13842== by 0x4DCB728: __assert_fail_base.cold (assert.c:92)
==13842== by 0x4DDCF35: __assert_fail (assert.c:101)
==13842== by 0x10E7E8: test_find_idup (test_hashtable_linprob.c:1332)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== HEAP SUMMARY:
==13842== in use at exit: 901 bytes in 11 blocks
==13842== total heap usage: 234 allocs, 223 frees, 169,605 bytes allocated
==13842==
==13842== 13 bytes in 3 blocks are definitely lost in loss record 2 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x11029D: upo_find_idup (hashtable.c:593)
==13842== by 0x10E771: test_find_idup (test_hashtable_linprob.c:1324)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== 424 (40 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 6 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x10F482: upo_ht_linprob_create (hashtable.c:313)
==13842== by 0x110093: upo_find_dup (hashtable.c:546)
==13842== by 0x10E66D: test_find_dup (test_hashtable_linprob.c:1310)
==13842== by 0x10EAC1: main (test_hashtable_linprob.c:1398)
==13842==
==13842== 424 (40 direct, 384 indirect) bytes in 1 blocks are definitely lost in loss record 7 of 7
==13842== at 0x4A37ECB: malloc (vg_replace_malloc.c:307)
==13842== by 0x10F482: upo_ht_linprob_create (hashtable.c:313)
==13842== by 0x110093: upo_find_dup (hashtable.c:546)
==13842== by 0x11035A: upo_find_idup (hashtable.c:602)
==13842== by 0x10E771: test_find_idup (test_hashtable_linprob.c:1324)
==13842== by 0x10EAF7: main (test_hashtable_linprob.c:1403)
==13842==
==13842== LEAK SUMMARY:
==13842== definitely lost: 93 bytes in 5 blocks
==13842== indirectly lost: 768 bytes in 2 blocks
==13842== possibly lost: 0 bytes in 0 blocks
==13842== still reachable: 40 bytes in 4 blocks
==13842== suppressed: 0 bytes in 0 blocks
==13842== Reachable blocks (those to which a pointer was found) are not shown.
==13842== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==13842==
==13842== For lists of detected and suppressed errors, rerun with: -s
==13842== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
Aborted (core dumped)
This is also the data structure:
/** \brief The type for nodes of list of strings. */
struct upo_strings_list_node_s {
char *str;
struct upo_strings_list_node_s *next;
};
/** \brief Alias for the type for nodes of list of strings. */
typedef struct upo_strings_list_node_s upo_strings_list_node_t;
/** \brief The type for list of strings. */
typedef upo_strings_list_node_t *upo_strings_list_t;
when I try to assert if the string saved in the node of the list is
equal to the result string (res[0] = "one" and res1 = "two"), the
assertion fail and a core dumped error appears
The fact that a core dump was produced is relevant only if you are inclined to load the dump into a debugger to examine the state of the program's memory when it aborted. Few people do that, and it is not uncommon for systems to be configured so that core dumps are not produced at all. I'll pay no further attention to it in this answer.
Many of your uses of assert() are inappropriate. Assertions are for run-time tests of the correctness of your code. They are useful for testing and documenting assumptions that your code makes about how other parts of your code will use it, or about characteristics the code relies upon the compiler to produce. Assertions must never contain code that you require to run on every execution of the program, such as tests for successful memory allocation, because they may be omitted from the executable completely depending on compile options. If one of your assertions fails, it always means that your code is buggy (possibly the assertion itself).
Write your own abort_unless() function or macro if you want a similar functionality for behavior that depends on input, runtime environment, or other behavior that may vary from run to run of the program.
Next, it looks like you're actually talking about this assertion, which is commented out in the code actually posted:
//assert( list->str == res[i] );
The test in that assertion has important differences from the one in your text, but I will focus on the one in the code. Possibly that particular use of assert is an appropriate one, so if it fails, then how is the code buggy? It is buggy because the == operator is comparing two char pointers themselves, not the data to which they point, and there is no reason for certainty that the two would be equal. You appear to want to employ strcmp(), instead:
assert(strcmp(list->str, res[i]) == 0);
Additionally, this code in upo_find_idup() ...
char *aux = malloc(sizeof(char*)); //For each string of strs to lowercase
... allocates enough space for a pointer itself, probably not more than 8 bytes. If you just wanted to store a pointer then there would be no need for the dynamic allocation or extra layer of indirection, but you're actually storing string contents. This will overrun the bounds of the allocated space if any of your strings are longer than a pointer.
Worse, your use of aux introduces unneeded extra work and code. It would be possible to allocate a long enough string for each case, but you're already doing that in the form of each aux_strs[i]. Just manipulate those directly.
Furthermore, the memory allocated for aux_strs itself is leaked, and so is the memory allocated for any of its members that are not carried through to the generated linked list. But this is also a bit of a logistical problem for you, because you must take care to avoid freeing the members that are carried through to the linked list. Furthermore, upo_find_dup() does not have enough information to do the freeing, because sometimes you call it with strings that it must not free in any case. A refactoring is probably needed here to enable you to manage memory correctly.
Try adding 32 to the ASCII value of each character, loops are the friends here.
Or you can use the built-in "toLower()" function.
Related
I am working on a function which allocates memory into an array, and then I free it later. Oddly enough, valgrind is giving me this error:
==93== HEAP SUMMARY:
==93== in use at exit: 11,160 bytes in 2,232 blocks
==93== total heap usage: 44,310 allocs, 42,078 frees, 1,632,230 bytes allocated
==93==
==93== 11,160 bytes in 2,232 blocks are definitely lost in loss record 1 of 1
==93== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==93== by 0x10976F: FillHashMap (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==93== by 0x1092F1: main (in /mnt/c/Users/Jordan/Documents/GitHub/flwg/flwp)
==93==
==93== LEAK SUMMARY:
==93== definitely lost: 11,160 bytes in 2,232 blocks
==93== indirectly lost: 0 bytes in 0 blocks
==93== possibly lost: 0 bytes in 0 blocks
==93== still reachable: 0 bytes in 0 blocks
==93== suppressed: 0 bytes in 0 blocks
==93==
==93== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Dr. Memory is giving me a similar error:
Error #1: UNADDRESSABLE ACCESS: reading 0x0000000000000000-0x0000000000000008 8 byte(s)
# 0 testing [C:/Users/Jordan/Documents/GitHub/flwg/FLWP-2.c:120]
# 1 main [C:/Users/Jordan/Documents/GitHub/flwg/FLWP-2.c:105]
Note: #0:00:01.195 in thread 14704
Note: instruction: mov (%rax) -> %rax
The strcmp line of code is what causes it to break with Dr. Memory, although valgrind says I have issues even if I don't call this particular method.
void testing(struct wordConnections *header){
header = header->nextRow;
while(strcmp(header->word, "berk") != 0){
header = header->nextRow;
if(header == NULL){
printf("Failed");
return;
}
}
}
The code that runs is (the value and significance of numLetters + 1 is it is the length of the char* stored in the wordStorage, the value of numLetters is 4):
char** FillHashMap(struct wordConnections **(*HashMap)){
int h = 0;
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity[3] = {132, 7420, 19829};
/*the word that we test, we add by two because first 4: word, 5th: \n, 6th: \0*/
char word[numLetters + 1];
/*how many times we've changed the character*/
int letterSpot = 0;
/*the character that goes through the file*/
char c;
FILE *flwd = OpenFile();
/* is it the first word of the line */
int wordCount = 0;
int isFirst = 1;
char p = fgetc(flwd);
c = p;
/* So, this is a temporary word, who will store the row, so all of its category folks will be contained within it */
char* rowWord = malloc(sizeof(char) * (numLetters + 1));
/*This stores all of the words*/
char** wordStorage = (char**)calloc(totalWordQuantity[numLetters - 2], sizeof(char*) * (numLetters + 1));
int i = 0;
/* First, take the character */
while((c = p) != EOF){
p = fgetc(flwd);
/* Add the character to the word */
word[letterSpot] = c;
/* Allows the letter spot to find the next place into the word */
letterSpot++;
/* Determines if the character is the placement immediately after the word */
if((c == ' ' && p != '\n') || c == '\n'){
letterSpot = 0;
/* Throws in the \0, converting into a string */
word[numLetters] = '\0';
wordStorage[wordCount] = malloc(sizeof(char) * (numLetters + 1));
h++;
strcpy(wordStorage[wordCount], word);
/* Determine if it's the first word */
if(isFirst == 1){
strcpy(rowWord, word);
/* Throw it in as a row */
AddRow2DLL(wordStorage[wordCount],
HashMap[FirstHashFunction(word[0])/*First Letter*/]
[SecondHashFunction(word)]/*First Vowel*/);
}
/* If it's not the first word */
else {
AddColumn2DLL(wordStorage[wordCount],
HashMap[FirstHashFunction(rowWord[0])/*First Letter*/]
[SecondHashFunction(rowWord)]/*First Vowel*/);
}
if(c == ' '){
isFirst = 0;
}
if(c == '\n'){
isFirst = 1;
}
wordCount++;
}
c = p;
}
free(rowWord);
fclose(flwd);
return wordStorage;
}
The hash map works fine, this is the method that causes the issues, without it, there are no memory leaks.
Later in the code, I free the wordStorage array with this method:
void FreeWordStorage(char** wordStorage){
int f = 0;
/* The Amount of words in each file, File 1, 2, 3 */
int totalWordQuantity[3] = {132, 7420, 19829};
int i;
for(i = 0; i < totalWordQuantity[numLetters - 2]; i++){
free(wordStorage[i]);
f++;
}
free(wordStorage);
}
I've tried all sorts of things to fix it. Oddly enough, when I check it with integers, I'm allocating and freeing the same amount of data.
Any help would be greatly appreciated. Thank you!
Valgrind's analysis indicates that the leaked memory was allocated by a bunch of malloc() calls by function FillHashMap(), and the only plausible candidate for those is this:
wordStorage[wordCount] = malloc(sizeof(char) * (numLetters + 1));
Function FreeWordStorage() appears to be correct for freeing the data allocated by FillHashMap(), so if some allocations are going unfreed then there are two main possibilities:
The pointer value returned by FillHashMap() is not later passed to FreeWordStorage(). The latter function might not be called at all on the code path that is being exercised, or perhaps a modified or outright wrong pointer is being passed to it.
Or,
Some or all of the pointers recorded in the allocated block returned by FillHashMap() are modified after being recorded, so that when it is called, FreeWordStorage() is ineffective at freeing the allocated memory.
Either one of those could be consistent with Dr. Memory's diagnostic, but whichever scenario applies, it does not appear to play out in the code presented in the question. I am reasonably confident that your pointers are being mangled somewhere else in the program.
I have written a small implementation of a simple stack in C using a linked list. The application works after a bit of fussing with gdb and valgrind. However, I have noticed that valgrind reports a number of "still reachable" leaks at termination of the program.
After some googling, I have found that these type of leaks are not an issue and that I generally shouldn't worry about them. Well that's great news! The only thing is, I would REALLY like to understand why valgrind sees these leaks and where they appear. I went to great pains through my first pass at this application to diligently release any allocated memory. What did I miss? Where are these allocations that valgrind sees but I cannot?
I have been staring at this for awhile now, and despite fiddling with the code this way and that, have come up empty handed. Hopefully you all can help me in this endeavor.
I have stripped the app down to a minimal example that will present the leak I am observing. It just initializes the stack and then immediately destroys it and exits.
// simple stack implementation
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
/*--- data structure in a stack item ---*/
struct data {
char * message;
};
/*--- stack item structure ---*/
struct item {
struct data * my_data;
struct item * next;
};
/*--- stack data structure ---*/
struct stack {
int initialized;
int empty;
struct item * head;
};
struct stack * my_stack;
/*--- create a new stack data structure with provided initial data ---*/
int
create_stack(struct data ** initial_items, int num_items) {
//allocate memory for the stack structure itself
my_stack = (struct stack *) malloc(sizeof(struct stack));
if(!my_stack) return -1;
my_stack->empty = 1;
my_stack ->initialized = 0;
if(num_items) {
//allocate memory for the head of the list first
my_stack->head = (struct item *) malloc(sizeof(struct item));
if(!my_stack->head) return -1;
my_stack->head->my_data = initial_items[0];
my_stack->head->next = NULL;
struct item * tracker = my_stack->head;
//fill the stack with elements containing the provided data
int i = 1;
for(; i < (num_items); i++) {
tracker->next = (struct item *) malloc(sizeof(struct item));
tracker = tracker->next;
if(!tracker) return -1;
tracker->my_data = initial_items[i];
tracker->next = NULL;
}
//no longer empty
my_stack->empty = 0;
}
//set initialized flag & return
my_stack->initialized = 1;
return 0;
}
/*--- destroy the stack by recursively freeing nodes ---*/
int
destroy_stack(struct item * recurse) {
//if the starting node is valid, begin
if(recurse) {
//if the current node links to another
if(recurse->next)
//recurse on the next node
destroy_stack(recurse->next);
else
//otherwise we hit the end, free the node
free(recurse);
}
//the starting node is invalid, just free the stack itself
else {
free(my_stack);
}
return 0;
}
/*--- test wrapper ---*/
int
main(int argc, char **argv) {
//initialize 10 element list of data structures to fill the stack items with
int i = 0;
int length = 10;
struct data ** initial_values = (struct data **) malloc(length*sizeof(struct data *));
//set each data element's value to i
for(; i < length; i++) {
char temp[16];
sprintf(temp, "%d", i);
initial_values[i] = (struct data *) malloc(sizeof(struct data));
initial_values[i]->message = strdup(temp);
}
//simple test case
//create a stack with the generated initial data, then destroy it
assert( !create_stack(initial_values, length) );
assert( !destroy_stack(my_stack->head) );
//free the string data our stack nodes were pointing to
i = 0;
while(i < length) {
free(initial_values[i]->message);
free(initial_values[i]);
i += 1;
}
free(initial_values);
return 0;
}
Running this through valgrind produces the following identified, unreleased blocks:
(trusty)kin3tix#localhost:~/C Practice/Data Structures$ valgrind --leak-check=full --show-leak-kinds=all ./stack_leak_test
==19340== Memcheck, a memory error detector
==19340== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==19340== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==19340== Command: ./stack_leak_test
==19340==
==19340==
==19340== HEAP SUMMARY:
==19340== in use at exit: 168 bytes in 10 blocks
==19340== total heap usage: 32 allocs, 22 frees, 364 bytes allocated
==19340==
==19340== 16 bytes in 1 blocks are still reachable in loss record 1 of 3
==19340== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19340== by 0x400739: create_stack (stack_leak_test.c:40)
==19340== by 0x40093B: main (stack_leak_test.c:95)
==19340==
==19340== 24 bytes in 1 blocks are still reachable in loss record 2 of 3
==19340== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19340== by 0x4006E6: create_stack (stack_leak_test.c:33)
==19340== by 0x40093B: main (stack_leak_test.c:95)
==19340==
==19340== 128 bytes in 8 blocks are still reachable in loss record 3 of 3
==19340== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19340== by 0x4007A1: create_stack (stack_leak_test.c:48)
==19340== by 0x40093B: main (stack_leak_test.c:95)
==19340==
==19340== LEAK SUMMARY:
==19340== definitely lost: 0 bytes in 0 blocks
==19340== indirectly lost: 0 bytes in 0 blocks
==19340== possibly lost: 0 bytes in 0 blocks
==19340== still reachable: 168 bytes in 10 blocks
==19340== suppressed: 0 bytes in 0 blocks
==19340==
==19340== For counts of detected and suppressed errors, rerun with: -v
==19340== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
They all seem to stem from "create_stack" but as far as I can tell my destroy function should be catching everything I allocate. What am I missing here?
Your destruction logic is trying to recursively combine two tasks (deleting the stack object and its items) in a single function. Worse, the else state shouldn't be there at all. You already determined you're sitting on a dynamic node (recurse). It needs to be deleted. Whether it has a next or not is not for the current depth to decide; that will be taken care of in the next depth of recursion.
Honestly, this is much simpler if you create a helper to wipe out the linked list, and as separate wrapper to do said-same to the stack itself:
/*--- destroy linked list nodes recursively ---*/
static void destroy_stack_items(struct item *item)
{
if (item)
{
destroy_stack_items(item->next);
free(item);
}
}
/*--- destroy the stack by recursively freeing nodes ---*/
int destroy_stack(struct stack *s)
{
if (s)
{
destroy_stack_items(s->head);
free(s);
}
return 0
}
and simply invoked as:
destroy_stack(my_stack);
Personally I would do it iteratively (thus remove the helper in the process), but I'm sure you have your reasons for otherwise. For example:
/*--- destroy the stack by iteratively freeing nodes ---*/
int destroy_stack(struct stack *s)
{
if (s)
{
while (s->head)
{
struct item *tmp = s->head;
s->head = tmp->next;
free(tmp);
}
free(s);
}
return 0
}
Best of luck.
I have made a minimal-working example of how to add elements to an array with realloc. This will be expanded in a future program that has many more elements.
#include <stdio.h>//printf
#include <stdlib.h>//malloc, realloc
int main() {
//BEGIN REALLOCATE-ABLE ARRAY
unsigned int *array, loop_variable;
const unsigned int ORIGINAL_ARRAY_SIZE = 4, REALLOC_INDICES = 99;
array = malloc(ORIGINAL_ARRAY_SIZE*sizeof(unsigned int));
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE; loop_variable++) {
array[loop_variable] = loop_variable;
}
//BEGIN REALLOCATION
for (loop_variable = 1; loop_variable < REALLOC_INDICES; loop_variable++) {
array = realloc(array,sizeof(unsigned int)*(ORIGINAL_ARRAY_SIZE+loop_variable));
array[ORIGINAL_ARRAY_SIZE+loop_variable-1] = 2*(ORIGINAL_ARRAY_SIZE+loop_variable-1);
printf("reallocate array[%d] = %d\n",ORIGINAL_ARRAY_SIZE+loop_variable-1,array[ORIGINAL_ARRAY_SIZE+loop_variable-1]);
}
//BEGIN PRINTING ARRAY VALUES
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE+REALLOC_INDICES-1; loop_variable++) {
printf("array[%d] = %d\n",loop_variable,array[loop_variable]);
}
//BEGIN FREE ARRAY
free(array); array = NULL;
return 0;
}
This should compile on any computer with gcc or clang. I then run this program on valgrind to ensure there are no memory leaks, and I get this:
==10791== HEAP SUMMARY:
==10791== in use at exit: 0 bytes in 0 blocks
==10791== total heap usage: 99 allocs, 99 frees, 20,988 bytes allocated
==10791==
==10791== All heap blocks were freed -- no leaks are possible
==10791==
==10791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==10791== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
However, what troubles me is that I'm using 20,988 bytes for a 101-element array. The memory use grows exponentially as the array gets bigger, instead of linearly by 4 bytes/element.
If I'm understanding Valgrind's output correctly, this array should have 4*101 elements = 404 bytes memory size, but appears to use about 50 times as much memory as it should. This is a trivial problem for such a small program, but more meaningful programs will run out of memory on this computer.
My question: is this array really using 20,988 bytes, or is Valgrind double-counting the memory?
Is there a more memory-efficient way to do this? I can't understand other examples of realloc, though I have tried to follow them as closely as I can and make this question relevant to as many users as possible.
==10791== in use at exit: 0 bytes in 0 blocks
==10791== total heap usage: 99 allocs, 99 frees, 20,988 bytes allocated
is this array really using 20,988 bytes
No, it's using 0 bytes.
“allocated” obviously means “ever allocated”, including bytes that have been freed, since the amount of memory “still allocated” is zero (and another line tells you that).
The answer, thanks to user Pascal Cuoq, is that Valgrind will sum the memory allocations for every allocation. This is why I was confused, and thought that realloc was using too much memory.
I thought that if you want to find the size of the array, you can comment out the line that says
free(array); array = NULL;
to intentionally introduce a memory bug, and Valgrind will output
==11699== LEAK SUMMARY:
==11699== definitely lost: 408 bytes in 1 blocks
==11699== indirectly lost: 0 bytes in 0 blocks
==11699== possibly lost: 0 bytes in 0 blocks
==11699== still reachable: 0 bytes in 0 blocks
==11699== suppressed: 0 bytes in 0 blocks
==11699==
==11699== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
==11699== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
which gives you the true size of the array at its last iteration. There is probably a better way to do this, but my point is made.
I added improvements suggested by other users here. I had a very difficult time finding good, minimal working examples of realloc on search engines, and for future use of anyone finding this on a search engine, this is very basic minimal working example of a good, but probably not best, how to use realloc in C:
#include <stdio.h>//include printf function
#include <stdlib.h>//include malloc, realloc functions
int main() {
/*BEGIN REALLOCATE-ABLE ARRAY*/
unsigned int *array, loop_variable;
const unsigned int ORIGINAL_ARRAY_SIZE = 4, REALLOC_INDICES = 99999;
array = malloc(ORIGINAL_ARRAY_SIZE*sizeof(unsigned int));
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE; loop_variable++) {
array[loop_variable] = loop_variable;
}
/*BEGIN REALLOCATION*/
for (loop_variable = 1; loop_variable < REALLOC_INDICES; loop_variable++) {
array = realloc(array,sizeof(unsigned int)*(ORIGINAL_ARRAY_SIZE+loop_variable));
if (array == NULL) {
printf("Array variable %d failed to reallocate :,-(\n",loop_variable);
exit(EXIT_FAILURE);
}
array[ORIGINAL_ARRAY_SIZE+loop_variable-1] = 2*(ORIGINAL_ARRAY_SIZE+loop_variable-1);
printf("reallocate array[%d] = %d\n",ORIGINAL_ARRAY_SIZE+loop_variable-1,array[ORIGINAL_ARRAY_SIZE+loop_variable-1]);
}
/*BEGIN PRINTING ARRAY VALUES*/
for (loop_variable = 0; loop_variable < ORIGINAL_ARRAY_SIZE+REALLOC_INDICES-1; loop_variable++) {
printf("array[%d] = %d\n",loop_variable,array[loop_variable]);
}
/*BEGIN FREE ARRAY*/
free(array); array = NULL;
return 0;
}
Need help again.
I've got my linked list working. It copies a list of words from a file into a linked list.
Now I want to make a hash table so that all words starting with the letter 'A' go into a bucket [0] of linked list.
The code I've written; it seems to work for small and large lists but Valgrind shows points to errors.
-----CODE-----
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct node //struct for linked list
{
char* word;
struct node* next;
}
node;
int findhash(char firstletter) //this function returns a hash value for first alphabet of every word
{
int hash = 0;
if(isupper(firstletter))
hash = firstletter-'A';
else hash = firstletter-'a';
return hash;
}
int main (void)
{
char* dictfile = "small";
FILE* dict = fopen(dictfile, "r");
if (dict == NULL)
return 1;
char oneword[47]; //to store the word from fscanf()
node* hashtable [30]; //creates a hashtable
for (int i = 0; i < 30; i++) //gives an index to every element in the hash table
{
node* temp = (node*)malloc(sizeof(node));
temp->next = NULL;
hashtable[i] = temp;
}
while ((fscanf (dict, "%s", oneword)) > 0)
{
node* temp = (node*)malloc(sizeof(node));
char* tempword = (char*)malloc(strlen(oneword)+1); //gives me a new pointer to store the string (as pointed out by Antione)
strcpy(tempword, oneword);
char firstletter = tempword[0];
int hash = 0;
hash = findhash(firstletter); //returns an index for the first alphabet of the word
temp->word = tempword;
//printf("%s\n", temp->word); //prints the value (just for debug)
temp->next = hashtable[hash];
hashtable[hash] = temp;
}
for (int i = 0; i < 30; i++)
{
node* temp = (node*)malloc(sizeof(node));
temp = hashtable[i];
while (temp != NULL) //loop to print the linked list
{
if (temp->word != NULL) //**THIS IS WHERE VALGRIND IS POINTING THE ERROR TO BE**
{
printf("%s\n", temp->word);
temp = temp->next;
}
else break;
}
}
printf("\n");
fclose(dict);
printf("SUCCESS!!\n");
}
Where am I going wrong?? Please help
-----VALGRIND ERROR-----
jharvard#appliance (~/Dropbox/pset5): valgrind ./tempeol
==11035== Memcheck, a memory error detector
==11035== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==11035== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==11035== Command: ./tempeol
==11035==
antione
==11035== Conditional jump or move depends on uninitialised value(s)
==11035== at 0x80488CA: main (tempeol.c:68)
==11035==
beer
bear
caterpillar
cat
google
root
SUCCESS!!
==11035==
==11035== HEAP SUMMARY:
==11035== in use at exit: 582 bytes in 74 blocks
==11035== total heap usage: 75 allocs, 1 frees, 934 bytes allocated
==11035==
==11035== LEAK SUMMARY:
==11035== definitely lost: 480 bytes in 60 blocks
==11035== indirectly lost: 102 bytes in 14 blocks
==11035== possibly lost: 0 bytes in 0 blocks
==11035== still reachable: 0 bytes in 0 blocks
==11035== suppressed: 0 bytes in 0 blocks
==11035== Rerun with --leak-check=full to see details of leaked memory
==11035==
==11035== For counts of detected and suppressed errors, rerun with: -v
==11035== Use --track-origins=yes to see where uninitialised values come from
==11035== ERROR SUMMARY: 30 errors from 1 contexts (suppressed: 0 from 0)
Valgrind shows 30 errors. My hashtable is size 30. So feel the problem should be somewhere there. But I can't figure out why?
Your initialization of the hashtable entries isn't initializing the field word, that is what valgrind is complaining about.
Additionally your code seems to have other problems. E.g the malloc in the line just before is immediately overwritten and thus this memory leaks. Also the return of malloc shouldn't be cast. Avoid casts whenever you can, think of casts as "casting a spell". As long as you don't know what that does, avoid it.
I've seen another question for allocating and freeing multi-dimensional arrays, but I suspect that it does not free correctly. For testing I made this small code extracted from my main code.
I compiled it under MacOS X.10 with XCode or gcc 4.9 with same results:
Faulty code
It runs 200000 times and the memory consumption grows up to 20GB!:
#include <stdlib.h>
typedef struct{
int lonSize;
int latSize;
double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;
void free_raf09_grid() {
if (raf09_grid.grid != NULL) {
int i;
for (i = 0; i < raf09_grid.lonSize; ++i) {
free(raf09_grid.grid[i]);
}
free(raf09_grid.grid);
}
raf09_grid.latSize = 0;
raf09_grid.lonSize = 0;
}
void get_raf09_grid() {
int nbElLat=381;
int nbElLon=421;
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
int i,j;
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
}
}
int main (int argc, char *argv[]) {
int i=0;
for (i=0;i<20000;i++) {
get_raf09_grid();
free_raf09_grid();
}
return 0;
}
I'm newbie so I suspect that my freeing is not correct...
Corrected code
With your help I corrected my code, it is now corrects and takes only 10M in ram:
#include <stdlib.h>
typedef struct{
int lonSize;
int latSize;
double **grid;
}raf09_grid_t;
static raf09_grid_t raf09_grid;
void free_raf09_grid() {
if (raf09_grid.grid != NULL) {
int i;
for (i = 0; i < raf09_grid.lonSize; ++i) {
free(raf09_grid.grid[i]);
}
free(raf09_grid.grid);
}
raf09_grid.latSize = 0;
raf09_grid.lonSize = 0;
}
void get_raf09_grid() {
raf09_grid.latSize=381;
raf09_grid.lonSize=421;
raf09_grid.grid = malloc(raf09_grid.lonSize*sizeof(double*));
int it;
for(it=0;it<raf09_grid.lonSize;it++)
raf09_grid.grid[it] = malloc(raf09_grid.latSize*sizeof(double));
int i,j;
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
}
}
int main (int argc, char *argv[]) {
int i=0;
for (i=0;i<20000;i++) {
get_raf09_grid();
free_raf09_grid();
}
return 0;
}
Valgrind is an invaluable tool in tracing memory leaks. Compiling your source code with debug information, and running it with:
valgrind --leak-check=full -v ./a.out
will give the following summary:
==7033== HEAP SUMMARY:
==7033== in use at exit: 1,283,208,000 bytes in 421,000 blocks
==7033== total heap usage: 422,000 allocs, 1,000 frees, 1,286,576,000 bytes allocated
==7033==
==7033== Searching for pointers to 421,000 not-freed blocks
==7033== Checked 92,040 bytes
==7033==
==7033== 18,288 bytes in 6 blocks are possibly lost in loss record 1 of 2
==7033== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033== by 0x400611: get_raf09_grid (grid.c:27)
==7033== by 0x4006A8: main (grid.c:39)
==7033==
==7033== 1,283,189,712 bytes in 420,994 blocks are definitely lost in loss record 2 of 2
==7033== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7033== by 0x400611: get_raf09_grid (grid.c:27)
==7033== by 0x4006A8: main (grid.c:39)
==7033==
==7033== LEAK SUMMARY:
==7033== definitely lost: 1,283,189,712 bytes in 420,994 blocks
==7033== indirectly lost: 0 bytes in 0 blocks
==7033== possibly lost: 18,288 bytes in 6 blocks
==7033== still reachable: 0 bytes in 0 blocks
==7033== suppressed: 0 bytes in 0 blocks
==7033==
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
--7033--
--7033-- used_suppression: 2 dl-hack3-cond-1
==7033==
==7033== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 2 from 2)
The link to line 27 shows that there is a problem with this statement:
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
You are allocating more memory here than is being freed later in the program.
Update the raf09_grid.lonSize variable in get_raf09_grid() to equal nbElLon, and it fixes the problem.
In general, every malloc should have a corresponding free. Once you know which malloc is leaking, then you can find the code that is supposed to free that variable, and debug from there.
Note: I reduced the loop from 20000 to 1000, but it will give you the same information.
After reading through yoiur question, here are a few suggestions:
In the code:
for(i=0;i<420;i++) {
for(j=0;j<380;j++) {
raf09_grid.grid[i][j]=0.0;
}
you are looping i and j for 420 and 380, while you've defined :
int nbElLat=381;
int nbElLon=421;
So, you never process the 420th iteration for the Longitudes. The same with missing out on the 380th loop for Latitude.
If that's a desirable thing, its fine, else you should fix it to something like this:
for(i=0;i<nbElLon;i++) { //better use macros or variable names than just plain magic numbers
for(j=0;j<nbElLat;j++) {
raf09_grid.grid[i][j]=0.0;
}
Second, in your free_raf09_grid() function, you use:
for (i = 0; i < raf09_grid.lonSize; ++i) {
but you haven't initialized that variable anywhere.
Perhaps in function get_raf09_grid() just before the declaration of int i,j do this:
raf09_grid.lonSize = nbElLon;
raf09_grid.latSize = nbElLat;
The third important one.
In the lines below:
raf09_grid.grid = malloc(nbElLon*sizeof(double*));
int it;
for(it=0;it<nbElLon;it++)
raf09_grid.grid[it] = malloc(nbElLat*sizeof(double));
you should check if the mallocs have returned success or not aka check for NULL.
your for loop uses lonSize as a parameter, but it doesn't get updated anywhere