c why realloc isn't working - c

I have the following code
void getPariceArray(Board board, treeNode *tn, Position *dst, int **prices, int *counter, int total)
{
if (tn == NULL)
return NULL;
if (tn->position[0] == dst[0][0] && tn->position[1] == dst[0][1])
{
prices = (int **)realloc(prices, sizeof(prices) *4);
prices[*counter] = (int *)malloc(sizeof(int));
printf("%d", sizeof(prices));
*prices[*counter] = total;
*counter = *counter + 1;
}
int x = tn->position[1] - '1';
int y = tn->position[0] - 'A';
int cellPrice = board[x][y] - '0';
total += cellPrice;
getPariceArray(board, tn->up, dst, prices, counter, total);
getPariceArray(board, tn->down, dst, prices, counter, total);
getPariceArray(board, tn->right, dst, prices, counter, total);
getPariceArray(board, tn->left, dst, prices, counter, total);
}
prices is array of pointers and every step in recursion I'm casting realloc to increase the prices size.
I got many error bugs and I had a feeling it related to allocation,
I printed the sizeof(prices) and I saw that it stayed 4 and not increase
Can someone please tell me where I went wrong?
thanks in advance
P.S
Edit
I have another function that princt the **prices
void printPricesArray(int **arr, int length)
{
for (int i = 0; i < length; i++)
{
printf("place:%d Price:%d\n", i, *arr[i]);
}
}
This is the error I'm getting when prices = realloc(prices, sizeof(prices) *4);
but when I'm changing the line to this prices = realloc(prices, sizeof(prices) * 150); everything goes well without errors because I know that in my example size isn't going passed 130, but I need dynamic increasing incase in different example size will be over 150.

I suppose that during code writing and correcting (compiler) errors the code evolved into a wrong direction.
I feel that you actually do not want to handle an array of pointers to integers but a (dynamically growing) array of integer values (not pointers to them). Yet the circumstance, that the function has to rewrite the pointer to the array, which led to introduce one more '*' in the interface, took you into the dilemma, and statement prices[*counter] = (int *)malloc(sizeof(int)) indicates to me that this is the basic misunderstanding.
Let me explain what I mean it on the following short example.
Suppose that we want to have a function dynamicPriceListAlloc, which allocates an array of integers for nrOfItems integers.
Let's start with the caller, i.e. function main: Therein, as we want to have a dynamically allocated integer array, we will hold a variable of type int *, i.e. a pointer to this array. As we want to have the array allocated in a function, we have to pass a pointer to this pointer, because otherwise the function could not assign the newly allocated memory address to this pointer. Hence, dynamicPriceListAlloc must take a pointer to a pointer to ints, i.e. int **.
But - now the misleading thing - the intent of dynamicPriceListAlloc is not to allocate a pointer with 10 pointers to ints, but to allocate an array of 10 integers and assigning this memory block to the pointer passed (by reference) as argument:
int main(){
int *priceList;
dynamicPriceListAlloc(&priceList, 10);
for (int i=0; i<10; i++)
printf("%d\n", priceList[i]);
}
void dynamicPriceListAlloc(int **prices, int nrOfItems) {
*prices = (int*)malloc(nrOfItems * sizeof(int));
for (int i=0; i<nrOfItems; i++)
// *prices[i] = i; // Wrong: takes prices[i] and then dereferences it
(*prices)[i] = i; // OK: derefernces prices (yielding a pointer an int-array) and then setting the i'th element
}
I suppose that you missed to correct the dereference-precedence thing in *prices[i] = i, and instead of correcting this to (*prices)[i] = i, you "solved" the problem by actually allocating storage for the pointer you dereference. And that's what I meant with "the code evolved in the wrong direction".
If I am right with this assumption, then your code would change as follows:
void getPariceArray(Board board, treeNode *tn, Position *dst, int **prices, int *counter, int total)
{
if (tn == NULL)
return;
if (tn->position[0] == dst[0][0] && tn->position[1] == dst[0][1])
{
size_t sizeOfPrices = (*counter) * sizeof(int);
*prices = (int*)realloc(*prices, sizeOfPrices);
printf("size of prices: %ld", sizeOfPrices);
(*prices)[*counter] = total;
*counter = *counter + 1;
}
int x = tn->position[1] - '1';
int y = tn->position[0] - 'A';
int cellPrice = board[x][y] - '0';
total += cellPrice;
getPariceArray(board, tn->up, dst, prices, counter, total);
getPariceArray(board, tn->down, dst, prices, counter, total);
getPariceArray(board, tn->right, dst, prices, counter, total);
getPariceArray(board, tn->left, dst, prices, counter, total);
}
And printPricesArray would be adapted as follows:
void printPricesArray(int *arr, int length)
{
for (int i = 0; i < length; i++)
{
printf("place:%d Price:%d\n", i, arr[i]);
}
}

