This problem is similar to mine.
But deliver no solution for me.
This is only a simplified code for testing and better understanding.
I know that this code doesn't care of problems after the malloc functions.
The code is for saving words in a struct called List, within a char** storage that used as array.
To create the list and add an item works fine.
But the deletion of the list makes problems.
Here is the code:
Declaration of the list:
typedef struct {
char** storage;
} List;
Main:
int main(){
int size = 2;
List* list;
list = new_list(2);
add(list, "Hello", 0);
add(list, "World", 1);
printf("\nlist->storage[0]: %s", list->storage[0]);
printf("\nlist->storage[1]: %s", list->storage[1]);
delete_list(&list,size);
return 0;
}
Make a new list:
List* new_list(size) {
List* listptr = malloc(sizeof(List));
listptr->storage = (char**)malloc(size * sizeof(char));
return listptr;
}
Add a string to the list:
void add(List* list, char* string, int pos) {
list->storage[pos] = (char*)malloc(strlen(string) * sizeof(char));
list->storage[pos] = string;
}
Delete the list, with all members:
void delete_list(List** list, int size) {
int a = 0;
for (a = 0; a < size; a++)
free((*list)->storage[a]);
free((*list)->storage);
free(*list);
}
Here I get an error in the for loop, at the line 'free((*list)->storage[a])'.
The goal is here to delete every allocated string.
If the list has no members, therefore the code run not in the for loop and the 'delte_list' function work well.
So that is my mistake in the line:
'free((*list)->storage[a])'
This allocation is wrong:
listptr->storage = (char**)malloc(size * sizeof(char));
^^^^^
As storage is a char** the sizeof should be sizeof(char*). When you only use sizeof(char) you end up with too little memory and later you write outside the allocated memory.
Also this line:
list->storage[pos] = string;
seems wrong.
Here you probably need a strcpy like:
strcpy(list->storage[pos], string)
and also add 1 to the malloc for the string termination, i.e.
malloc((1 + strlen(string)) * sizeof(char));
but notice that sizeof(char) is always 1 so
malloc(1 + strlen(string));
is fine.
BTW: A good way of getting your malloc correct is to use "sizeof what_the_variable_points_to". Like:
char** x = malloc(size * sizeof *x);
^^
Use *x instead of sizeof(char*)
in this way you always get the correct size and avoid bugs due to simple typos.
As an example from your code:
List* listptr = malloc(sizeof(List)); // works but
List* listptr = malloc(sizeof *listptr); // this is less error prone
Related
I have an array of strings that is dynamically sized (I won't know the size of the strings at compile) that keeps giving me a segmentation fault error. The array is contained in a struct called hm and it has an array for the strings as well as an array for values. This part of the code is only to resize the string array properly when a new string is added to the struct.
I am relatively new to C and structs, so if there is a better way to implement this I would love to hear about it. I have already tried looking around for this situation and most seem to be having the issue with the outer array using sizeof(char) instead of sizeof(char*), but when I changed that the issue still happens.
//problematic part of the function
char** t = (char**)realloc(hm->keys, hm->size * sizeof(char*));
if (t) hm->keys = t;
for (i = 0; i < hm->size; i++) {
char* temp = (char*)realloc(hm->keys[i], hm->largestKey * sizeof(char)); //seg fault here
if (temp) {
hm->keys[i] = temp;
}
}
//struct
typedef struct HM_struct {
size_t size;
size_t largestKey;
char** keys;
int* values;
void (*add)(struct HM_struct* hm, char* key, int value);
} HM;
The problem is that when you realloc() and increase the allocated memory size, the new memory is not initialised (or with a debug library, initialised to a sentinal value). So, assuming you know the oldSize, a quick fix is:
char** t = realloc(hm->keys, hm->size * sizeof(char*)); // As before
if (t) hm->keys = t; // As before
for (i = oldSize; i < hm->size; i++)
hm->keys[i] = NULL;
Now, according to the realloc() definition, when you call:
char* temp = realloc(NULL, hm->largestKey * sizeof(char));
It behaves as:
char* temp = malloc(hm->largestKey * sizeof(char));
So here is my problem, I have created this struct:
typedef struct foo *fooPtr;
struct foo {
foo2Ptr node;
foo3Ptr node;
char *Random;
};
fooNew(char* String) {
int StringLength;
StringLength = strlen(String) + 1;
Newfoo = (fooPtr *)malloc(sizeof(fooPtr));
Newfoo->Random = (char*)malloc(StringLength * sizeof(char));
strcpy(Newfoo->Random, String);
/*Rest of foo members initialized below....*/
}
fooChangeRandom(fooPtr Foo, String) {
int StringLength;
StringLength = strlen(String) + 1;
free(Foo->Random);
Foo->Random = (char*)malloc(StringLength * sizeof(char));
strcpy(Foo->Random, String);
}
But whenever I try to print the new string I get random characters. As I recall C requires me to free everything I allocate with malloc, calloc, or realloc so how does Random change when the fooNew ends? Tried to debug and at free I get the SIGTRAP error, on the line that free() gets used, however this is the only dynamically allocated object I have created and I haven't used free before. So Is there something I am missing or something wrong with the syntax of malloc or free?
You need to correct
Newfoo = (fooPtr *)malloc(sizeof(fooPtr));
to
Newfoo = (fooPtr *)malloc(sizeof(struct foo));
I made an array of Node structs and I am trying to sort nodes in alphabetical order based on their char* variable called "word".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memwatch.h"
#include "concord.h"
#define BUFFSIZE 1000
int main(int argc, char** argv)
{
Node** list;
printf("%s%s\n","The file name is ", argv[1]);
readInputFile(argv[1], list);
return 0;
}
int compareWords(const void* nodeA, const void* nodeB)
{
Node* nodeAA = (Node *) nodeA;
Node* nodeBB = (Node *) nodeB;
puts("now here\n");
printf("%s\n", nodeAA->word);
printf("%s\n", nodeBB->word);
return strcmp(nodeAA->word, nodeBB->word);
}
void readInputFile(char* filename, Node** wordList)
{
FILE* file;
file = fopen(filename, "r");
wordList = calloc(BUFFSIZE, sizeof(Node*));
char* currentWord;
currentWord = (char*) malloc(sizeof(char) *BUFFSIZE);
int i;
i = 0;
while(fscanf(file, "%s", currentWord) == 1)
{
wordList[i] = (Node*) malloc(sizeof(Node));
wordList[i]->word = strdup(currentWord);
puts(wordList[i]->word);
}
fclose(file);
qsort(wordList, i, sizeof(Node), compareWords);
}
Before I was printing out garbage when I tried to print out the word in the compare function, now it looks like the function is not even being called.
now it looks like the function is not even being called.
That is because to sort a list of 0 elements you never need to compare two elements:
// ...
int i;
i = 0; // --- set to 0
while(fscanf(file, "%s", currentWord) == 1)
{
// i not changed ... causes other problems, too
// (contents omited)
}
fclose(file);
// i is still 0
qsort(wordList, i, sizeof(Node), compareWords);
// ...
Apart from that your usage of an "out parameters" is wrong, as pointed out in the comment by David C. Rankin. In this case, i'd also advise to just use the return value.
Moreover, I'd split that function into multiple functions:
// Does the file opening and closing, calls readInput
Node * readInputFile(char const *);
// The actual reading
Node * readInput(FILE *)
// Probably do the sorting outside of these functions
[First of all you question is incomplete as it misses to show us the definition of Node.]
However, three issues here:
I made an array of Node structs
You don't.
Here
wordList = calloc(BUFFSIZE, sizeof(Node*));
you allocate memory for an array of pointers to Node.
And then here
wordList[i] = (Node*) malloc(sizeof(Node));
you allocated a separate chunk of memory to each element of the pointer array created previously.
The latter may be scattered all over the process's memory. They will not be located in a continous block of memory, as expected by qsort(), which might have been the reason for:
I was printing out garbage [before]
On returning from readInputFile() the value of wordList is lost.
The reading loop does not increment the index counter i.
To fix 1. and 2. create an array and return a reference to it back up to the caller of readInputFile() like so
*wordList = calloc(BUFFSIZE, sizeof **wordList);
and call qsort() like this:
qsort(*wordList, i, sizeof(Node), compareWords);
To fix 3. do this:
size_t i = 0; /* No need for negative indexes here .*/
while((i < BUFFSIZE) /* Male sure not to overflow the array. */
&& (fscanf(file, "%s", currentWord) == 1))
{
(*wordList)[i].word = strdup(currentWord); /* This is POSIX not Standard C. */
puts((*wordList)[i].word);
++i;
}
I have been looking online but so far nothing has helped me understand my problem. Currently I am trying to make two lists that each contain a list of words. Each space contains a word struct and within each word struct is list of 30 doc_list structs. I have been able to allocate memory and store a char*s within the word list struct but when I try to allocate memory and store a char* within a doc_list struct I get a segmentation error. I am confused because I declared my doc_list struct the same exact way as I did my word_list struct.
Below is the initialization of my structs
In my C file I initialize my Hash Table
#define BUFFSIZE 1000
#define STOPLIST_INDEX 0
#define DOCUMENTS_INDEX 1
struct HashTable{
int tableSize;
struct word_list** wordList;
};
struct word_list{
char* word;
struct doc_list** docList;
};
struct doc_list{
char* docName;
int timesAppear;
};
//Initialing lists associated with hash table
struct HashTable** initialize_hash_table(int argc, char** argv)
{
int k; //HashTables
int i; //Words
int q; //Document names
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable **));
for(k =0; k < 2; k++)
{
hashTable[k] = calloc (1, sizeof(struct HashTable *));
hashTable[k]->wordList = calloc(BUFFSIZE, sizeof(struct word_list **));
for(i = 0; i < BUFFSIZE; i++)
{
hashTable[k]->wordList[i] = calloc(1, sizeof(struct word_list *));
hashTable[k]->wordList[i]->docList = calloc(30, sizeof(struct doc_list**));
for(q = 0; q < 30; q++)
{
hashTable[k]->wordList[i]->docList[q] = calloc(1, sizeof(struct doc_list*));
}
}
}
return hashTable;
}
then in my insert function where I store the document name char* value is where I get a segmentation error. I don't understand why this happens because I initialized my doc_list structure the exact same way that I initialized my word_list structure.
int insert(struct HashTable** hashTable, char* document_word, char* filename, int index)
{
//create the hash key
int key = hashFunction(document_word, BUFFSIZE);
//Check if word exists in Stop List
if(index == 0 || hashTable[STOPLIST_INDEX]->wordList[key]->word == NULL)
{
//insert into list
hashTable[index]->wordList[key] = malloc(sizeof(struct word_list*));
hashTable[index]->wordList[key]->word = strdup(document_word);
printf("%s%s\n", "INSERTED VALUE: ", hashTable[index]->wordList[key]->word);
//Add filename to words' document list
int w = 0;
puts("segfaulting here");
puts("1");
hashTable[index]->wordList[key]->docList[w] = malloc(sizeof(struct doc_list*));
hashTable[index]->wordList[key]->docList[w]->docName = strdup(filename);
printf("%s%s\n", "INSERTED ", filename);
printf("\n");
}
return 0;
}
What I believe is happening is that all the word structs are being declared NULL if they are not allocated memory for a word but none of the doc_list structs are being declared NULL for some reason. I allocated memory for them the exact same way I did the word_list structs.
The output when I run the program is this:
Hashing filename:stopwords.txt
---------
INSERTED VALUE: a
segfaulting here
1
Segmentation fault (core dumped)
What am I doing wrong??
Problems I see:
hashTable[k] = calloc (1, sizeof(struct HashTable *));
needs to be changed to
hashTable[k] = calloc (1, sizeof(struct HashTable));
Type of hasTable[k] is struct HashTable*. The object that it points to has to be of size struct HashTable, not struct HashTable*.
There is a similar error in:
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable **));
It needs to be:
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable*));
You won't see the error easily since sizeof(struct HashTable*) is equal to sizeof(struct HashTable**) in most cases.
More of such errors are in initialize_hash_table.
hashTable[k]->wordList[i]->docList = calloc(30, sizeof(struct doc_list**));
needs to be
hashTable[k]->wordList[i]->docList = calloc(30, sizeof(struct doc_list*));
hashTable[k]->wordList[i]->docList[q] = calloc(1, sizeof(struct doc_list*));
needs to be
hashTable[k]->wordList[i]->docList[q] = calloc(1, sizeof(struct doc_list));
You have similar errors in insert.
hashTable[index]->wordList[key] = malloc(sizeof(struct word_list*));
needs to be
hashTable[index]->wordList[key] = malloc(sizeof(struct word_list));
hashTable[index]->wordList[key]->docList[w] = malloc(sizeof(struct doc_list*));
needs to be
hashTable[index]->wordList[key]->docList[w] = malloc(sizeof(struct doc_list));
Tip: Only use calloc if you actually need your memory zeroed. malloc is faster.
Also, there is no need to test unequality to 0 NULL \0, unless you need your truth value normalized to 0|1, and even then !! is preferrable. ! for equality to 0 in any of its guises.
But your real problem is something else:
struct HashTable** hashTable = calloc(2, sizeof(struct HashTable **));
The above line alloates zeroed memory for 2 struct HashTable**, and stores the pointer in hashTable, which has type sttruct HashTable** too!!
You actually want to allocate space for 2 struct HashTable*.
In this one specific case it does not kill you, because those two pointer types happen to use the same amount of space on this architecture, but it's a pattern which is repeated with worse results later, and allocating too little memory leads to buffer overruns, which as Undefined Behavior mean anything can happen (and naturally mostly bad things).
When you want to point with pointer p to a memory block, allocate it thus:
p = malloc(count * sizeof *p);
p = calloc(count, sizeof *p); /* only for zeroed memory */
You do not want to use sizeof on the type, because it is far too easy to get it wrong, adding or leaving off one or more levels of indirection or taking a completely unrelated type.
Unless you name a VLA to sizeof, it will not evaluate its arguments, but only get the type and derive a compile-ime-constant.
Some more things you should read:
How to Debug Small Programs
C99 with Technical corrigenda TC1, TC2, and TC3 included
MCVE
How does one malloc an array of structs correctly if each struct contains an array of strings which vary in size?
So each struct might have a different size and would make it impossible to
realloc(numberOfStructs * sizeof(structName))
after
malloc(initialSize * sizeof(structName)
How does one allocate memory for this and keep track of what is going on?
If your structure has a char *, it takes up the size of one pointer. If it has a char[200], it takes up two hundred bytes.
I am making some guesses here, based on the information you have provided. The only reason I can see for wanting to realloc an array of structs is if you want to add more structs to that array. That's cool. There are plenty of reasons to want that kind of dynamic storage. The best way to handle it, especially if the structures are themselves dynamic, is to keep an array of pointers to these structures. Example:
1. Data structure:
typedef struct {
int numberOfStrings;
char ** strings;
}
stringHolder;
typedef struct {
int numberOfStructs;
stringHolder ** structs;
}
structList;
2. Managing dynamic arrays of strings:
void createNewStringHolder(stringHolder ** holder) {
(*holder) = malloc(sizeof(stringHolder));
(*holder)->numberOfStrings = 0;
(*holder)->strings = NULL;
}
void destroyStringHolder(stringHolder ** holder) {
// first, free each individual string
int stringIndex;
for (stringIndex = 0; stringIndex < (*holder)->numberOfStrings; stringIndex++)
{ free((*holder)->strings[stringIndex]); }
// next, free the strings[] array
free((*holder)->strings);
// finally, free the holder itself
free((*holder));
}
void addStringToHolder(stringHolder * holder, const char * string) {
int newStringCount = holder->numberOfStrings + 1;
char ** newStrings = realloc(holder->strings, newStringCount * sizeof(char *));
if (newStrings != NULL) {
holder->numberOfStrings = newStringCount;
holder->strings = newStrings;
newStrings[newStringCount - 1] = malloc((strlen(string) + 1) * sizeof(char));
strcpy(newStrings[newStringCount - 1], string);
}
}
3. Managing a dynamic array of structures:
void createNewStructList(structList ** list, int initialSize) {
// create a new list
(*list) = malloc(sizeof(structList));
// create a new list of struct pointers
(*list)->numberOfStructs = initialSize;
(*list)->structs = malloc(initialSize * sizeof(stringHolder *));
// initialize new structs
int structIndex;
for (structIndex = 0; structIndex < initialSize; structIndex++)
{ createNewStringHolder(&((*list)->structs[structIndex])); }
}
void destroyStructList(structList ** list) {
// destroy each struct in the list
int structIndex;
for (structIndex = 0; structIndex < (*list)->numberOfStructs; structIndex++)
{ destroyStringHolder(&((*list)->structs[structIndex])); }
// destroy the list itself
free((*list));
}
stringHolder * addNewStructToList(structList * list) {
int newStructCount = list->numberOfStructs + 1;
size_t newSize = newStructCount * sizeof(stringHolder *);
stringHolder ** newList = realloc(list->structs, newSize);
if (newList != NULL) {
list->numberOfStructs = newStructCount;
list->structs = newList;
createNewStringHolder(&(newList[newStructCount - 1]));
return newList[newStructCount - 1];
}
return NULL;
}
4. Main program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char * argv[]) {
structList * allHolders;
createNewStructList(&allHolders, 10);
addStringToHolder(allHolders->structs[4], "The wind took it");
addStringToHolder(allHolders->structs[4], "Am I not merciful?");
addStringToHolder(allHolders->structs[7], "Aziz, Light!");
printf("%s\n", allHolders->structs[4]->strings[0]); // The wind took it
printf("%s\n", allHolders->structs[4]->strings[1]); // Am I not merciful?
printf("%s\n", allHolders->structs[7]->strings[0]); // Aziz, Light!
stringHolder * newHolder = addNewStructToList(allHolders);
addStringToHolder(newHolder, "You shall not pass!");
printf("%s\n", newHolder->strings[0]); // You shall not pass!
printf("%s\n", allHolders->structs[10]->strings[0]); // You shall not pass!
destroyStructList(&allHolders);
return 0;
}
You don't, generally. There are two reasons you might want to do this:
So that a single free() will release the entire block of memory.
To avoid internal memory fragmentation.
But unless you have an exceptional situation, neither are very compelling, because there is crippling drawback to this approach:
If you do this, then block[i] is meaningless. You have not allocated an array. There is no way to tell where your next struct starts without either examining the struct or having outside information about the size/position of your structs in the block.
It is not so clear how your struct type is declared. C99 has a special construct for such things, called flexible array member of a struct:
As a special case, the last element of
a structure with more than one named
member may have an incomplete array
type; this is called a flexible array
member.
You could do something like
typedef struct myString myString;
struct myString { size_t len; char c[]; };
You may then allocate such a beast with
size_t x = 35;
myString* s = malloc(sizeof(myString) + x);
s->len = x;
and reallocate it with
size_t y = 350;
{
myString* tmp = realloc(s, sizeof(myString) + y);
if (!tmp) abort(); // or whatever
tmp->len = y;
}
s = tmp;
To use this more comfortably you'd probably better wrap this into macros or inline functions.