I have had a look around but have not been able to find an answer to this question already. I am trying to create a hash table of which each element is a struct. In each struct is a variable to let the program know if the cell has been occupied, for this to work I need to set all of them to zero. The thing is it worked fine but now and then (seemingly randomly) I'd get an access violation. I thought I fixed it but when I come to grow my array the error creeps up again, leading me to believe that I have made an error. My pointer knowledge is not that good at all, so any help would be appreciated. This is what the function looks like:
HashTableCell *initialiseTable(HashTableCell *hashTable, int *tableSizePtr)
{
int i = 0;
int totalSize = *tableSizePtr * sizeof(HashTableCell);
HashTableCell *tempStartingcell;
tempStartingcell = (HashTableCell*)malloc(sizeof(HashTableCell));
*tempStartingcell = *hashTable;
while (i <= *tableSizePtr)
{
/*we keep moving forward, need to use the first entry*/
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
hashTable->isOccupied = 0;
i++;
}
free(tempStartingcell);
return hashTable;
}
And before I malloced some space for the table and passed it in another function like so:
HashTableCell *hashTable;
hashTable = (HashTableCell*)malloc((sizeof(HashTableCell)*tableSize));
hashTable = initialiseTable(hashTable, tableSizePtr);
The idea is to start at the beginning and move along the correct number of spaces along per iteration of the while loop. When I come to resize I merely make a new array with double the malloced space and pass it to the initialise function but this throws up an access violation error at seemingly random indexes.
I am using VS2015 if that helps anything.
Thank you for your help.
The problem is in this line:
*hashTable = *(tempStartingcell + (i * sizeof(HashTableCell)));
When you are adding an integer to a pointer, C and C++ already take into account the size of the array elements, so you should not multiply with sizeof(HashTableCell), but rather do:
*hashTable = *(tempStartingcell + i);
Otherwise, your extra multiplication will cause an access outside of the tempStartingCell array. It makes even more sense to write it like this:
*hashTable = tempStartingcell[i];
But there is more wrong with your code; if you just want to set isOccupied to zero for each element in hashTable, just do:
void initialiseTable(HashTableCell *hashTable, int tableSize)
{
for (int i = 0; i < tableSize; i++)
hashTable[i].isOccupied = 0;
}
Related
I have to read a txt with data in it. I can read it and store the data, but I don't know why, some stored data is not good after the read method.
Here is my output:
I write out these data with exactly the same code, except that the first is inside the loop and the second is outside of the loop.
I store these data in their own struct arrays. So as you can see, my problem is that I can't access my data outside that loop. What could be wrong?
Here is the full code: https://pastebin.com/wzEJqcZG
And the test data: https://pastebin.com/L7J133mz
This is inside the file read loop:
printf("%c %i - ", sorok[i].futarkod, sorok[i].datum);
for(j=0;j<sorok[i].rendelesCount;j++) {
printf("%i%c", sorok[i].rendelesek[j].db, sorok[i].rendelesek[j].fajta);
}
printf("\n");
And this is outside of the file read loop:
for(i=0;i<5;i++) {
printf("%c %i - ", sorok[i].futarkod, sorok[i].datum);
for(j=0;j<sorok[i].rendelesCount;j++) {
printf("%i%c ", sorok[i].rendelesek[j].db, sorok[i].rendelesek[j].fajta);
}
printf("\n");
}
In the output the first two columns are good, just the text after the dash is not.
test.c:65:14: warning: 'sor' may not be used as an array element due to flexible array member
[-Wflexible-array-extensions]
sor sorok[32];
^
rendeles rendelesek[]; is a flexible array member meaning since it's at the end of the struct you can, in theory, allocate as much memory for the array as you like. However this means the size of any given sor will vary.
Each element of an array in C must be of a fixed size, going from one element to another is simply start-of-array-memory + (i * sizeof(element)). Since sor can be of different sizes it can't be put into an array.
You could use an array of pointers to sor, or you can change sor to contain a pointer to rendeles **rendelesek;. Or both, getting used to working with pointers is good.
The real problem is sor.rendelesek is never allocated. Whichever you choose, you still have to allocate memory to sor.rendelesek else you're writing into someone else's memory. As a flexible array member, you have to use a pointer array and allocate sufficient memory as part of sor.
typedef struct {
char futarkod;
int datum;
int rendelesCount;
rendeles rendelesek[];
} sor;
sor *sorok[32];
for( size_t i = 0; i < 32; i++) {
sorok[i] = malloc(sizeof(sor) + (sizeof(rendeles) * 32));
}
Or you can use a rendelesek ** instead and allocate that directly. Combining both is probably the best option.
typedef struct {
char futarkod;
int datum;
int rendelesCount;
rendeles *rendelesek;
} sor;
sor *new_sor(const size_t num_rendeles) {
sor *new = malloc(sizeof(sor));
new->rendelesek = malloc(sizeof(rendeles) * num_rendeles);
return new;
}
int main()
{
sor *sorok[32];
for( size_t i = 0; i < 32; i++) {
sorok[i] = new_sor(32);
}
Reading inputs into statically allocated structures like this is risky and wasteful because you have to allocate what you think is the most possible elements. It's very easy to allocate way too much or not enough. Instead they should be dynamically allocated as needed, but that's another thing.
OK, so the problem is basically like the title. Couldn't find a question that got all bits of it, so I figured I'd ask.
Say I want an array of structs shaped like the following
typedef struct s_woo{
char** n;
char* x;
} t_woo;
So I believe I should do
t_woo* woos = malloc(num_woos * sizeof(*woos));
Seems simple enough (and should deter people from yelling at me for my habit of casting malloc).
Then I want to initialize the things in each of those structs.
So intuitively I do:
for(i = 0; i < num_woos; i++){
num_ns = randomint1 / randomint2; //let's say num_ns is big, like 250-ish, average, and changes every round of the loop
woos[i].n = malloc(num_ns * sizeof(char*));
woos[i].x = malloc(num_ns * sizeof(char));
for(j = 0; j < num_ns; j++){
woos[i].n[j] = malloc(16 * sizeof(char)); // I just want 16 characters per char*
}
}
This is the boiled down version of what I have in my code. I want to know what can possibly go wrong with what I've written - like any possible thing. I'm not looking for anything in particular, just general problems with the above, like memory/heap issues, pointer mistakes etc.
Leave out "Virtual Memory Exhausted". My code error checks for that using a wrapper function on malloc, so I'm very sure that's not it.
Even better:
static const size_t woo_n_size = 16;
/* To make sure you use 16 everywhere,
* also easier to change it
*/
struct woo_item {
char n[woo_n_size];
char x;
};
struct s_woo {
struct woo_item *items;
size_t size; / * optinal, to keep track of item count */
}
With the woo_item struct you can make sure there is no x without n[woo_n_size] allocated, and vice versa.
You can remember the count of woo_items by having a designated null element to close each of your lists, or just store a size member in s_woo
It was, actually, the display function after all. Sorry if I wasted your time (I didn't actually put the code of the display function here, my bad. However, I did learn some new things, so thank you all!
I have created a structure which involves an array that represents a set of integers.
When I first create a structure, I use malloc() to allocate space for the structure and thus, the array.
The problem resides, however, in the fact that when I create the structure, the first element of the array is being assigned a number. I want, however, to just create a structure where the array in it is uninitialised.
typedef struct set{
int numberOfValues; /* The number of values in the set */
int value[40]; /* the set */
} *Set; /* Set is thus a pointer to struct set */
Set aOfPStructs[4];
void create()
{
static int setnum = 0;
Set S; /* S is a pointer to struct set */
if (setnum <= 4)
{
S = (struct set *) malloc(sizeof(struct set));
S->numberOfValues = 0;
aOfPStructs[setnum] = S;
printf("The set's number is %d\n", setnum);
setnum++;
}
else
printf("Error. No more sets can be created.\n");
}
The above is only a snippet from the whole program, but any other code is irrelevant to the question tbh.
So with that code, if I were to display the contents of the array in the structure, I would get 1 value. Thing is, I have not added any elements to the array, so I should get no values at this point. Can I fix this?
Any help would be appreciated! Thanks!
Edit:
I tried memset(), but it's not exactly what I want. When I use the create(), I want 0 elements in the array value[], but the code is generating 1 random element once I use the create function.
The function. to display the element seems to work just fine though. Funny thing is, when I run a function to delete one element from the array, that extra element is removed, only to be added again if I run the add() function.
Edit 2:
Added a screenshot for further explanation of my problem. I appreciate every comment thus far, and future ones too.
http://imgur.com/cza3ip6
Edit 3:
Ok, I get the use of memset() now and the concept of initialisation. Thing is, if I wanted to check the number of elements of the set, just right after I create it, I should get 0 because I have not added any elements, but an element is being generated with create...
I think you may not understand what "initialized" and "uninitialized" mean.
"Uninitialized" means "holding whatever bit pattern happens to be left over from the last computation that used this memory or from bootstrapping the machine."
"Initialized" just means you have assigned a set value.
The malloc call gives you uninitialized storage according to this definition. So what you are seeing is the best you can get. You are printing the integer formed from the arbitrary bit pattern in the first array slot.
For what it's worth, the simplest way to get a pre-zeroed memory block of n ints (initialized to zero) is to say.
int *blk = calloc(n, sizeof(int));
Use memset to set to 0 all the data in the structure. By default when you use malloc the memory you get is not initiliazed:
S = (struct set *) malloc(sizeof(struct set));
memset(S, 0, sizeof(struct set));
Try this. It uses a little different approach to create and initialize array of structs, but the relevant point is that it uses memset to init array of ints for each element of struct array:
#include<stdio.h>
typedef struct {
int numberOfValues; /* The number of values in the set */
int value[40]; /* the set */
}SET;
SET set[4], *pSet; //initialize SET *, pSet to the first position of set
main()
{
int i;
pSet= &set[0];
for(i=0;i<4;i++)
{
memset(pSet[i].value, 0, sizeof(int)*40); //set all elements of member value to 0
}
}
You haven't posted the function displaying your set. I suppose that the problem may be there. Maybe you use something like for(i=0; i <= S->numberOfValues; i++) instead of for(i=0; i < S->numberOfValues; i++), so you print the first element even if not there.
I am trying to implement a priority queue based on binary heap using a static array (I will be later using a linked list, just wanted to test first with an array).
typedef struct n
{
int x;
int y;
int size;
double value;
} node;
node arr[100];
int total = 1;
void insertElement(int x, int y, int size, double value)
{
node n;
n.x = x;
n.y = y;
n.size = size;
n.value = value;
arr[total] = n;
if (total > 1)
insertArrange(total);
total += 1;
}
Now in the delete function i will just return the top most node and delete it, then re-arranging the whole heap. Problem is I can not free any memory. Suppose I use
free(&arr[1]);
I am getting pointer being freed was not allocated error. Is this the proper way of implementation? How to tackle memory issues?
I am using Xcode with Apple LLVM 4.2 compiler. This entire thing will be ultimately put into a bigger project in Objective-C but for now I do not want to use NSMutableArray. I want a simple solution in C.
You only need to call free() if you have used malloc() or calloc(). In fact, attempting to free anything else is undefined behaviour.
As it stands, your code will not be leaking any memory.
Why delete? You could just zero it out and write new data to it whenever you need to. Also My recommendation would be to remember which nodes you delete, so that later when you need to insert a new node, you will know beforehand where the free space is.
For example:
node arr[10];
indexes free_index[10];
//(delete the 6th member of nodes)
delete arr[5];
//remember which one you deleted
free_index[0] = 5;
//later when you add new node you can search the index and pick the first matching value
// zero it out so that it will not be used accidentally again like this
int i = free_index[0] // finding which one is free is task for loops
new_node(arr[i]);
free_index[i] = NULL;
This code example here is very incomplete you have to complete it depending on your own implementation. I just gave you the idea. watch out for free_index [0] = 0; it basically will never match as a valid index. If you zero out indexes with = NULL statement.
There is also a big assumption from my side that you do not wish to shrink the size of this array or grow it. Just empty some elements and then add new ones.
If you want to grow the array you have to calloc it first. I advise calloc because you can allocate array of structs with it.
Growing this is easy with realloc.
But with shrinking you need to create temporary array of nodes where you will store all active results, shrink the original array, put the active results from temporary array back into original and free temporary array.
calloc(numberofnodearrays,sizeof(node));
I am supposed to follow the following criteria:
Implement function answer4 (pointer parameter and n):
Prepare an array of student_record using malloc() of n items.
Duplicate the student record from the parameter to the array n
times.
Return the array.
And I came with the code below, but it's obviously not correct. What's the correct way to implement this?
student_record *answer4(student_record* p, unsigned int n)
{
int i;
student_record* q = malloc(sizeof(student_record)*n);
for(i = 0; i < n ; i++){
q[i] = p[i];
}
free(q);
return q;
};
p = malloc(sizeof(student_record)*n);
This is problematic: you're overwriting the p input argument, so you can't reference the data you were handed after that line.
Which means that your inner loop reads initialized data.
This:
return a;
is problematic too - it would return a pointer to a local variable, and that's not good - that pointer becomes invalid as soon as the function returns.
What you need is something like:
student_record* ret = malloc(...);
for (int i=...) {
// copy p[i] to ret[i]
}
return ret;
1) You reassigned p, the array you were suppose to copy, by calling malloc().
2) You can't return the address of a local stack variable (a). Change a to a pointer, malloc it to the size of p, and copy p into. Malloc'd memory is heap memory, and so you can return such an address.
a[] is a local automatic array. Once you return from the function, it is erased from memory, so the calling function can't use the array you returned.
What you probably wanted to do is to malloc a new array (ie, not p), into which you should assign the duplicates and return its values w/o freeing the malloced memory.
Try to use better names, it might help in avoiding the obvious mix-up errors you have in your code.
For instance, start the function with:
student_record * answer4(const student_record *template, size_t n)
{
...
}
It also makes the code clearer. Note that I added const to make it clearer that the first argument is input-only, and made the type of the second one size_t which is good when dealing with "counts" and sizes of things.
The code in this question is evolving quite quickly but at the time of this answer it contains these two lines:
free(q);
return q;
This is guaranteed to be wrong - after the call to free its argument points to invalid memory and anything could happen subsequently upon using the value of q. i.e. you're returning an invalid pointer. Since you're returning q, don't free it yet! It becomes a "caller-owned" variable and it becomes the caller's responsibility to free it.
student_record* answer4(student_record* p, unsigned int n)
{
uint8_t *data, *pos;
size_t size = sizeof(student_record);
data = malloc(size*n);
pos = data;
for(unsigned int i = 0; i < n ; i++, pos=&pos[size])
memcpy(pos,p,size);
return (student_record *)data;
};
You may do like this.
This compiles and, I think, does what you want:
student_record *answer4(const student_record *const p, const unsigned int n)
{
unsigned int i;
student_record *const a = malloc(sizeof(student_record)*n);
for(i = 0; i < n; ++i)
{
a[i] = p[i];
}
return a;
};
Several points:
The existing array is identified as p. You want to copy from it. You probably do not want to free it (to free it is probably the caller's job).
The new array is a. You want to copy to it. The function cannot free it, because the caller will need it. Therefore, the caller must take the responsibility to free it, once the caller has done with it.
The array has n elements, indexed 0 through n-1. The usual way to express the upper bound on the index thus is i < n.
The consts I have added are not required, but well-written code will probably include them.
Altought, there are previous GOOD answers to this question, I couldn't avoid added my own. Since I got pascal programming in Collegue, I am used to do this, in C related programming languages:
void* AnyFunction(int AnyParameter)
{
void* Result = NULL;
DoSomethingWith(Result);
return Result;
}
This, helps me to easy debug, and avoid bugs like the one mention by #ysap, related to pointers.
Something important to remember, is that the question mention to return a SINGLE pointer, this a common caveat, because a pointer, can be used to address a single item, or a consecutive array !!!
This question suggests to use an array as A CONCEPT, with pointers, NOT USING ARRAY SYNTAX.
// returns a single pointer to an array:
student_record* answer4(student_record* student, unsigned int n)
{
// empty result variable for this function:
student_record* Result = NULL;
// the result will allocate a conceptual array, even if it is a single pointer:
student_record* Result = malloc(sizeof(student_record)*n);
// a copy of the destination result, will move for each item
student_record* dest = Result;
int i;
for(i = 0; i < n ; i++){
// copy contents, not address:
*dest = *student;
// move to next item of "Result"
dest++;
}
// the data referenced by "Result", was changed using "dest"
return Result;
} // student_record* answer4(...)
Check that, there is not subscript operator here, because of addressing with pointers.
Please, don't start a pascal v.s. c flame war, this is just a suggestion.