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's my logic:
This is some text:
char *text;
Then this is array of texts:
char **arr;
Then array of these arrays is:
char ***arr2d;
And if I want a function to modify it, it needs to accept it as:
char ****arr2d;
And within the function use it as:
*arr2d = (e.g. allocate);
So if I want to create 2D array like this and make the first row, first column contain just a letter 'a', then why does this not work?
#define COLUMNS 7
void loadTable(char ****table)
{
*table = (char ***) malloc(sizeof(char**));
if (!*table) {
printf("Allocation error for table rows.");
return;
}
*table[0] = (char**) malloc(COLUMNS * sizeof(char*));
if (!*table[0]) {
printf("Allocation error for table columns.");
return;
}
*table[0][0] = (char*) malloc(2 * sizeof(char));
*table[0][0][0] = (char)(97);
*table[0][0][1] = '\0';
}
int main()
{
char ***table;
loadTable(&table);
return 0;
}
You would need only 3 *** to do what you describe, not 4 ****. Be aware, there are methods to allow you to avoid excessive depth in terms of arrays of arrays of strings. And there are also good reasons to avoid excessively deep orders of arrays, not the least is the need to free(.) everything you allocate. That means exactly one call to free(.) for each and every call to [m][c][re]alloc(.).
But to address your question...
In general, to create new memory for a single array of a previously allocated memory, you could use a function prototyped as:
char * ReSizeBuffer(char **str, size_t origSize);
Where if say the previously allocated buffer were created as:
char *buf = calloc(origSize, 1);
...the usage could look like:
char *tmp = {0};
tmp = ReSizeBuffer(&buf, newSize); //see implementation below
if(!tmp)
{
free(buf);
return NULL;
}
buf = tmp;
///use new buf
...
Then if this works for a single array of char, then the prototype for allocating new memory for a previously allocated array of strings might look like this:
char ** ReSizeBuffer(char ***str, size_t numArrays, size_t strLens);
Where if say the previously allocated 2D buffer were created as:
char **buf = Create2DStr(size_t numStrings, size_t maxStrLen); //see implementation below
...the usage could look like:
char **tmp = {0};
tmp = ReSizeBuffer(&buf, numStrings, maxStrLen);
if(!tmp)
{
free(buf);
return NULL;
}
buf = tmp;
///use new buf
...
Implementations:
Implementation of ReSizeBuffer. This must be expanded if you desire to implement the second prototype:
char * ReSizeBuffer(char **str, size_t size)
{
char *tmp={0};
if(!(*str)) return NULL;
if(size == 0)
{
free(*str);
return NULL;
}
tmp = (char *)realloc((char *)(*str), size);
if(!tmp)
{
free(*str);
return NULL;
}
*str = tmp;
return *str;
}
Implementation of Create2DStr might look like this:
char ** Create2DStr(size_t numStrings, size_t maxStrLen)
{
int i;
char **a = {0};
a = calloc(numStrings, sizeof(char *));
for(i=0;i<numStrings; i++)
{
a[i] = calloc(maxStrLen + 1, 1);
}
return a;
}
I just stumbled upon this old question of mine and spotted the problem immediately. Here is the answer:
The number of asterisks is actually correct, the problem is operator evaluation. Specifically, all lines of code of this form:
*table[0]
should have been written as:
(*table)[0]
usually a basic question, but maybe I am just too stupid. I try to pass an char * as output trought the parameter of a function. Inside the function I create a temporary char * which I want to memcpy to the address I've passed. Here is the code:
#define BLOCKSIZE=1024
int myFunction(char *s, char **out) {
int i = strlen(s);
*out = (char *)malloc(BLOCKSIZE);
char tmp[BLOCKSIZE];
strcpy(tmp, s);
tmp[++i] = 0x0f;
for(int i=strlen(s);i < BLOCKSIZE; i++) {
tmp[i] = 0xcc;
}
memcpy(*out, tmp, BLOCKSIZE);
return 0;
}
int main() {
char *s = "Hello World";
char *o = (char *)malloc(BLOCKSIZE);
myFunction(s, &o);
}
The problem is, the stack gets corrupted after it jumps out of the function myFunction..
Is there another way to do it?
Thank you in advance!
Best,
Update: Problem solved
The for loop part i < BLOCKSIZE must be changed to i < (BLOCKSIZE - 1).
Your first problem is that you malloc twice, before and in the function. The malloc outside the call (second line of main) is leaked.
The second problem (and this tells me you didn't even compile the code) is that you use i before defining it.
I'm trying to implement generic stack in C, but I can't print value that I pushed. Here is the code
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <memory.h>
typedef struct{
void *elems;
int sizeOfElems;
int allocated;
int lenght;
}stack;
void allocate_stack(stack *s, int sizeOfElements){
assert(sizeOfElements > 0);
s->sizeOfElems = sizeOfElements;
s->allocated = 2;
s->lenght = 2;
s->elems = malloc(sizeOfElements * s->allocated);
}
void deallocate_stack(stack *s){
free(s->elems);
}
void push_elem(stack *s, void *elem){
s->lenght += 1;
if(s->allocated == s->lenght){
realloc(s, s->lenght * s->sizeOfElems);
s->lenght *= 2;
}
void *target = (char *)s->elems + s->lenght * s->sizeOfElems;
memcpy(target, elem, s->sizeOfElems);
}
void pop_elem(stack *s, void *elemAddr){
void *source = (char *)s->elems + (s->lenght-1) * s->sizeOfElems;
memcpy(elemAddr, source, s->sizeOfElems);
s->lenght -=1;
}
int main(){
stack s;
allocate_stack(&s, 1);
char a = 'a';
push_elem(&s, &a);
char *elem = NULL;
pop_elem(&s, elem);
printf("%s", elem);
deallocate_stack(&s);
return 0;
}
The problem is that I don't get anything when I run the program, just press return to close the window. I'm programming on Linux using GCC toolkit.
You are missing the allocation of your stack struct. When you do allocate_stack you must call allocate to create a stack object before assigning things to it. For instance the s you pass in is null and you start trying to assign values to the various fields of it. This is undefined behavior and likely the reason your program isn't working.
Try changing the signature of your allocate_stack function to return a stack pointer and then the first step should be to malloc(sizeof struct stack) . You should return the pointer you got from the malloc at the and and assign it to s.
Edit: unless you want the stack to be on the stack in which case allocate it like you would a normal variable.
In your push_elem:
s->lenght += 1;
if(s->allocated == s->lenght){
realloc(s, s->lenght * s->sizeOfElems);
s->lenght *= 2;
}
It seems like you are trying to re-allocate space if you run out, but your default value of 2 for allocated is going to stay as it is, you should probably do something like:
if (s->allocated < s->lenght) {
realloc(s->elems, ....)
//Increase both allocated and length to represent the current state of the stack
}
Notice that in the realloc() call you are passing s, which is in the stack, this won't do what you want:
http://pubs.opengroup.org/onlinepubs/7908799/xsh/realloc.html
As per your structure you should be passing
s->elems
Also, before calling pop_elem, you are assigning NULL to elem. Inside your pop_elem, this is where you are trying to do a memcpy() to. To do this you will have to allocate memory:http://pubs.opengroup.org/onlinepubs/009695399/functions/memcpy.html
I know how to create an array of structs but with a predefined size. However is there a way to create a dynamic array of structs such that the array could get bigger?
For example:
typedef struct
{
char *str;
} words;
main()
{
words x[100]; // I do not want to use this, I want to dynamic increase the size of the array as data comes in.
}
Is this possible?
I've researched this: words* array = (words*)malloc(sizeof(words) * 100);
I want to get rid of the 100 and store the data as it comes in. Thus if 76 fields of data comes in, I want to store 76 and not 100. I'm assuming that I don't know how much data is coming into my program. In the struct I defined above I could create the first "index" as:
words* array = (words*)malloc(sizeof(words));
However I want to dynamically add elements to the array after. I hope I described the problem area clearly enough. The major challenge is to dynamically add a second field, at least that is the challenge for the moment.
I've made a little progress however:
typedef struct {
char *str;
} words;
// Allocate first string.
words x = (words) malloc(sizeof(words));
x[0].str = "john";
// Allocate second string.
x=(words*) realloc(x, sizeof(words));
x[1].FirstName = "bob";
// printf second string.
printf("%s", x[1].str); --> This is working, it's printing out bob.
free(x); // Free up memory.
printf("%s", x[1].str); --> Not working since its still printing out BOB even though I freed up memory. What is wrong?
I did some error checking and this is what I found. If after I free up memory for x I add the following:
x=NULL;
then if I try to print x I get an error which is what I want. So is it that the free function is not working, at least on my compiler? I'm using DevC??
Thanks, I understand now due to:
FirstName is a pointer to an array of char which is not being allocated by the malloc, only the pointer is being allocated and after you call free, it doesn't erase the memory, it just marks it as available on the heap to be over written later. – MattSmith
Update
I'm trying to modularize and put the creation of my array of structs in a function but nothing seems to work. I'm trying something very simple and I don't know what else to do. It's along the same lines as before, just another function, loaddata that is loading the data and outside the method I need to do some printing. How can I make it work? My code is as follows:
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
typedef struct
{
char *str1;
char *str2;
} words;
void LoadData(words *, int *);
main()
{
words *x;
int num;
LoadData(&x, &num);
printf("%s %s", x[0].str1, x[0].str2);
printf("%s %s", x[1].str1, x[1].str2);
getch();
}//
void LoadData(words *x, int * num)
{
x = (words*) malloc(sizeof(words));
x[0].str1 = "johnnie\0";
x[0].str2 = "krapson\0";
x = (words*) realloc(x, sizeof(words)*2);
x[1].str1 = "bob\0";
x[1].str2 = "marley\0";
*num=*num+1;
}//
This simple test code is crashing and I have no idea why. Where is the bug?
You've tagged this as C++ as well as C.
If you're using C++ things are a lot easier. The standard template library has a template called vector which allows you to dynamically build up a list of objects.
#include <stdio.h>
#include <vector>
typedef std::vector<char*> words;
int main(int argc, char** argv) {
words myWords;
myWords.push_back("Hello");
myWords.push_back("World");
words::iterator iter;
for (iter = myWords.begin(); iter != myWords.end(); ++iter) {
printf("%s ", *iter);
}
return 0;
}
If you're using C things are a lot harder, yes malloc, realloc and free are the tools to help you. You might want to consider using a linked list data structure instead. These are generally easier to grow but don't facilitate random access as easily.
#include <stdio.h>
#include <stdlib.h>
typedef struct s_words {
char* str;
struct s_words* next;
} words;
words* create_words(char* word) {
words* newWords = malloc(sizeof(words));
if (NULL != newWords){
newWords->str = word;
newWords->next = NULL;
}
return newWords;
}
void delete_words(words* oldWords) {
if (NULL != oldWords->next) {
delete_words(oldWords->next);
}
free(oldWords);
}
words* add_word(words* wordList, char* word) {
words* newWords = create_words(word);
if (NULL != newWords) {
newWords->next = wordList;
}
return newWords;
}
int main(int argc, char** argv) {
words* myWords = create_words("Hello");
myWords = add_word(myWords, "World");
words* iter;
for (iter = myWords; NULL != iter; iter = iter->next) {
printf("%s ", iter->str);
}
delete_words(myWords);
return 0;
}
Yikes, sorry for the worlds longest answer. So WRT to the "don't want to use a linked list comment":
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char** words;
size_t nWords;
size_t size;
size_t block_size;
} word_list;
word_list* create_word_list(size_t block_size) {
word_list* pWordList = malloc(sizeof(word_list));
if (NULL != pWordList) {
pWordList->nWords = 0;
pWordList->size = block_size;
pWordList->block_size = block_size;
pWordList->words = malloc(sizeof(char*)*block_size);
if (NULL == pWordList->words) {
free(pWordList);
return NULL;
}
}
return pWordList;
}
void delete_word_list(word_list* pWordList) {
free(pWordList->words);
free(pWordList);
}
int add_word_to_word_list(word_list* pWordList, char* word) {
size_t nWords = pWordList->nWords;
if (nWords >= pWordList->size) {
size_t newSize = pWordList->size + pWordList->block_size;
void* newWords = realloc(pWordList->words, sizeof(char*)*newSize);
if (NULL == newWords) {
return 0;
} else {
pWordList->size = newSize;
pWordList->words = (char**)newWords;
}
}
pWordList->words[nWords] = word;
++pWordList->nWords;
return 1;
}
char** word_list_start(word_list* pWordList) {
return pWordList->words;
}
char** word_list_end(word_list* pWordList) {
return &pWordList->words[pWordList->nWords];
}
int main(int argc, char** argv) {
word_list* myWords = create_word_list(2);
add_word_to_word_list(myWords, "Hello");
add_word_to_word_list(myWords, "World");
add_word_to_word_list(myWords, "Goodbye");
char** iter;
for (iter = word_list_start(myWords); iter != word_list_end(myWords); ++iter) {
printf("%s ", *iter);
}
delete_word_list(myWords);
return 0;
}
If you want to dynamically allocate arrays, you can use malloc from stdlib.h.
If you want to allocate an array of 100 elements using your words struct, try the following:
words* array = (words*)malloc(sizeof(words) * 100);
The size of the memory that you want to allocate is passed into malloc and then it will return a pointer of type void (void*). In most cases you'll probably want to cast it to the pointer type you desire, which in this case is words*.
The sizeof keyword is used here to find out the size of the words struct, then that size is multiplied by the number of elements you want to allocate.
Once you are done, be sure to use free() to free up the heap memory you used in order to prevent memory leaks:
free(array);
If you want to change the size of the allocated array, you can try to use realloc as others have mentioned, but keep in mind that if you do many reallocs you may end up fragmenting the memory. If you want to dynamically resize the array in order to keep a low memory footprint for your program, it may be better to not do too many reallocs.
This looks like an academic exercise which unfortunately makes it harder since you can't use C++. Basically you have to manage some of the overhead for the allocation and keep track how much memory has been allocated if you need to resize it later. This is where the C++ standard library shines.
For your example, the following code allocates the memory and later resizes it:
// initial size
int count = 100;
words *testWords = (words*) malloc(count * sizeof(words));
// resize the array
count = 76;
testWords = (words*) realloc(testWords, count* sizeof(words));
Keep in mind, in your example you are just allocating a pointer to a char and you still need to allocate the string itself and more importantly to free it at the end. So this code allocates 100 pointers to char and then resizes it to 76, but does not allocate the strings themselves.
I have a suspicion that you actually want to allocate the number of characters in a string which is very similar to the above, but change word to char.
EDIT: Also keep in mind it makes a lot of sense to create functions to perform common tasks and enforce consistency so you don't copy code everywhere. For example, you might have a) allocate the struct, b) assign values to the struct, and c) free the struct. So you might have:
// Allocate a words struct
words* CreateWords(int size);
// Assign a value
void AssignWord(word* dest, char* str);
// Clear a words structs (and possibly internal storage)
void FreeWords(words* w);
EDIT: As far as resizing the structs, it is identical to resizing the char array. However the difference is if you make the struct array bigger, you should probably initialize the new array items to NULL. Likewise, if you make the struct array smaller, you need to cleanup before removing the items -- that is free items that have been allocated (and only the allocated items) before you resize the struct array. This is the primary reason I suggested creating helper functions to help manage this.
// Resize words (must know original and new size if shrinking
// if you need to free internal storage first)
void ResizeWords(words* w, size_t oldsize, size_t newsize);
In C++, use a vector. It's like an array but you can easily add and remove elements and it will take care of allocating and deallocating memory for you.
I know the title of the question says C, but you tagged your question with C and C++...
Another option for you is a linked list. You'll need to analyze how your program will use the data structure, if you don't need random access it could be faster than reallocating.
Your code in the last update should not compile, much less run. You're passing &x to LoadData. &x has the type of **words, but LoadData expects words* . Of course it crashes when you call realloc on a pointer that's pointing into stack.
The way to fix it is to change LoadData to accept words** . Thi sway, you can actually modify the pointer in main(). For example, realloc call would look like
*x = (words*) realloc(*x, sizeof(words)*2);
It's the same principlae as in "num" being int* rather than int.
Besides this, you need to really figure out how the strings in words ere stored. Assigning a const string to char * (as in str2 = "marley\0") is permitted, but it's rarely the right solution, even in C.
Another point: non need to have "marley\0" unless you really need two 0s at the end of string. Compiler adds 0 tho the end of every string literal.
For the test code: if you want to modify a pointer in a function, you should pass a "pointer to pointer" to the function. Corrected code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct
{
char *str1;
char *str2;
} words;
void LoadData(words**, int*);
main()
{
words **x;
int num;
LoadData(x, &num);
printf("%s %s\n", (*x[0]).str1, (*x[0]).str2);
printf("%s %s\n", (*x[1]).str1, (*x[1]).str2);
}
void LoadData(words **x, int *num)
{
*x = (words*) malloc(sizeof(words));
(*x[0]).str1 = "johnnie\0";
(*x[0]).str2 = "krapson\0";
*x = (words*) realloc(*x, sizeof(words) * 2);
(*x[1]).str1 = "bob\0";
(*x[1]).str2 = "marley\0";
*num = *num + 1;
}
Every coder need to simplify their code to make it easily understood....even for beginners.
So array of structures using dynamically is easy, if you understand the concepts.
// Dynamically sized array of structures
#include <stdio.h>
#include <stdlib.h>
struct book
{
char name[20];
int p;
}; //Declaring book structure
int main ()
{
int n, i;
struct book *b; // Initializing pointer to a structure
scanf ("%d\n", &n);
b = (struct book *) calloc (n, sizeof (struct book)); //Creating memory for array of structures dynamically
for (i = 0; i < n; i++)
{
scanf ("%s %d\n", (b + i)->name, &(b + i)->p); //Getting values for array of structures (no error check)
}
for (i = 0; i < n; i++)
{
printf ("%s %d\t", (b + i)->name, (b + i)->p); //Printing values in array of structures
}
scanf ("%d\n", &n); //Get array size to re-allocate
b = (struct book *) realloc (b, n * sizeof (struct book)); //change the size of an array using realloc function
printf ("\n");
for (i = 0; i < n; i++)
{
printf ("%s %d\t", (b + i)->name, (b + i)->p); //Printing values in array of structures
}
return 0;
}
If you want to grow the array dynamically, you should use malloc() to dynamically allocate some fixed amount of memory, and then use realloc() whenever you run out. A common technique is to use an exponential growth function such that you allocate some small fixed amount and then make the array grow by duplicating the allocated amount.
Some example code would be:
size = 64; i = 0;
x = malloc(sizeof(words)*size); /* enough space for 64 words */
while (read_words()) {
if (++i > size) {
size *= 2;
x = realloc(sizeof(words) * size);
}
}
/* done with x */
free(x);
Here is how I would do it in C++
size_t size = 500;
char* dynamicAllocatedString = new char[ size ];
Use same principal for any struct or c++ class.