Related

sprintf Producing segmentation fault

I am getting a segmentation fault from the below program.
#include <stdio.h>
#include <string.h>
void removeProcess(int*, int);
void removeProcessN(char**, int, int);
void main() {
int numPro = 0, quanTime = 0, contTime = 0, i, elemNum, time = 0;
//Supply variables with user input
printf("Enter number of processes: ");
scanf("%d", &numPro);
printf("Enter context switch time: ");
scanf("%d", &contTime);
printf("Enter quantum of time: ");
scanf("%d", &quanTime);
//Create array of number of process time
int proTime[numPro];
//Create string array for better output
char *proNames[numPro];
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
sprintf(proNames[i], "p%d", i);
}
elemNum = 0;
//While a process remains active
while (numPro != 0) {
//Retrieves the element being worked with
elemNum = elemNum % numPro;
//Describe process working with
printf("Executing process %s\nStart time = %d\n", proNames[elemNum], time);
proTime[elemNum] -= quanTime;
//If process time complete, remove process
if (proTime[elemNum] <= 0){
removeProcess(proTime, elemNum);
removeProcessN(proNames, elemNum, numPro);
--numPro;
}
//Add amount of time with context time
time = time + quanTime + contTime;
elemNum++;
}
}
/**
*#param *array pointer to an array of integers
*#param elem int of the element to remove
* Removes an element 'elem' from the supplied integer array.
*/
void removeProcessN(char **array, int numElem, int elem) {
char *temparray[numElem - 1];
//Copy array to temparray except for elem to remove
int i;
for (i = 0; i < elem; i++) {
if (i == numElem) {
continue;
} else {
temparray[i] = array[i];
}
}
//End by setting the pointer of array to the temparray
array = temparray;
}
/**
*#param *array pointer to an array of integers
*#param elem int of the element to remove
* Removes an element 'elem' from the supplied integer array.
*/
void removeProcess(int *array, int elem) {
//Number of elements in the array
int numElem = sizeof(array) / sizeof(int);
int temparray[numElem - 1];
//Copy array to temparray except for elem to remove
int i;
for (i = 0; i < numElem; i++) {
if (i == elem) {
continue;
} else {
temparray[i] = array[i];
}
}
//End by setting the pointer of array to the temparray
array = temparray;
}
I know the segmentation fault is coming from sprintf. I am trying to simulate how an operating system would complete a process using round robin. I have tried using sprintf because that's what tutorials were saying online to use when trying to manipulate strings. The removeProcessN is just removing an index from the array proNames. I am mostly just concerned with the sprintf.
I have tried malloc when I do the sprintf but it would not even compile at that point. If someone could offer an explanation I'd be appreciative.
The problem here is that proNames is an array of pointers, but they are
uninitialized, so passing it to sprintf to write something, will crash. You
would have either use a double array or allocate memory with malloc. But as
you are only printing integers and the string representatuion of integers has a
maximal length, allocating memory with malloc will be more harder, because you
have to check that malloc doesn't return NULL, you have to free the memory
later, etc.
So I'd do:
char proNames[numPro][30]; // 28 characters for an int (usually 4 bytes long)
// should be more than enough
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
sprintf(proNames[i], "p%d", i);
}
Your removeProcessN would need to change as well:
void removeProcessN(int numElem, int elem, int dim, char (*array)[dim]) {
for(int i = elem; i < numElem - 1; ++i)
strcpy(array[i], array[i+1]);
array[numElem - 1][0] = 0; // setting last element to empty string
}
Note that I moved the array argument at the last position, otherwise numElem
is not known and the compiler would return an error.
And now you can call it like this:
removeProcessN(elemNum, numPro, 30, proNames);
The 30 comes from the char proNames[numProp][30]; declaration.
I'd like to comment on the last line of your function removeProcessN:
//End by setting the pointer of array to the temparray
array = temparray;
That is not correct, first because temparray is local variable and ceases to
exist when the function returns. And array is local variable in the function,
so changing it doesn't affect anybody.
The alternative with memory allocation would look like this:
char *proNames[numPro];
//Retrieves process time from user
for (i = 0; i < numPro; i++){
printf("Enter execution time for process %d: ", i);
scanf("%d", proTime + i);
int len = snprintf(NULL, 0, "p%d", i);
proNames[i] = malloc(len + 1);
if(proNames[i] == NULL)
{
// error handling, free the previously allocated
// memory, and return/exit
}
sprintf(proNames[i], "p%d", i);
}
and removeProcessN:
void removeProcessN(char **array, int numElem, int elem) {
char *to_remove = array[elem];
for(int i = elem; i < numElem - 1; ++i)
array[i] = array[i+1];
free(to_remove);
array[numElem - 1] = NULL; // setting last element to NULL
// makes freeing easier as
// free(NULL) is allowed
}
And the way you originally called the removeProcessN would be OK.
If you eventually call removeProcessN for all processes, then all the memory
should be freed because removeProcessN frees it. If there are some elements
that remain in the array, then you have to free them later.
OP posted in the comments
My theory was that temparray would be a pointer to an array so I could just remove an index from the main array.
So when I say array = temparray, the pointer for array points to temparray. I know it worked for removeProcess. Is it different for strings?
The array = temparray also has no effect in removeProcess, array is still
a local variable and changing where it points to has no effect at all, because
you are changing a local variable only.
Besides the code is wrong:
int numElem = sizeof(array) / sizeof(int);
this only works for pure arrays, it does not work for pointers because
sizeof(array) returns you the size that a pointer of int needs to be stored.
Like the other function, you need to pass the site the array to the function.
If you say that this function worked, then just only by accident, because it
yields undefined behavior. By incorrectly calculating the number of elements,
temparray will have the wrong size, so here temparray[i] = array[i]; you may
access beyond the bounds which leads to undefined behaviour. Undefined behaviour
means that you cannot predict what is going to happen, it could be anything from
crashing to formatting your hard drive. Results that result from undefined
behaviour are useless.
And again array = temparray; just changes where the local variable array is
pointing, the caller of removeProcess doesn't see that.
The correct version would be:
int removeProcess(int *array, int elem, int numElem) {
if(array == NULL)
return 0;
// nothing to do if the elemnt to be removed is
// the last one
if(elem == numElem - 1)
return 1;
// overwriting the memory, because memory
// regions overlap, we use memmove
memmove(array + elem, array + elem + 1, numElem - elem - 1);
return 0;
}
So, to make it clear:
Let's look at this code:
void sum(int *array, size_t len);
{
int c[len];
array = c;
}
void bar(void)
{
int x[] = { 1, 3, 5 };
size_t len = sizeof x / sizeof *x;
sum(x, sizeof x / sizeof *x);
printf("x[0] = %d, x[1] = %d, x[2] = %d\n", x[0], x[1], x[2]);
}
sum has only a copy of the pointer you've passed in bar, so from bar's
point of view, sum changed the copy, so bar will print
x[0] = 1, x[1] = 3, x[2] = 5.
But if you want that the caller sees any change, then you to access through the
pointer:
void sum(int *array, size_t len)
{
int c[len];
for(size_t i = 0; i < len; ++i)
array[i] += 10;
array = c;
}
With this version bar would print x[0] = 11, x[1] = 13, x[2] = 15 and
and array = c will have no effect on bar.

