Create string.out from string.in in C - c

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));

Related

Calling free() on a variable initialised by strdup still results in memory leak

I have the following code:
static const char * path[2];
int main(int argc, char *argv[]) {
// validate argument
char * temp = dirname(dirname(strdup(argv[optind])));
path[0] = temp
path[1] = NULL;
// do stuff
free(temp);
return 0;
}
I understand that strdup allocates memory which needs to be freed in order to avoid memory leaks. I attempt to do this before returning from the function but the leak still presists.
Valgrind output:
$ valgrind --leak-check=full -s ./tstprog meta_schema.schema
==36849== Memcheck, a memory error detector
==36849== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==36849== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==36849== Command: ./tstprog meta_schema.schema
==36849==
==36849== Invalid free() / delete / delete[] / realloc()
==36849== at 0x484827F: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==36849== by 0x11577A: main (tstprog.c:134)
==36849== Address 0x4a42ae1 is 0 bytes inside data symbol "dot.0"
==36849==
==36849==
==36849== HEAP SUMMARY:
==36849== in use at exit: 19 bytes in 1 blocks
==36849== total heap usage: 255 allocs, 255 frees, 64,111 bytes allocated
==36849==
==36849== 19 bytes in 1 blocks are definitely lost in loss record 1 of 1
==36849== at 0x4845899: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==36849== by 0x49240CF: strdup (in /usr/lib/libc.so.6)
==36849== by 0x1155C1: main (tstprog.c:108)
==36849==
==36849== LEAK SUMMARY:
==36849== definitely lost: 19 bytes in 1 blocks
==36849== indirectly lost: 0 bytes in 0 blocks
==36849== possibly lost: 0 bytes in 0 blocks
==36849== still reachable: 0 bytes in 0 blocks
==36849== suppressed: 0 bytes in 0 blocks
==36849==
==36849== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
==36849==
==36849== 1 errors in context 1 of 2:
==36849== Invalid free() / delete / delete[] / realloc()
==36849== at 0x484827F: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==36849== by 0x11577A: main (tstprog.c:134)
==36849== Address 0x4a42ae1 is 0 bytes inside data symbol "dot.0"
==36849==
==36849== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
I have also looked at this post and they seem to do the same thing when they call free(who->name).
What am I missing?
Quoting from dirname man page
Both dirname() and basename() return pointers to null-terminated strings.
(Do not pass these pointers to free(3).)
You are not freeing strdup result (which you can, indeed). You are freeing dirname result. Which you can't.

How to view all mallocs in valgrind

Normally to run valgrind to check for memory leaks I'll do something like this:
$ valgrind --leak-check=full ./main
==1431== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==1431== HEAP SUMMARY:
==1431== in use at exit: 0 bytes in 0 blocks
==1431== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==1431==
==1431== All heap blocks were freed -- no leaks are possible
==1431==
==1431== For counts of detected and suppressed errors, rerun with: -v
==1431== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Is there a way where I can see where the following malloc / free was done, even though it doesn't result in an error?
==1431== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
The program I am running is the following:
#include <stdio.h>
int main(void)
{
printf("Hi\n");
}
The malloc is located in the printf (obviously) and when I comment out that line the mallocs go away in valgrind: but how can I see the 'trace' for the malloc within the printf function?
Here is what shows from using massif:
n1: 1024 (heap allocation functions) malloc/new/new[], --alloc-fns, etc.
n1: 1024 0x4EB11FA: _IO_file_doallocate (filedoalloc.c:101)
n1: 1024 0x4EC13E7: _IO_doallocbuf (genops.c:365)
n1: 1024 0x4EC0506: _IO_file_overflow##GLIBC_2.2.5 (fileops.c:759)
n1: 1024 0x4EBEA5B: _IO_file_xsputn##GLIBC_2.2.5 (fileops.c:1266)
n1: 1024 0x4EB3AFD: puts (ioputs.c:40)
n0: 1024 0x108648: main (main.c:4)
But it's a bit opaque to me how the printf goes that far into the function calls to do the allocations.

Read in Words from Text File and Store into Dynamic Array Valgrind Errors in C

