I am trying to have dynamically allocate arrays of structures and perform operations on them but i keep running into segmentation faults. could someone help me out?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *malloc(size_t size);
typedef struct {
double x;
double y;
} coords;
struct figure {
char fig_name[128];
int coordcount, size_tracker;
coords *pointer;
} fig;
void init_fig(int n, struct figure **point)
{
printf("%u\n", sizeof(coords));
point[n]->pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n]->pointer == NULL){
exit(-1);
}
point[n]->pointer[19].x = 2;
point[n]->pointer[0].x = 1;
point[n]->pointer[0].y = 2;
point[n]->pointer[7].x = 100;
}
int main()
{
int numfigs = 1;
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
point = &fig;
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
I labelled where the first seg fault occurs, (used ddd). what i dont get is that i can manipulate point[1] in main but not in any other function.
I agree with #Maxim Skurydin.
Nevertheless I'd like to explain your mistake in some more details.
Reading your init_fig one assumes that the parameter you pass struct figure **point - is actually array of pointers to struct figure. And this function accesses its n'th element.
However in your main you do something else. You allocate an array of struct figure, and your point variable points to its head. Then you take the address of this local variable and call your init_fig.
Here's the problem. init_fig assumes that you pass it an array of pointers, whereas actually this "array" consists of a single element only: the local point variable declared in main.
EDIT:
How to do this properly.
Leave main intact, fix init_fig.
This means that actually there's an array of figure structs. Means - a single memory block, interpreted as an array of consequent structs.
void init_fig(int n, struct figure *point)
{
printf("%u\n", sizeof(coords));
point[n].pointer = malloc(sizeof(coords) * 20); <-------SEGFAULT
if (point[n].pointer == NULL){
exit(-1);
}
point[n].pointer[19].x = 2;
point[n].pointer[0].x = 1;
point[n].pointer[0].y = 2;
point[n].pointer[7].x = 100;
}
Leave init_fig intact. Fix main.
This means that we actually should allocate an array of pointers, every such a pointer should point to an allocated point structure.
int main()
{
int numfigs = 1;
struct figure ** point;
point = malloc(sizeof(struct figure*) * 16);
for (i = 0; i < 16; i++)
point[i] = malloc(sizeof(struct figure));
point[1].coordcount = 1;
init_fig(numfigs, &point);
return 0;
}
You allocate memory and store the pointer in point but then you forget that pointer when you assign &fig to it.
point = malloc(sizeof(struct figure) * 16);
point = &fig;
So, you are essentially trying to write fig[1], that does not make sense.
struct figure * point;
point = malloc(sizeof(struct figure) * 16);
here point is pointer pointing to memory of 16 structures in heap
but in the next line you have done this
point = &fig;
so its memory leak and also point is not pointing to that allocated region anymore
and also init_fig should be like this
void init_fig(int n, struct figure **point)
It's the problem of segfault
Eliminate this line point = &fig;
and modify the function:
void init_fig(int n, struct figure *point)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * 20);
...
}
since you should pass an array of structs and not an array of pointers.
Also, add a third parameter to the init_fig function so you can pass the size of the array of points that you want to create. Like :
void init_fig(int n, struct figure *point, int size)
{
...
point[n].pointer = (coords*) malloc(sizeof(coords) * size);
...
}
Therefore, making the function more reusable.
Modify also the call to that function:
init_fig(numfigs, &point); to init_fig(numfigs, point);
Related
So when I pass a data type like a struct to assign some memory to it I find that the pointer doesn't change within the main scope. This further becomes a problem when I try to free the memory but obviously if its using the original pointer it will be pointing at the stack address.
void allocate(int *value){
value = malloc(10 * sizeof(int));
}
int main(){
int val2;
allocate(&val2);
free(&val2);
return 0;
}
I can fix this by using a double pointer to be passed into the allocate function but some course work I'm doing requires to only pass a pointer and I cant get it to update the pointer when it returns to main. I have looked around for a while but cant find a straight forward answer, I feel like my coursework is wrong but that might be my lack of understanding.
The requirement to "only pass a pointer" seems contrived, and you could argue that a pointer to pointer (not a "double pointer") is a pointer, but perhaps you could use void * to punch a hole in the type system. Or use a struct:
#include <stdlib.h>
#include <stdio.h>
struct intbuffer {
int *d;
size_t cap;
};
void *
xmalloc(size_t s)
{
void *r = malloc(s);
if( r == NULL ){
perror("malloc");
exit(1);
}
return r;
}
void
allocate(void *p, size_t s)
{
*(int **)p = xmalloc(s * sizeof(int));
}
void
allocate2(struct intbuffer *p)
{
p->d = xmalloc(p->cap * sizeof *p->d);
}
int
main(void)
{
int *val2;
struct intbuffer v;
allocate(&val2, 10);
free(val2);
v.cap = 10; /* Horrible api!! */
allocate2(&v);
free(v.d);
return 0;
}
Note that setting the capacity in the struct prior to making the call to allocate is a violation of many principles of software design, but this whole thing is absurdly contrived due to the bizarre artificial limitations.
There are not enough *'s in each place, but you will have to figure out what that means.
void allocate(int** value){
*value = malloc(10 * sizeof(int));
}
int main(){
int* val2;
allocate(&val2);
free(val2);
return 0;
}
I have an issue with pointers to struct that have members that are pointers to struct too.
Browsing the suggested similar questions I found out this:
Accessing elements within a pointer of a struct inside another pointer to a struct
where people suggest to pay attention to allocation memory of the structure.
I think this is done correctly in my code.
typedef struct {
int id_vec;
float *vec_value;
} Vector;
typedef struct cluster{
int id_cluster;
float *centroid;
Vector *patternInCluster;
} Cluster;
int main(void){
Cluster *cluster_ptr= malloc(3 * sizeof(Cluster));
if (cluster_ptr==NULL){
printf("NULL");
}
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
if (cluster_ptr->patternInCluster==NULL){
printf("NULL");
cluster_ptr->patternInCluster=NULL;
}
float p1[3]={0.0f,1.0f,2.0f};
Vector *somePattern=malloc(2 * sizeof(Vector));
somePattern[0].id_vec=1;
somePattern[0].vec_value=p1;
somePattern[1].id_vec=2;
somePattern[1].vec_value=p1;
}
Then I expect that this statement works:
cluster_ptr[1].patternInCluster[1]=somePattern[1];
But it compiles and produces a Segmentation Fault.
Unexpectedly, the following statement doesn't get errors:
cluster_ptr[0].patternInCluster[1]=somePattern[1];
and a test show me correct result(somePattern[1] id and value)
I tried to debug with gdb but I only can see this:
Program received signal SIGSEGV, Segmentation fault.
0x00005555555547fe in main () at test_struct.c:36
36 cluster_ptr[1].patternInCluster[1]=somePattern[1];
Am I missing some allocation mistakes?
It's because you're not populating things fully.
This line
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
is the same as saying
cluster_ptr[0].patternInCluster=malloc(2 * sizeof(Vector *));
and really given that cluster_ptr has been allocated as 3 Cluster it would be more clearer in your code to do the latter.
Since cluster_ptr[1].patternInCluster hasn't been given a value, trying to dereference it will lead to undefined behaviour but more likely will result in a segmentation fault.
You do not allocate enough memory:
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector *));
With patternInCluster being of type Vector *, you should allocate memory to hold elements of type Vector, not Vector*.
cluster_ptr->patternInCluster=malloc(2 * sizeof(Vector));
Your problem is NOT accessing the pointer inside the struct. Your problem is how you are using malloc().
When you have one pointer, you malloc only once:
int *pointer = (int* )malloc(sizeof(int));
*pointer = 1;
printf("*pointer:%d\n", *pointer);
When you have pointer-to-pointer, you malloc() once for the **pointer_to_pointer, but you also have to malloc() once for the *pointer_to_pointer:
int** pointer_to_pointer = (int** )malloc(sizeof(int*));
*pointer_to_pointer = (int* )malloc(sizeof(int));
**pointer_to_pointer = 2;
printf("**pointer:%d\n", **pointer_to_pointer);
And if you have more than one pointer, at the location pointed to by **pointer_to_pointer, you need a for loop to assign memory to every one of those *pointer_to_pointers.
for (unsigned int i = 0; i < 3; i++)
{
*(pointer_to_pointer + i*sizeof(int)) = (int* )malloc(sizeof(int));
}
**(pointer_to_pointer + sizeof(int)) = 3;
**(pointer_to_pointer + 2UL*sizeof(int)) = 4;
printf("**(pointer_to_pointer + sizeof(int):%d\n", **(pointer_to_pointer + sizeof(int)));
printf("**(pointer_to_pointer + 2UL*sizeof(int):%d\n", **(pointer_to_pointer + 2UL*sizeof(int)));
You are mistaken to think that Cluster *cluster_ptr= malloc(3 * sizeof(Cluster)); will automatically/magically assign memory for Cluster[0] and Cluster[1] and Cluster[2].
Your statement actually assigns memory only for Cluster[0], but big enough for 3 Clusters.
So the the modified code will look like this:
#include <string.h>
#include <stdio.h>
#include <malloc.h>
typedef struct {
int id_vec;
float *vec_value;
} Vector;
typedef struct cluster{
int id_cluster;
float *centroid;
Vector **patternInCluster;
} Cluster;
int main(void){
Cluster **cluster_ptr = (Cluster **)malloc(sizeof(Cluster*));
for (long unsigned int i = 0; i < 3; i++) {
cluster_ptr[i] = (Cluster *)malloc(sizeof(Cluster));
if (cluster_ptr[i]==NULL){
printf("NULL");
}
cluster_ptr[i]->patternInCluster = (Vector **) malloc(sizeof(Vector*));
for (long unsigned int j = 0; j < 3; j++) {
(*cluster_ptr)->patternInCluster[j] = (Vector *) malloc(sizeof(Vector));
if ((*cluster_ptr)->patternInCluster[j]==NULL){
printf("NULL");
(*cluster_ptr)->patternInCluster[j]=NULL;
}
}
}
float p1[3]={0.0f,1.0f,2.0f};
Vector *somePattern= (Vector *) malloc(sizeof(Vector));
somePattern[0].id_vec=1;
somePattern[0].vec_value=p1;
somePattern[1].id_vec=2;
somePattern[1].vec_value=p1;
cluster_ptr[1]->patternInCluster[1] = &somePattern[0];
cluster_ptr[0]->patternInCluster[1] = &somePattern[1];
cluster_ptr[1]->patternInCluster[0] = &somePattern[1];
cluster_ptr[2]->patternInCluster[1] = &somePattern[0];
printf("%d\n", cluster_ptr[1]->patternInCluster[1]->id_vec);
printf("%d\n", cluster_ptr[0]->patternInCluster[1]->id_vec);
printf("%d\n", cluster_ptr[1]->patternInCluster[0]->id_vec);
printf("%d\n", cluster_ptr[2]->patternInCluster[1]->id_vec);
return 0;
}
On my system, I just compiled and it builds and runs error-free.
I have a struct called menu_item that looks like:
struct menu_item
{
char name[ITEM_NAME_LEN+1];
};
And in main I declare an array of pointers to the struct (am I right about this part?):
struct menu_item * menu_items[NUM_MENU_ITEMS];
And also in main I'm trying to call:
init_menu(&menu_items[NUM_MENU_ITEMS]);
init_menu function looks like this:
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
However I'm getting a segmentation error, what am I doing wrong? Thanks in advance.
Take a closer look to your function.
void menu_init(struct menu_item * menu_items[NUM_MENU_ITEMS])
{
/* allocate memory for each element in the array */
menu_items[NUM_MENU_ITEMS] = (struct menu_item *) malloc(sizeof(struct menu_item));
}
You need to carry the size of the array in a second parameter in your function. However, NUM_MENU_ITEMS, seems to be a global #define, thus you don't need to carry a second parameter.
Then you are accessing an out of bound cell, menu_items[NUM_MENU_ITEMS]. I assume you know that the indexing starts from 0 and ends at NUM_MENU_ITEMS-1.
In your function, you need, inside a loop, to allocate memory. Moreover, you don't need to cast what malloc returns.
So, for example, you could do something like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ITEM_NAME_LEN 15
#define NUM_MENU_ITEMS 3
// Define the struct before main
struct menu_item {
char name[ITEM_NAME_LEN + 1];
};
// Give a synonym. Now struct menu_item is the same with menu_item_t.
// Notice the _t extension, which implies that this is a typedef.
typedef struct menu_item menu_item_t;
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), allocate memory for
* every cell of the array.
*/
void init_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// for every cell of our array, allocate memory
p[i] = malloc(sizeof(menu_item_t));
// check that allocation for the i-th cell is OK
if(!p[i]) {
printf("Error in allocating %d item!\n\n", i);
return;
}
}
}
/**
* Given a pointer 'p' to an array of pointers
* (of type menu_item_t), de-allocate memory for
* every cell of the array.
*/
void delete_menu(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
// free the memory we had allocated for the i-th cell
free(p[i]);
// set the pointer to NULL
p[i] = NULL;
}
}
void fill(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
strcpy(p[i]->name, "myitem");
}
}
void print(menu_item_t* p[]) {
int i;
for(i = 0; i < NUM_MENU_ITEMS; ++i) {
printf("%s\n", p[i]->name);
}
}
int main(void) {
// Declare an array of pointers of menu_items_t.
// The size of the array is NUM_MENU_ITEMS
menu_item_t *menu_items[NUM_MENU_ITEMS];
init_menu(menu_items);
fill(menu_items);
print(menu_items);
delete_menu(menu_items);
return 0;
}
When I deal with structs, I always have this example on mind.
You are calling your function as
init_menu(&menu_items[NUM_MENU_ITEMS]);
This does not make sense. Expression &menu_items[NUM_MENU_ITEMS] creates a pointer to element with index NUM_MENU_ITEMS. Such element does not exist. Your array has elements numbered from 0 to NUM_MENU_ITEMS - 1. There's no element with index NUM_MENU_ITEMS.
Expression &menu_items[NUM_MENU_ITEMS] produces a pointer into the uncharted memory past the end of the array. You pass that pointer to the function. Later you are trying to use that pointer as if it were your array. You write into that uncharted memory, which causes a crash.
If you want to pass your array to the function, just pass it. Your function should be called as
init_menu(menu_items);
That's it. There's no need to create any pointers to any elements with strange indices.
Later, inside your function you are again trying to access element NUM_MENU_ITEMS of your array
menu_items[NUM_MENU_ITEMS] = ...
This does not make sense either for the very same reasons.
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.
I am struggling really hard to understand this behavior so maybe someone can shed some light on the situation.
I simply can't figure out why I can't return a pointer to a struct from a method and expect to be able to still re-use it afterwards.
As you can see the generateSmallMatrix() method creates an int[] array and sets it inside the ysmf struct that I then return to main. Main then takes the ysmf* and calls printArray (again). And on the third try the array cannot be retrieved any more..
It's driving me crazy..
I have checked with my Eclipse debugger that on all calls the location of matrix->A is identical (0x7fffffffe180 - so for all I know about C pointers any form of accessing that int should return the correct value - be it *(ax++) or ax[i]) .. but neither do..
Very frustrating to say the least, so here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct sparseMatrix
{
int* A;
} ysmf;
void printArray(int* ax, int length) {
int i = 0;
for (i = 0; i < length; i++) {
printf("%i,", ax[i]);
}
printf("\n");
}
ysmf* generateSmallMatrix()
{
ysmf *matrix = malloc(sizeof(ysmf));
int a[] = {1,2,3,9,1,4};
printArray(a, 6); // returns 1,2,3,9,1,4,
matrix->A = a;
printArray(matrix->A, 6); //returns 1,2,3,9,1,4,
//printArray(matrix->A, 6);
return matrix;
}
int main(void) {
ysmf* matrix = generateSmallMatrix();
printArray(matrix->A, 6); //returns 1,6,-7856,32767,1,4,
return EXIT_SUCCESS;
}
You can see the problem occuring where I have inserted the comments.
I know this is probably something totally basic I shouldn't have missed..
Because a is a local array, whose lifetime ends when the generateSmallMatrix() function ends. Accessing it after that results in undefined behaviour.
This line
ysmf *matrix = malloc(sizeof(ysmf));
Allocates only enough space for your ysmf struct, which in this case, is just an int pointer. So you then go and point that at 'a'.
matrix->A = a;
The problem is that a is on the stack. So it is now pointing at this memory address but when you exit the function that memory is no longer reserved for the array.
If you instead malloced memory for 'a' and pointed your struct at that, then you would be OK.
Try this...
ysmf* generateSmallMatrix()
{
ysmf *matrix = malloc(sizeof(ysmf));
int a[] = {1,2,3,9,1,4};
printArray(a, 6);
matrix->A = malloc(sizeof(int) * 6);
memcpy(matrix->A, a, sizeof(int) * 6);
printArray(matrix->A, 6);
return matrix;
}
Now outside of the generateSmallMatrix function you should be able to print the correct values. However, be sure to free what was malloc'd.
int main(void) {
ysmf* matrix = generateSmallMatrix();
printArray(matrix->A, 6);
free(matrix->A);
free(matrix);
return EXIT_SUCCESS;
}
Hope this helps.