This is in my main.c
int main(){
int size = 5;
Path Solution;
PathInit(&Solution,size);
printf("Size: %d\n",Solution.size);
printf("top: %d", Solution.top);
}
This is in my path.h
typedef struct{
int size;
int top;
int *item;
}Path;
This is in my path.c
void PathInit(Path *P, int vsize){
P = (Path *)malloc(sizeof(Path));
P->size = vsize;
P->item = (int *)malloc(sizeof(int)*vsize);
P->top = -1;
}
The expected output is
Size: 5
top: -1
However the output is something along the lines of
Size: 3412832
top: 0
Can someone explain why my struct is not initializing properly. Also this isn't my full code but ive narrowed the problem down to these sections. Any help would be great. Thanks
You are using the stack:
Path Solution;
and passing a pointer:
PathInit(&Solution,size);
so you don't need to reserve space with malloc:
void PathInit(Path *P, int vsize){
P = (Path *)malloc(sizeof(Path)); /* Remove this line */
As mentioned in the answer of #Alter Mann's, the issue is that you mess up with the stack storage, which is undefined behaviour. In case you want to use dynamic allocation, you need to pass a pointer to pointer (and btw there is no need to cast the result of malloc in C), so you can modify it in your function, like:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int size;
int top;
int *item;
} Path;
void PathInit(Path **P, int vsize) { // pass pointer to pointer so we can modify it
*P = malloc(sizeof(Path)); // No need (and not recommended) to cast malloc in C
(*P)->size = vsize;
(*P)->item = malloc(sizeof(int) * vsize);
(*P)->top = -1;
}
int main() {
int size = 5;
Path* Solution; // this is now a pointer
PathInit(&Solution, size);
printf("Size: %d\n", Solution->size);
printf("top: %d", Solution->top);
free(Solution->item);
free(Solution);
}
Otherwise you need to return the pointer from your function:
Path* PathInit(int vsize) {
Path* tmp = malloc(sizeof(Path));
tmp->size = vsize;
tmp->item = malloc(sizeof(int) * vsize);
tmp->top = -1;
return tmp;
}
and call it like
Path* Solution;
Solution = PathInit(size);
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 am fairly new to c and struggling to properly use the C stdlib qsort() function.
This is relevant to education and as such i am only allowed to use C99 and standard libraries if this is important.
I have a list of items taken from a HashTable and put into a HashItem **array but then when sorting this i am struggling with the compare function, i cannot get the correct value out of the struct. I have looked around and seen a few solutions but they all seem to lead to a
[Error] dereferencing pointer to incomplete type
Here is the struct :
typedef struct {
char *word;
int occurences;
} HashItem;
And i am interested in comparing and sorting by the occurences value.
Here is the bit of code which calls the qsort:
int n = array->number_of_values;
HashItem **standard_array = array_getarray(array);
qsort(standard_array, n, sizeof(HashItem*), compare_func);
Here is the compare function:
int compare_func(const void *a, const void *b){
const struct HashItem* aa = (HashItem*)a;
const struct HashItem* bb = (HashItem*)b;
int val_1 = aa->occurencies;
int val_2 = bb->occurencies;
if(val_1 == val_2){
return 0;
}else if(val_1 > val_2){
return 1;
}else{
return -1;
}
}
Sorry for the formatting, i am new to asking questions here.
I hope you can help thankyou.
Array code :
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
/*Method to create a new dynamic array and return it */
DynArray* array_new(int file_size){
DynArray *array = malloc(sizeof(DynArray));
array->number_of_values = 0;
array->capacity = file_size / 10;
printf("capacity is %d " , array->capacity);
array->items = malloc(sizeof(HashItem*)* array->capacity);
}
/*Method used to increase the size of the array and reallocate memory*/
void array_increase_if_full(DynArray *array){
if (array->number_of_values >= array->capacity){
array->capacity *= 1.25;
array->items = realloc(array->items, sizeof(HashItem)*array->capacity);
}
}
/*Method to add a string to the dynamic array specified */
void array_append(DynArray *array, HashItem *item){
array_increase_if_full(array);
array->items[array->number_of_values] = item;
//printf("item %s added \n at position %d ", array->items[array->number_of_values]->word, array->number_of_values);
array->number_of_values++;
}
/*Method used to get value at specified position for given array*/
HashItem *array_get(DynArray *array, int position){
if(position >= array->number_of_values || position <0){
printf("Index specified out of range");
exit(1);
}
//printf("item %s at position %d retrieved", array->items[position]->word, position);
return array->items[position];
}
HashItem **array_getarray(DynArray *array){
HashItem **toreturn[array->number_of_values];
int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
Printing the array from the main gives the correct unsorted values of word:occurences
Edit:
Thanks to everyone that took their time to help, it is now in a working state with Michaels suggestion, i no longer use the array_getarray() method and instead use:
int n = array->number_of_values;
int i;
HashItem **standard_array = malloc(n*sizeof(HashItem*));
for(i = 0; i < n; i++){
standard_array[i] = array_get(array, i);
printf("%s : %d \n" , standard_array[i]->word, standard_array[i]->occurences);
}
You structure declaration:
typedef struct {
char *word;
int occurences;
} HashItem;
declares a typedef name for an anonymous struct. There is a HashItem type that's a structure, but there is no struct HashItem type.
So when your compare_func() has the following declarations:
const struct HashItem* aa = (HashItem*)a;
const struct HashItem* bb = (HashItem*)b;
those struct HashItem* variables are pointers to a forward declared struct HashItem that has nothign to do with the HashItem strucuture above.
Just change those variable declarations to:
const HashItem* aa = (HashItem*)a;
const HashItem* bb = (HashItem*)b;
and/or change the declaration of the structure to:
typedef struct HashItem {
char *word;
int occurences;
} HashItem;
However, there's another issue (as mentioned in other answers): you are apparently sorting an array of pointers to HashItem objects, but your compare_function() is being written as if you're sorting an array of the objects (not pointers).
To address this:
int compare_func(const void *a, const void *b)
{
// get HashItem*'s from the HashItem**'s
const HashItem* aa = *((HashItem**)a);
const HashItem* bb = *((HashItem**)b);
int val_1 = aa->occurencies;
int val_2 = bb->occurencies;
if (val_1 == val_2) {
return 0;
} else if (val_1 > val_2) {
return 1;
} else {
return -1;
}
}
Finally (for now anyway), this function is returning the address to a local array, so the data it points to is no longer valid:
HashItem **array_getarray(DynArray *array){
HashItem **toreturn[array->number_of_values];
int i;
for(i = 0; i < array->number_of_values; i++){
toreturn[i] = array_get(array, i);
}
return toreturn;
}
I think you'll need to allocate the array you're retuning using malloc() or calloc() or something. But what I really think you need to do is step back and create some drawing of your data structures and think about the lifetime of the various objects contained in them and how those lifetimes can be tracked an managed so that you don't have leaks, double frees, or pointer dereferences to no longer valid objects.
Change qsort(standard_array, n, sizeof(HashItem), compare_func); to
qsort(standard_array, n, sizeof(HashItem*), compare_func);
In function void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
the third parameter size_t size stands for:
Size in bytes of each element in the array.
It now looks to me like your problems are all springing from the first definition.
/*DynArray is a dynamically resizing array that is used to hold values and retain size data throughout*/
typedef struct{
int number_of_values;
int capacity;
HashItem **items;
}DynArray;
I see no reason for items to be a double-pointer. The comment says it should contain values, but a double-pointer pointing to an array would contain pointers, not the ultimate values. I think this initial misstep is causing you to trip everywhere else. Change it to
...
HashItem *items;
...
and the rest should flow more naturally.
i want to build a structure which can hold simple datatypes like integers or arrays of that structure.
the structure looks like that:
typedef struct data_s {
size_t size; // size of memory data is pointing to
void * data; // pointer to data (array of data_t or simple type)
} data_t;
i have simplified it, normally there are more informations stored in the structure.
i wrote functions to set and get integer values, they work!
now i tried to write functions for creating an array and seting and getting the values, they don't work.
i used gdb to find where it fails. it shows me that my dereferencing doesnt work as i expect. i use following:
((data_t**)(data->data))[i]
and there i got a access violation.
i t would be great if somebody could show me my mistake. here is a working codeexample, i have minimized the code, that you dont have the overhead of my programm (also errorhandling is removed).
the code compiles without any error using gcc -g main.c -o test with gcc 4.8.1 on xubuntu 13.10 with 3.11 kernel
#include <stdio.h>
#include <stdlib.h>
typedef struct data_s {
size_t size;
void * data;
} data_t;
void set_integer(data_t *data, int value){
data->size = sizeof(int);
data->data = malloc(data->size);
*((int*)(data->data)) = value;
}
void get_integer(data_t *data, int *value){
(*value) = *((int*)(data->data));
}
void create_array(data_t *data, size_t len){
data->size = sizeof(data_t) * len;
data->data = malloc(data->size);
int i;
for(i=0; i<data->size; i++){ //initialize array
((data_t**)(data->data))[i]->data = NULL;
((data_t**)(data->data))[i]->size = 0;
}
}
void set_array(data_t *data, int index, data_t *value){
((data_t**)(data->data))[index]->data = value->data;
((data_t**)(data->data))[index]->size = value->size;
}
void get_array(data_t *data, int index, data_t *value){
value->data = ((data_t**)(data->data))[index]->data;
value->size = ((data_t**)(data->data))[index]->size;
}
void free_data(data_t *data, int is_array){
if(is_array){
int i;
for(i=0; i<(data->size / sizeof(data_t)); i++)
free(((data_t**)(data->data))[i]->data);
}
free(data->data);
}
int main(int argc, char**argv){
data_t data;
set_integer(&data, 42);
int val;
get_integer(&data, &val);
printf("expect 42; has: %d\n", val);
free_data(&data, 0);
data_t element;
create_array(&data, 3);
int i;
for(i=0; i<3; i++){
set_integer(&element, i*2);
set_array(&data, i, &element);
}
for(i=0; i<3; i++){
get_array(&data, i, &element);
get_integer(&element, &val);
printf("index: %d; value: %d\n", i, val);
}
free_data(&data, 1);
return 0;
}
((data_t**)(data->data))[i] is used when data->data is an array of pointers, try
((data_t*)(data->data))[i]
EDIT: to access the members, use something like
((data_t*)data->data)[i].data = NULL;
((data_t*)data->data)[i].size = 0;
What does data->data point to? Well, the line data->data = malloc(data->size); tells you: it points to a slap of uninitialized memory.
The problem is, that you don't store anything in that memory before trying to dereference a pointer you read from this memory. I. e. (data_t**)data->data is fine, ((data_t**)data->data)[index] yields a data_t* of undefined value, and because that value is undefined, dereferencing the pointer with ((data_t**)data->data)[index]->data is undefined behavior.
If you want to create an array of data_t objects, one indirection suffices, i. e. use
void create_array(data_t *data, size_t len){
data->size = sizeof(data_t) * len;
data->data = malloc(data->size);
int i;
for(i=0; i<data->size; i++){ //initialize array
((data_t*)(data->data))[i].data = NULL;
((data_t*)(data->data))[i].size = 0;
}
}
((data_t**)(data->data))[i];
In the above statement, data->data evaluates to data member of structure variable data (you should use different identifiers) which is of type void *. Now, you want to point data->data to a buffer which is an array of objects of type data_t. This means you must cast data->data to type data_t *, and not data_t **. Therefore, you should change the above statement to
((data_t *)(data->data))[i];
everywhere in your code. Also, note that free takes an argument of type void * and therefore you don't need to cast your pointer before passing it to free.
I would like to create a function that will reallocate 2D array of typedef struct
typedef struct hero_data{
char name[254];
char title[254];
int encoding;
int startstr;
double incstr;
int startdex;
double incdex;
int startintel;
double incintel;
int basemindmg,basemaxdmg;
double bat;
double basearmor;
struct hero_data *next;
struct hero_data *Class;
}hero;
typedef struct parameters{
int toughtotal;
int nimbletotal;
int smarttotal;
int skeptictotal;
int mystictotal;
int cursedtotal;
int brutetotal;
int shreddertotal;
int vanillatotal;
int typetotal;
int typenum;
hero **smart[];
hero **nimble[];
hero **tough[];
hero **type[][];
hero **skeptic[][];
hero **mystic[][];
hero **cursed[][];
hero **brute[][];
hero **shredder[][];
hero **vanilla[][];
}Parameters;
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p = realloc(p,sizeof(Parameters *) * typenum);
for ( i = 0; i < typenum; i++)
{
p[i] = realloc(p[i],sizeof(Parameters) * typetotal);
}
}
The function above shall be called like: void reallocation(p->type,p->typenum,p->typetotal);
So, by substituting the parameters of the function correctly, I expect the function to look like:
void reallocation(Parameters *p, int typenum,int typetotal)
{
int i;
p->type = realloc(p->type,sizeof(Parameters *) * p->typenum);
for ( i = 0; i < p->typenum; i++)
{
p->type[i] = realloc(p->type[i],sizeof(Parameters) * p->typetotal);
}
}
The typedef struct named Parameters contains int typenum, int typetotal, and the 2D arrays that shall be initialized through realloc().
When I try to compile, I am getting an error in Tiny C (Windows): *The file is in C.
Error: cannot cast 'struct parameters' to 'void *'
(This apeears in the 'p[i] = realloc(p[i],sizeof(Parameters) * typetotal')
Can anyone help me re-write this function so that I will be able to realloc the 2D arrays within the Parameter *p?
I tried changing void reallocation(Parameters *p, ...) into void reallocation(Parameters *p[], ...) and the Error # 2 becomes the same message as Error #1 and it appears in the = of p[i] = realloc (...);
A large problem with your code is that you are assigning inequal types to each other, and you are also not checking the result of realloc. If this call were to fail, you will leak the memory allocated initially.
Assuming that your struct looks like
typedef struct {
int typenum;
int typetotal;
} Parameters;
Parameters *p;
p = malloc(10 * sizeof(*p));
if (p == NULL)
printf("Allocatation of memory failed!\n");
To properly reallocate to say 20, you could do something like this
reallocate_p(&p, 20);
Where the function is defined as
void reallocate_p(Parameters **p, int new_size)
{
Parameters *temp;
temp = realloc(*p, sizeof(*temp) * new_size);
if (temp==NULL) {
printf("Reallocatation of memory failed!\n");
// Handle error
}
*p = temp;
return;
}
Also note that we don't cast the return value of malloc() and realloc().
As to why, see this reference
OP is coding in C, but using a using a C++ compiler.
Code in C++
// C
// p = realloc(p,sizeof(Parameters *) * typenum);
// C++
p = (Parameters *) realloc(p,sizeof(Parameters *) * typenum);
OR
VS2012: set properties for each C file to use C compiler
How to compile C in visual studio 2010?
OP code has a memory leak when scaling down the pointer array table. The pointers in the table that are about to be loss due to realloc() need to be freed first.
for (i=old_typenum; i<typenum; i++) free(p[i]);
p = realloc(p,sizeof(Parameters *) * typenum);
int *f, *l;
int main(){
int *a;
a = calloc(1, sizeof(int));
f = l = a;
put(&a, 1);
put(&a, 3);
put(&a, 2);
_getch();
return 0;
}
void put(int **a, int d){
printf("--%d--", sizeof(*a)); //always == 4
void *tmp = (int *)realloc(*a, sizeof(*a) + sizeof(int));
if (temp) //allocated succesfully
*a = temp;
else
printf("Allocating a failed");
l++;
}
I trying to create a queue model based on int pointers.
I've corrected the sample a bit. But it still failed.
Could you please help?
a is an int pointer (int*), therefore its size if 4 bytes (on your machine) you should keep track of the size of allocated memory.
For example:
int *f, *l;
int main(){
int *a;
size_tasize = 0;
a = calloc(1, sizeof(int));
f = l = a;
asize = sizeof(int);
put(a, 1, &asize);
put(a, 3, &asize);
put(a, 2, &asize);
_getch();
return 0;
}
void put(int *a, int d, size_t * asize){
printf("--%d--\n", asize); //always == 4
void *tmp = (int *)realloc(a, *asize + sizeof(int));
(*asize) += 4;
if (tmp)
a = tmp; //allocated succesfully
else
printf("Reallocating of 'a' size %d failed\n", asize);
l++;
}
In C, there is no way to know the size of an array which is referenced by a pointer:
int a[25]; // Known size
int *b = a; // Unknown size
so the sizeof() just prints the size of the pointer which is 4 bytes on a 32bit platform.
If you need the size, allocate a structure like so:
struct Mem {
int size;
int a[1];
}
Use sizeof(struct Mem) + sizeof(int) * amount to determine how much memory to allocate, assign it to a pointer. Now you can use the memory with ptr->a[x].
Note that it will allocate a bit more memory that necessary (usually 4 bytes) but this approach works with different alignments, pointer sizes, etc.
sizeof(a) is the size of the pointer, not what a points to.
You are modifying the local variable a within the function, not the variable a in your main function. You either need to return the new value of a from put() or pass in a pointer to your pointer (int **a) to modify it.
For example:
int *put(int *a, int d);
int main(){
int *a;
a = calloc(1, sizeof(int));
a = put(a, 1);
...
}
int *put(int *a, int d){
void *tmp = (int *)realloc(a, sizeof(a) + sizeof(int));
if (tmp)
a = tmp; //allocated succesfully
else
printf("Reallocating of 'a' size %d failed\n", sizeof(a));
return a;
}
sizeof(a) will always return 4 in your case. It returns the size of the pointer, not the size of the memory allocated that the pointer is pointing to.
Instead of doing
if (tmp)
a = tmp;
return tmp and assign it to a in main.
If you want to re-assign a new block to the pointer in a function other then one in which it has been defined , you have to pass a pointer to this pointer or return the newly allocated block and collect it into the same older block in caller function, as otherwise you'd be updating a copy.
The whole concept does not work the way you would it have to.
The sizeof a stuff does not work the way you intend to.
The reallocation itself is wrong, as you don't return the new address to the caller.
You have no information about the length of your data.
I would propose the following:
struct memblock {
unsigned int alloced;
unsigned int len;
int * data;
}
// in order to prealloc
char add_realloc(struct memblock * mb, unsigned int add) {
add += mb->alloced;
int * tmp = realloc(mb->data, sizeof(*mb) + add * sizeof(*(mb->data)));
if (!tmp) return 0;
mb->data = tmp;
mb->alloced = add;
return 1;
}
char put(struct memblock * mb, int d) {
if (mb->len == mb->alloced) {
// realloc
if (!add_realloc(mb, 1)) return 0;
}
mb->data[mb->len++] = d;
return 1;
}
int main(){
struct memblock a = {} // init with all zeros.
// Calling realloc() with a NULL pointer is like malloc().
// we put 3 values. Prealloc for not to have to realloc too often.
if (add_realloc(&a, 3) {
// now we are safe. Don't check the return values - it is guaranteed to be ok.
put(&a, 1);
put(&a, 3);
put(&a, 2);
}
return 0;
}