I'm trying to read in words from a text file in C using fscanf and putthem into a dynamically allocated array. However, I keep getting errors in Valgrind and (null) characters seem to be popping up in my output. I create a double pointer **str_array to hold each character array and initially allocate enough space for 4 character arrays. fscanf runs and stores the read in string into str[] and I use strcpy to copy str[]'s string into str_array. I realloc memory if str_array needs to hold more strings.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char str[80];
int word_alloc = 0;
int word_count = 0;
char **str_array;
FILE *file;
file = fopen(argv[1], "r");
// Allocate memory to the array of strings (char arrays)
word_alloc = 4;
str_array = (char **) malloc(sizeof(char*) * word_alloc);
while (fscanf(file, "%s", str) != EOF) {
// If there are more than 4 strings, double size
if (word_count > word_alloc) {
word_alloc *= 2;
str_array = (char **) realloc(str_array, sizeof(char*) * word_alloc);
}
str_array[word_count] = (char *) malloc(sizeof(char) * (strlen(str) + 1));
strcpy(str_array[word_count], str);
++word_count;
}
int i = 0;
for (; i<word_count; i++) {
printf("Word: %s\n", str_array[i]);
}
i = 0;
for (; i<word_count; i++) {
free(str_array[word_count]);
}
free(str_array);
fclose(file);
return 0;
}
Here's the Valgrind error code.
==6254== Memcheck, a memory error detector
==6254== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==6254== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==6254== Command: ./a.out readin-test.txt
==6254==
==6254== Invalid write of size 8
==6254== at 0x4008A6: main (readin-test.c:25)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Invalid read of size 8
==6254== at 0x4008C0: main (readin-test.c:26)
==6254== Address 0x51fc2e0 is 0 bytes after a block of size 32 alloc'd
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400835: main (readin-test.c:16)
==6254==
==6254== Conditional jump or move depends on uninitialised value(s)
==6254== at 0x4C2BDA2: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x40094A: main (readin-test.c:37)
==6254== Uninitialised value was created by a heap allocation
==6254== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x400871: main (readin-test.c:22)
==6254==
==6254==
==6254== HEAP SUMMARY:
==6254== in use at exit: 999 bytes in 173 blocks
==6254== total heap usage: 181 allocs, 8 frees, 5,631 bytes allocated
==6254==
==6254== 999 bytes in 173 blocks are definitely lost in loss record 1 of 1
==6254== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6254== by 0x4008A5: main (readin-test.c:25)
==6254==
==6254== LEAK SUMMARY:
==6254== definitely lost: 999 bytes in 173 blocks
==6254== indirectly lost: 0 bytes in 0 blocks
==6254== possibly lost: 0 bytes in 0 blocks
==6254== still reachable: 0 bytes in 0 blocks
==6254== suppressed: 0 bytes in 0 blocks
==6254==
==6254== For counts of detected and suppressed errors, rerun with: -v
==6254== ERROR SUMMARY: 186 errors from 4 contexts (suppressed: 0 from 0)
You have an error in the free loop:
i = 0;
for (; i<word_count; i++) {
free(str_array[word_count]);
}
The array index should be i, not word_count.

Invalid write of size 8, C Valgrind, string arrays

