i have an array with an initial size
int size = 5; //initial size ofwordsArray
wfpPointer wordsArray = new WordFrequencyPair[size];
where wfpPointer is a typedef for a pointer that points to the adress of a variable of type WordFrequencyPair.
now when i detect that my array is full i call the following function to expand it:
int expandWordsArray(WordFrequencyPair wordsArrayIn[], int currentSize){
int newSize = currentSize * 2;
wfpPointer newArray = new WordFrequencyPair[newSize];
for(int i = 0; i < currentSize; i++)
newArray[i] = wordsArrayIn[i];
delete [] wordsArrayIn;
wordsArrayIn = newArray;
return newSize;
}
the thing is when i write this code in the main without calling the function it works perfectly fine and the array expands. From within the function however my program crashes. Note: eclipse gives me no errors and compiles the program without trouble.
Plz help
Thank you
You are passing the array (that is, a pointer to the first element of the array) by value. The function deletes, the array (using the original value of the pointer), then constructs a new array on the heap and points the local pointer to it.
Meanwhile, back in the calling code (main), the pointer hasn't changed and the old array has been deleted. When you try to dereference the pointer, BOOM!
You should pass the pointer by reference:
int expandWordsArray(WordFrequencyPair *&wordsArrayIn, int currentSize)
Related
I have to dynamically increase a length of double array. I know, how to do it with char array, so I tried this:
int main() {
char * tmp = NULL;
for (int i = 1; i <= 4; i++) {
tmp = realloc(tmp, i * sizeof(char));
tmp[i] = 'i';
}
puts("char OK");
double * tmp1 = NULL;
for (int i = 1; i <= 4; i++) {
tmp1 = realloc(tmp1, i * sizeof(double));
tmp1[i] = 0;
}
return 0;
}
The first array works fine. But the second one crushes with message realloc(): invalid next size.
These are my 2 questions:
Why this way doesn't work in a double array?
How to dynamically increase the size of array of doubles?
UPD:
removed a typo
TL;DR: Both the snippets are wrong, the first one appears to work because of undefined behavior.
To elaborate, the problem is with your indexing logic. C uses a 0-based indexing. So, inside the loop which is staring the iteration from value of i as 1, by using
tmp[i] = .......
you're trying to access invalid memory, at this point, only access up to tmp[i-1] is valid.
You need to use tmp1[i-1] = 0;, and likewise.
That said,
Always check for the success of the memory allocator functions before using the returned pointers.
Never use the form
pointer = realloc (pointer, ......)
because, in case realloc call fails, you'll end up losing the original pointer, too.
Quoting C11, chapter ยง7.22.3.5
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
and
[....] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Always use a temporary pointer variable to store the return value of realloc(),
check for the success of the call [not-null return value] and
then assign it back to the original variable, if needed.
I have a weird problem and I don't know the reason, so I can't think of a solution to fix it.
My problem:
I have a removeEntry function with a array of structs as parameter, but somehow this function doesn't work.
In an earlier version of my code, I declared my array of structs outside the main function (outside every function), and it worked then. But since I now create my array of struct in my main function, I have to give it as parameter, and now my removeEntry function doesn't work.
Code that isn't working:
void removeEntry(struct entry entries[])
{
int entryNumber;
int nrBytes = sizeof(entries);
int arrayLength = nrBytes / sizeof(entries[0]);
printf("\nEnter entry number to delete: ");
scanf("%d",&entryNumber);
while (scanfOnlyNumber(entryNumber) == false || entryNumber == 0 || entries[entryNumber].entry_number == 0)
{
printf("\nEnter a legit entry number to delete: ");
scanf("%d", &entryNumber);
// Tell the user that the entry was invalid
}
int i = 0;
for(i = entryNumber; i < arrayLength - 1; i++)
{
entries[i] = entries[i + 1]; //removes element and moves every element after that one place back.
}
updateEntryNumber(entries);
printf("\nEntry %d removed succesfully, and entry numbers updated!\n", entryNumber);
}
My teacher told me that my arraylength calculation doesn't work when I create my array of structs inside my main function (what I do now),
but I can't tell why it doesn't work. If anybody can explain that, then I might be able to fix my removeEnty problem by myself.
If anyone wants the working code (where I don't give my array as parameter, because I create my array outside every function), then tell me and I will post it.
Problem
When you pass an array to a function, you don't pass the entire array, instead you pass a pointer to the array. Hence, when you do int nrBytes = sizeof(entries); you're actually getting the size of pointer variable rather than the size of array.
Solution
Pass your array length along with a pointer to the array to the function, something like this:
void removeEntry(struct entry entries[], int arrayLength){
// your code
}
int nrBytes = sizeof(entries); // basically size of struct node *
int arrayLength = nrBytes / sizeof(entries[0]);
In this sizeof(entries) will give size of struct pointer , and not the array , and also in second statement , it wont correctly .
This is because array decays into pointer after passing it to function and referring it .
What you need to do is calculate number of elements in struct array in main and then pass it to the function .
void removeEntry(struct entry entries[],int arrayLength);
Calculate arrayLength in main as you do.
if you compile your example, you will probably see a warning like this one:
warning: sizeof on array function parameter will return size of 'entry *' instead of 'entry []' [-Wsizeof-array-argument]
As noted in the answer by V. Kravchenko, this suggests that nrBytes will contain merely the size of the pointer, while sizeof(entries[0]) returns the "true" size of the entire structure. Therefore, arrayLength will be most probably zero.
You should pass array's size to function, because int nrBytes = sizeof(entries); is always 4 or 8 (on x64 systems). It's just pointer's size.
int nrBytes = sizeof(entries);
Arrays of any type (even arrays of structs) decay into pointers when passed to a function. The lenght of this pointer is always fixed and gives no indication as to the lenght whatsoever. So pass the lenght with the function call.
Save pointer to array in struct.
I would like to store the pointer to array of int into struct but I am having trouble.
Below my code with commentaries:
typedef struct _index {
int *data;
} Index;
void adder(struct _index *s){
int i;
int arr[maxint];
for(i=0; i<maxint; i++) {
arr[i] = i+42;
}
//i got a gibberish
//s->data = arr;
//works fine
s->data = (int *) malloc(maxint * sizeof(int));
s->data = memcpy(s->data, arr, maxint * sizeof(int));
)
int main() {
Index n;
int i;
//this method also works.
//int arr[maxint];
//for(i=0; i<maxint; i++) {
// arr[i] = i+42;
//
//}
//n.data = arr;
adder(&n);
for(i=0; i<maxint;i++) {
printf("%d-", n.data[i]);
}//testing
return 0;
}
when i make assignment, i got strange numbers:
117-118-119-120-12-0-22-2292964-0-2293008-127-0-129-130-131-0-0-0-0-0-0-138-0
but if i use malloc and memcpy all works fine
You got gibberish in your first case, because you tried to "return" the address of a local variable from a function through the pointer. Once the function finishes execution, the int arr[maxint]; won't be valid. In other words, after adder() finishes execution, int arr[maxint]; goes out of scope and it's lifetime is over. So, the (returned) pointer becomes invalid and using that further in the caller function will result in undefined behaviour.
Solution:
As you've done correctly, using dynamic memory.
use static variable (not a good approach, but possible).
In both the aforesaid approach, the lifetime of the variable ( static arr array/ malloc()ed memory) is not limited to function scope and thus, the pointer to the meory will be vaild in the caller function.
The array arr in the adder() function is on the stack and only exists as long as the code in that function is running. Once adder() returns that memory is re-used by the rest of the program and its content overwritten.
int arr[] is placed on the stack and gets removed from the stack when it goes out of scope. So you will point to garbage.
It works fine if you include it in your main because that way it hasn't gone out of scope yet.
Malloc works because you allocate memory and not just place it on the stack.
While learning about pointers, arrays and functions on tutorials point I realised that I could achieve my goal of returning an array from a function by creating a new array in the main function, creating a pointer and assigning the return value of the function to this pointer and then using a for loop in the main function incrementing the pointer to reassign the values of the array to the array internal to the sorting function.
However I was wondering since the memory is returned to the stack after the function returns how come the values in the array aren't reassigned to something else and secondly is there a way I could using memory addresses change the actual array in the main function inside the sorting functions and then return void? I am using a bubble sort algorithm, this is my current sorting function;
#include <stdbool.h>
int *arr_sort(int *arr){
int *ptr = arr;
bool flag = true;
while(flag){
flag = false;
int i = 0;
for(i;i<4;i++){
if(arr[i]>arr[i+1]){
flag = true;
arr[i]+=arr[i+1];
arr[i+1] = arr[i]-arr[i+1];
arr[i]-= arr[i+1];
}
// printf("%d : %d\t%d : %d \n",i,arr[i],i+1,arr[i+1]); *Included to display the values as they are being switched
}
printf("\n\n");
}
return arr;
}
Then the for loop in the main that assigned my array (called unsorted_array) to the pointer as it is incremented through the array created inside the sorting function
ptr = arr_sort(unsorted_array);
for(j;j<5;j++){
unsorted_array[j]=*(ptr+j);
The whole thing works as a program but I was just wondering in the interest of building up knowledge (Haven't been programming in C for long), is there a better way to do this?
No need to return array from your function. Just define your function as
void arr_sort(int *arr){
bool flag = true;
while(flag){
flag = false;
int i;
for(i = 0; i < 4; i++){
if(arr[i] > arr[i+1]){
flag = true;
arr[i]+=arr[i+1];
arr[i+1] = arr[i]-arr[i+1];
arr[i]-= arr[i+1];
}
}
printf("\n\n");
}
}
Any and all changes to arr will be made to the array in main.
I assume that you, with "creating a new array in the main function" mean something like this:
int main(int argc, const char *argv[])
{
char unsorted_array[ARRAY_SIZE];
// ... Code
}
Any variable, (trivial, pointer or array) located on the stack is kept while calling another function, but any variable located on the stack by the called function is invalidated when the function returns.
But: a pointer located on the stack may point to an array on the heap. That is if the array is either allocated by malloc(), being declared as static inside the function, or being a global variable. In that case, the content of the array is of course kept as the function returns, and can be made available to the calling function by e.g returning the pointer. Only the pointer (e.g. typically 4 bytes) is copied to the calling function stack as the function returns, not the array which the pointer points to.
Similarly, an array located on the stack may be made available to a called function, by supplying the called function with a pointer to the array, just as you do. What is copied to the called function's stack, is only the pointer (4 bytes), hence the called function may access and modify the array, and the array itself is not invalidated as the function returns.
NB: in C, when invoking a function declared as
void afun(char anarray[ARRAY_SIZE);
the compiler implicitly treats the function as if it was declared as
void afun(char *anarray);
i.e. calling afun only copies the pointer, not the array to the called function's stack.
Lets say I have the following situation (some rough pseudocode):
struct {
int i;
} x
main(){
x** array = malloc(size of x pointer); // pointer to an array of pointers of type x
int* size = current size of x // (initally 0)
add(array, size);
}
add(x** array, int* size){ // adds one actual element to the array
x** temp = realloc(array, (*size)+1); // increase the array size by one
free(array);
array = temp;
// My question is targeted here
array[*size] = malloc(size of x); // makes a pointer to the value
array[*size]->i = size;
*size++;
}
My question is: Once add() is finished, do the values of the pointers stored in array disappear along with the function call stack, since I allocated them inside func()? I fear that they might, in which case would there be a better way for me to do things?
No, they don't. They persist until the pointer returned by malloc() is passed to the corresponding free() function. There would be no point in the existence of the malloc() function if it worked the same way as automatic arrays.
Edit: sidenote. As #Ancurio pointer it out, you're incorrectly freeing the memory behind the previous pointer returned by malloc() which is at that time invalid as realloc() has been used on it. Don't do that. realloc() does its job properly.)