dynamically increase size of array (int*) in c

i want to dynamically add numbers to an array in c. My idea is to just allocate a new array with size + 1, add the number, free the root array and change the pointer from the temp to the root array. Like this:
void addNumber(int* a, int* size, int number)
{
*size = *size + 1;
int* temp = (int*)(calloc(*size, sizeof(int)));
int i, j = 0;
for(i = 0; i < *size-1; i++) {
if(a[i] < number) {
printf("add ai");
temp[j] = a[i];
j++;
} else {
printf("add number");
temp[j] = number;
}
}
if(j != *size) {
printf("add new number");
temp[j] = number;
}
free(a);
a = temp;
}
int main(int argc, char* argv[])
{
int n = 10;
int* a;
int size = 1;
a = (int*) (calloc(1, sizeof(int)));
a[0] = 1;
if(!contains(a, size, 2)) {
addNumber(a, &size, 2);
}
printArray(a,size);
return 0;
}
The problem is that in the addNumber function the code works and the *a has the right values of the new array. But in the main function the array *a has the values 1,0. So the new inserted value 2 is not added. Why? Can't get the reason.
To dynamically change the array size, you can use the realloc() routine. Apart from being eaiser to use, it can be faster than the approach of calling free() and malloc() sequentially.
It is guaranteed the reallocated block will be populated with the content of the old memory block.
The problem is that in the addNumber function the code works and the *a has the right values of the new array
There are two major flaws in your code. The first is that you your addNumber() routine doesn't return the newly allocated memory block (thus it is being leaked), you should either use double pointer or return the new block as function result.
And the second one results from the first - after a has been freed, you continue to write to it.
If you prefer to stick to your current approach, this modified code should work:
void addNumber(int** a, int* size, int number)
{
*size = *size + 1;
int* temp = (int*)(calloc(*size, sizeof(int)));
int i, j = 0;
for(i = 0; i < *size-1; i++) {
if((*a)[i] < number) {
printf("add ai");
temp[j] = (*a)[i];
j++;
} else {
printf("add number");
temp[j] = number;
}
}
if(j != *size) {
printf("add new number");
temp[j] = number;
}
free(*a);
*a = temp;
}
int main(int argc, char* argv[])
{
int n = 10;
int* a;
int size = 1;
a = (int*) (calloc(1, sizeof(int)));
a[0] = 1;
if(!contains(a, size, 2)) {
addNumber(&a, &size, 2);
}
printArray(a,size);
return 0;
}
What you're looking for is realloc(). It can be used to grow or shrink memory while retaining its contents.
/* array is now sizeof(int) * new_size bytes */
array = realloc(array, sizeof(int) * new_size);
realloc() might change the existing memory allocation, or it might allocate a whole new block of memory. This is why it's important to reassign the result back to the thing being reallocated.
But if addNumber() reallocates the array by making new memory, main() won't know it. This is for the same reason this doesn't work.
void incrementNumber(int num) {
num = num + 1;
}
int num is a number that gets passed by value. If you want it to be reflected in the caller, you need to pass it as a pointer.
void incrementNumber(int *num) {
*num = *num + 1;
}
Pointers are the same way. They're still numbers. int *a passes a pointer by value. If you change a in addNumber it won't be seen by the caller. Just like before, you need to pass it as a pointer. A pointer to a pointer used like this is known as a double pointer.
void addNumber( int **array_ptr, size_t *array_size, size_t type_size, int number ) {
/* Increment the size and make sure that bubbles up */
*array_size = *array_size + 1;
/* realloc might grow the memory, or it might allocate new memory
either way, assign the result back to its original variable
by dereferencing the double pointer.
*/
*array_ptr = realloc(*array_ptr, *array_size * type_size);
/* Since it's a double pointer, we have to first dereference it before using
it as an array */
(*array_ptr)[*array_size - 1] = number;
}
(Note that I also pass in the sizeof the elements in the array, that can't be assumed).
This is called by passing a pointer to the array.
addNumber(&a, &size, sizeof(int), 5);
After that, everything is the same.
for( int i = 0; i < size; i++ ) {
printf("%d ", a[i]);
}
puts("");
Eventually you'll want to improve this by having the array, size, and type in a struct so you can pass that around in a neat package.
typedef struct {
int *array;
size_t size;
} IntArray;
This is great to do as an exercise, you'll learn a lot and kick a lot of bad habits about static memory. But doing dynamic data structures correctly and efficiently is difficult (for example, allocating one extra slot at a time is very inefficient).
There are many, many libraries out there which provide such dynamic structures. So continue with this as an exercise, but for real code use a library such as Gnome Lib.
Why? Can't get the reason.
That's because you are modifying the value of a locally in addNumber. That does not change the value of a in main.
In order for main to have access to the newly allocated memory, you need to change addNumber to return the newly allocated pointer.
int* addNumber(int* a, int* size, int number){
...
return a;
}
and then change main to:
if(!contains(a, size, 2)){
a = addNumber(a, &size, 2);
// Assign to a the new pointer value.
}
Your 'a' in main is already a pointer, passing it to a function passes a copy of it. What you have to do is - pass the adress '&a' and receive it in funtion as double pointer '**a' and inside the function, use dereference to get values inside array ( like *a[i] and free(*a).
Change the last line to 'return temp' and collect it in main as a=addnumber(&a,&size,2);
By the way, instead of going through all these hassle why don't you just use realloc() function. It increases the size of array dynamically. After using realloc you can just add the new number at the last index.

realloc(): invalid next size in simple program. Can't figure out the issue [duplicate]

Disclaimer: This is homework. I am attempting it and do not expect or want anyone to do it for me. Just a few pointers (hehe) where I'm going wrong would be appreciated.
The homework requires me to create an int* array that holds 10 elements, and then attempt to insert a million ints into it. Each insertion checks if the array needs to be resized, and if it does, I increase it's size so it can hold one more element.
When I insert 10,000 elements, it works fine, but if I try 100,000 elements, I get the following error:
*** glibc detected *** ./set2: realloc(): invalid old size: 0x00000000024dc010 ***
This is the code I'm running. I've commented it so it's easily readable.
void main()
{
//begin with a size of 10
int currentsize = 10;
int* arr = malloc(currentsize * sizeof(int));
int i;
//initalize with all elements set to INT_MAX
for(i = 0; i < currentsize; i++) {
arr[i] = INT_MAX;
}
// insert random elements
for(i = 0; i < 100000; i++) {
currentsize = add(rand() % 100,arr,currentsize);
}
free(arr);
}
/*
Method resizes array if needed, and returns the new size of the array
Also inserts the element into the array
*/
int add(int x, int* arr, int size)
{
//find the first available location
int newSize = size;
int i;
for(i = 0; i < size; i++) {
if (arr[i] == INT_MAX)
break;
}
if (i >= size) {
//need to realloc
newSize++;
arr = realloc(arr, newSize * sizeof(int) );
}
arr[i] = x;
return newSize;
}
The error is probably because you properly use realloc to change arr in the function add, but this modified value is lost when add returns. So the next call to add will receive the old, now bad value.
Also I can't understand why you're using a the for loop to search. You know you want to add at the last element, so why search? Just reallocate the array and plug the new value in the new slot.
Incidentally I'm pretty sure your teacher is trying to get you to see that reallocating for each member causes an asymptotic run time problem. Most implementations of realloc will do a lot of copying with this algorithm. This is why real programs grow the array size by a factor greater than one (often 1.5 or 2) rather than by fixed amounts.
The usual idiom is to abstract the variable size array in a struct:
typedef struct array_s {
int *elts;
int size;
} VARIABLE_ARRAY;
void init(VARIABLE_ARRAY *a)
{
a->size = 10;
a->elts = malloc(a->size * sizeof a->elts[0]);
// CHECK FOR NULL RETURN FROM malloc() HERE
}
void ensure_size(VARIABLE_ARRAY *a, size_t size)
{
if (a->size < size) {
// RESET size HERE TO INCREASE BY FACTOR OF OLD SIZE
// size = 2 * a->size;
a->elts = realloc(size * sizeof a->elts[0]);
a->size = size;
// CHECK FOR NULL RETURN FROM realloc() HERE
}
}
// Set the i'th position of array a. If there wasn't
// enough space, expand the array so there is.
void set(VARIABLE_ARRAY *a, int i, int val)
{
ensure_size(a, i + 1);
a->elts[i] = val;
}
void test(void)
{
VARIABLE_ARRAY a;
init(&a);
for (int i = 0; i < 100000; i++) {
set(&a, i, rand());
}
...
}
I would pass arr to add() as a pointer (to a pointer), so that it can be modified inside of add()
int add(int x, int** arr, int size)
{
// ...
*arr = realloc(*arr, newSize * sizeof(int) );
}
And calling it....
currentsize = add(rand() % 100, &arr, currentsize);
Note that that your code (and my suggested change) is not doing any error checking. You should be checking the return value of malloc and realloc for NULL.

realloc invalid old size

Disclaimer: This is homework. I am attempting it and do not expect or want anyone to do it for me. Just a few pointers (hehe) where I'm going wrong would be appreciated.
The homework requires me to create an int* array that holds 10 elements, and then attempt to insert a million ints into it. Each insertion checks if the array needs to be resized, and if it does, I increase it's size so it can hold one more element.
When I insert 10,000 elements, it works fine, but if I try 100,000 elements, I get the following error:
*** glibc detected *** ./set2: realloc(): invalid old size: 0x00000000024dc010 ***
This is the code I'm running. I've commented it so it's easily readable.
void main()
{
//begin with a size of 10
int currentsize = 10;
int* arr = malloc(currentsize * sizeof(int));
int i;
//initalize with all elements set to INT_MAX
for(i = 0; i < currentsize; i++) {
arr[i] = INT_MAX;
}
// insert random elements
for(i = 0; i < 100000; i++) {
currentsize = add(rand() % 100,arr,currentsize);
}
free(arr);
}
/*
Method resizes array if needed, and returns the new size of the array
Also inserts the element into the array
*/
int add(int x, int* arr, int size)
{
//find the first available location
int newSize = size;
int i;
for(i = 0; i < size; i++) {
if (arr[i] == INT_MAX)
break;
}
if (i >= size) {
//need to realloc
newSize++;
arr = realloc(arr, newSize * sizeof(int) );
}
arr[i] = x;
return newSize;
}
The error is probably because you properly use realloc to change arr in the function add, but this modified value is lost when add returns. So the next call to add will receive the old, now bad value.
Also I can't understand why you're using a the for loop to search. You know you want to add at the last element, so why search? Just reallocate the array and plug the new value in the new slot.
Incidentally I'm pretty sure your teacher is trying to get you to see that reallocating for each member causes an asymptotic run time problem. Most implementations of realloc will do a lot of copying with this algorithm. This is why real programs grow the array size by a factor greater than one (often 1.5 or 2) rather than by fixed amounts.
The usual idiom is to abstract the variable size array in a struct:
typedef struct array_s {
int *elts;
int size;
} VARIABLE_ARRAY;
void init(VARIABLE_ARRAY *a)
{
a->size = 10;
a->elts = malloc(a->size * sizeof a->elts[0]);
// CHECK FOR NULL RETURN FROM malloc() HERE
}
void ensure_size(VARIABLE_ARRAY *a, size_t size)
{
if (a->size < size) {
// RESET size HERE TO INCREASE BY FACTOR OF OLD SIZE
// size = 2 * a->size;
a->elts = realloc(size * sizeof a->elts[0]);
a->size = size;
// CHECK FOR NULL RETURN FROM realloc() HERE
}
}
// Set the i'th position of array a. If there wasn't
// enough space, expand the array so there is.
void set(VARIABLE_ARRAY *a, int i, int val)
{
ensure_size(a, i + 1);
a->elts[i] = val;
}
void test(void)
{
VARIABLE_ARRAY a;
init(&a);
for (int i = 0; i < 100000; i++) {
set(&a, i, rand());
}
...
}
I would pass arr to add() as a pointer (to a pointer), so that it can be modified inside of add()
int add(int x, int** arr, int size)
{
// ...
*arr = realloc(*arr, newSize * sizeof(int) );
}
And calling it....
currentsize = add(rand() % 100, &arr, currentsize);
Note that that your code (and my suggested change) is not doing any error checking. You should be checking the return value of malloc and realloc for NULL.

Passing pointer variables through functions in C

I'm getting some strange behaviour here. Any help would be great.
I start like this:
int *event_positions = (int *) malloc(1 * sizeof(int)); // let us start with 1 and then add more within the method. This should continue until we have all the flags we want.
int number_of_flags = event_extractor(vocal_data, size, event_positions);
// HERE I WOULD LIKE TO USE THE VALUES OF event_positions BUT THE ARE WEIRD I.E. THEY DON'T MATCH THE VALUES BEING PRINTED IN THE LAST METHOD.
Event extractor then passes on the variable to another method. Simplified this looks like this:
int event_extractor (int *audio_samples, unsigned int size_of_audio ,int *event_flags)
{
int number_of_flags = apply_threshold (lopass_samples, length, event_flags);
// PRINT ARRAY event_flags HERE
// VALUES ARE INCORRECT AND WEIRD
}
The last method:
int apply_threshold (int *audio_samples, unsigned int size_of_audio, int *event_flags)
{
// DO SOME STUFF HERE.
// PRINT THE ARRAY WHICH SHOW THE CORRECT VALUES.
}
I hope this is clear. Basically I have an array which I pass as an argument and am having trouble accessing those values after the method has finished.
EDIT 1
First File:
int *event_positions = (int *) malloc(1 * sizeof(int)); // let us start with 1 and then add more within the method. This should continue until we have all the flags we want.
int number_of_flags = event_extractor(vocal_data, size, event_positions);
Second File:
int apply_threshold (int *audio_samples, unsigned int size_of_audio, int *event_flags)
{
int flag = 0; // this will be the number of flags that I have
bool run = true; // this will make sure that a minimum amount of time passes before I grab another flag. It's a guard.
int counter = 0; // this is the counter for the above guard.
printf("\n\nCURRENT MINIMUM TIME: 20100 SAMPLES \n\n");
// event_flags[0] = 1; // this first one is a dud. within the loop we will automatically start adding flags
int threshold = calculate_threshold_value(audio_samples, size_of_audio);
printf("\n\n this is the threshold %d \n\n", threshold);
int length = (int)size_of_audio;
for (int i = 0; i < length; i++)
{
if (audio_samples[i] > threshold && run)
{
// ** is this realloc working ?
event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1)); // reallocate the size of the array
event_flags[flag] = i;
// printf("FLAG CREATED! %i\n ", i);
printf("EVENT FLAG %i %i\n",flag, event_flags[flag] );
flag++;
run = false;
}
if (!run) {
counter++;
if (counter > 20100) { // hardcode minimum size for now.
counter = 0;
run=true;
}
}
}
printf("\n\n\n NUMBER OF EVENTS --- %d\n", flag);
for (int i = 0; i < flag; i++) {
printf("FLAG %i -- %d\n", i, event_flags[i]);
}
printf("\nFIVE samples before and after my second flag: \n 0 should indicate a reach in the threshold\n");
for (int i = 0; i <10 ; i++) {
printf("VOCAL SAMPLE %i %i \n", i-5,audio_samples[event_flags[1]+i-5] );
}
return flag;
}
EDIT 2
I've updated my code according to Erik's model. My loop now looks like this
if (audio_samples[i] > threshold && run)
{
// ** is this realloc working ?
// event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1));
*event_flags = (int*)realloc(*event_flags, sizeof(int) * (flag+1)); // reallocate the size of the array
*event_flags[flag] = i;
// printf("FLAG CREATED! %i\n ", i);
printf("EVENT FLAG %i %i\n",flag, *event_flags[flag] );
flag++;
run = false;
}
And now I'm getting an error that looks like this. Any ideas?
Are you reallocating event_flags in apply_threshold? If so, you need to let the caller get the updated pointer back.
Something like:
int apply_threshold (int *audio_samples, unsigned int size_of_audio, int **event_flags) {
*event_flags = realloc ...
}
...
int number_of_flags = apply_threshold (lopass_samples, length, &event_flags);
EDIT: In response to updated question:
event_flags = (int*)realloc(event_flags, sizeof(int) * (flag+1)); // reallocate the size of the array
This changes the local copy of the event_flags pointer. Caller will not see the change. Use the method I described above.
EDIT2: More detailed sample.
void foo(int * v) {
v = 0; // The local copy of main's myvar is now 0. main's actual myvar is unchanged
}
void bar(int ** v) {
*v = 0; // Main's myvar is now 0, we have a pointer to it and can modify it.
}
int main() {
int * myvar = (int *) malloc(1); // Allocate 1 byte and make myvar point at this byte.
foo(myvar); // Call foo, passing a *copy of* myvar, which also points at the allocated byte
bar(&myvar); // Call bar, passing a *pointer to* myvar, which again points to the allocated byte
}
EDIT3: In response to new question.
Is your "length" the number of ints or number of bytes? You're treating it as number of ints, which could cause your error if it really is number of bytes.
You need to pass a pointer to pointer or a reference to pointer. A realloc might be moving your memory to another position and the caller won't notice.
realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, then the
call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to mal‐
loc(), calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.

Resources