I have been using both valgrind and gdb and I can not quite figure out what the problem is. It hops around too much for me to really trace it down in gdb, and in valgrind I don't have enough information. Here is my makeargv function, which is putting strings outputted from strtok() into arrays. makeargv is called from the below parse function. I'm not sure where I'm going wrong. I would really appreciate the help :D.
Just an FYI I'm really new to all this malloc'ing and don't really understand the concept as well as I would like. I'm not sure when specifically I should be mallocing. I feel like since here I am mainly setting constant values I don't have to be, but I'm wondering why it won't work.
makeargv function
int makeargv(const char *string, char **argvp) {
int i = 0;
int numtokens = 0;
const char *copy;
char *buffer = malloc(160*sizeof(char));
if ((string == NULL) || (delims == NULL) || (argvp == NULL)) {
return -1;
}
argvp = NULL;
copy = string + strspn(string, delims);
if ((buffer = malloc(strlen(copy) + 1)) == NULL) {
return -1;
}
strcpy(buffer, copy);
numtokens = 0;
if (strtok(buffer, delims) != NULL) {
for (numtokens = 1; strtok(NULL, delims) != NULL; numtokens++);
}
if ((argvp = malloc((numtokens + 2)*sizeof(int))) == NULL) {
free(buffer);
return -1;
}
if (numtokens == 0) {
free(buffer);
}
else {
strcpy(buffer, copy);
*argvp = malloc(16);
*argvp = strtok(buffer, delims);
for (i = 2; i < (numtokens*2); i += 2) {
*(argvp + i) = strtok(NULL, delims);
//printf("%s\n", strtok(NULL, delims)); /*When I run this the tokens come out
correctly so I know it isn't a problem with strtok */
}
}
// *((argvp) + numtokens) = NULL;
free(buffer);
return numtokens;
}
Parse function
void parse_file(char* filename) {
char* line = malloc(160*sizeof(char));
FILE* fp = file_open(filename);
int i = 0;
while((line = file_getline(line, fp)) != NULL) {
char** results = malloc(16*10*sizeof(char));
if (strlen(line) == 1){
continue;
}
if ((i = makeargv(line, results)) == -1){
printf("ERROR SOMEWHERE IN MAKEARGV");
continue;
}
}
fclose(fp);
free(line);
}
valgrind output
==7309== Memcheck, a memory error detector
==7309== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==7309== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==7309== Command: ./custmake
==7309==
==7309== Invalid write of size 8
==7309== at 0x400C23: makeargv (main.c:62)
==7309== by 0x400CD4: parse_file (main.c:120)
==7309== by 0x400DFF: main (main.c:172)
==7309== Address 0x51f25c0 is 16 bytes inside a block of size 20 alloc'd
==7309== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x400B76: makeargv (main.c:49)
==7309== by 0x400CD4: parse_file (main.c:120)
==7309== by 0x400DFF: main (main.c:172)
==7309==
==7309== Use of uninitialised value of size 8
==7309== at 0x4C2BFC2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x4EA2CEB: puts (ioputs.c:37)
==7309== by 0x400D09: parse_file (main.c:128)
==7309== by 0x400DFF: main (main.c:172)
==7309==
==7309== Invalid read of size 1
==7309== at 0x4C2BFC2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x4EA2CEB: puts (ioputs.c:37)
==7309== by 0x400D09: parse_file (main.c:128)
==7309== by 0x400DFF: main (main.c:172)
==7309== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==7309==
==7309==
==7309== Process terminating with default action of signal 11 (SIGSEGV)
==7309== Access not within mapped region at address 0x0
==7309== at 0x4C2BFC2: __GI_strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x4EA2CEB: puts (ioputs.c:37)
==7309== by 0x400D09: parse_file (main.c:128)
==7309== by 0x400DFF: main (main.c:172)
==7309== If you believe this happened as a result of a stack
==7309== overflow in your program's main thread (unlikely but
==7309== possible), you can try to increase the size of the
==7309== main thread stack using the --main-stacksize= flag.
==7309== The main thread stack size used in this run was 8388608.
==7309==
==7309== HEAP SUMMARY:
==7309== in use at exit: 1,084 bytes in 6 blocks
==7309== total heap usage: 7 allocs, 1 frees, 1,100 bytes allocated
==7309==
==7309== 16 bytes in 1 blocks are definitely lost in loss record 1 of 6
==7309== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x400BCB: makeargv (main.c:59)
==7309== by 0x400CD4: parse_file (main.c:120)
==7309== by 0x400DFF: main (main.c:172)
==7309==
==7309== 20 bytes in 1 blocks are definitely lost in loss record 2 of 6
==7309== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x400B76: makeargv (main.c:49)
==7309== by 0x400CD4: parse_file (main.c:120)
==7309== by 0x400DFF: main (main.c:172)
==7309==
==7309== 160 bytes in 1 blocks are definitely lost in loss record 5 of 6
==7309== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7309== by 0x400A6E: makeargv (main.c:32)
==7309== by 0x400CD4: parse_file (main.c:120)
==7309== by 0x400DFF: main (main.c:172)
==7309==
==7309== LEAK SUMMARY:
==7309== definitely lost: 196 bytes in 3 blocks
==7309== indirectly lost: 0 bytes in 0 blocks
==7309== possibly lost: 0 bytes in 0 blocks
==7309== still reachable: 888 bytes in 3 blocks
==7309== suppressed: 0 bytes in 0 blocks
==7309== Reachable blocks (those to which a pointer was found) are not shown.
==7309== To see them, rerun with: --leak-check=full --show-reachable=yes
==7309==
==7309== For counts of detected and suppressed errors, rerun with: -v
==7309== Use --track-origins=yes to see where uninitialised values come from
==7309== ERROR SUMMARY: 7 errors from 6 contexts (suppressed: 2 from 2)
Segmentation fault (core dumped)
Your argvp variable in makeargv is an array of pointers, but when you allocate he memory for it you use sizeof(int) which will only be four bytes on a 64 bit system, while pointers will be 8 bytes.
As a result you write beyond the end of the array - that's why it reports you writing 8 bytes at offset 16 of a 20 byte block, which therefore overlaps the end of the block by 4 bytes.
Use sizeof(char *) to get the correct size of a pointer when allocating the argvp array.

What's the problem with this code? [hashtable in C]

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.

Resources