I was trying to free a list of integers starting from the head and knowing how many elements are in the list, but I am getting an invalid pointer error.
The code is the following:
int* factors = job_factorization(number, size);
printf("Thread %d: job terminated. Result: ", params->thread_id);
int* tmp;
for (int i = 0; i < *size; i++){
printf("%d ", *factors);
tmp = factors;
factors++;
free(tmp);
}
int *job_factorization(int number, int *size) {
int *factors;
int array_size = SIZE_INCREASE;
int factor = 2;
if (number < 2)
return NULL;
factors = (int *) malloc(sizeof(int) * SIZE_INCREASE);
*size = 0;
while (number != 1) {
// check whether the number is divisible by the factor
if (number % factor == 0) {
// if there is no more space available, resize the array
if (*size == array_size) {
array_size += SIZE_INCREASE;
factors = (int *) realloc(factors, sizeof(int) * array_size);
}
// add the factor to the list of prime factors
factors[*size] = factor;
(*size)++;
number = number / factor;
}
else {
// if not a factor, move to the next prime number
factor = next_prime(factor);
}
}
return factors;
}
Does anyone have any idea of the reason why this is happening? I have no clue about it (the function job_factorization works correctly)
job_factorization makes one malloc (and a number of reallocs). To the user of job_factorization this looks like one allocation only and that only needs one free. Like this:
int* factors = job_factorization(number, size);
for (int i = 0; i < *size; i++) {
printf("%d ", factors[i]); // don't increase factors in the loop
}
free(factors); // one free
When you use realloc it replaces the old allocation, so if you first malloc for 1 element, then realloc for 2 elements, the result is one allocation with 2 elements - which requires one free only.
Related
thanks for taking the time in reading this.
In my question a "vector" is defined as a 1D dimensional array of integers.
Therefore an array of vectors would be a 2D dimensional array in which every vector can be of a different length.
I'm asked to use:
int** vectors- the 2D array
int size -an integer that represents how many vectors exist inside **vectors
int* sizes-a 1D array of integers that represents the length of the vectors
for example,for:
vectors = {{4,3,4,3},{11,22,33,44,55,66},NULL,{5},{3,33,333,33,3}}.
size is 5 (there are 5 vectors inside vectors).
sizes is {4,6,0,1,5} (4 is the length of the first vector and so on).
size is inputted by the user at the beginning of main() and **vectors&*sizes are dynimacilly allocated with size's value.
I'm asked to write the function:
int init(int ***vectors, int **sizes, int size) which initializes **vectors to be an array of NULLs and *sizes to be an array of zeros.
I came up with this code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int init(int*** vectors, int** sizes, int size)
{
int i, k,j;
printf("check\n");
*vectors = (int**)malloc(size * sizeof(int*));
if (*vectors == NULL)
return 0;
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
printf("check 2\n");
for (k = 0; k<size; k++)
{
if (*(vectors+k) != NULL)
printf("didn't work\n");
else
printf("current is null\n");
}
*sizes= (int*)malloc(size * sizeof(int));
if (*sizes == NULL)
return 0;
for (j= 0; j < size; j++)
{
*(sizes + j) = 0;
printf("%d ", *(sizes + j));
}
printf("\n");
return 1;
}
int main()
{
int size, i;
int** vectors = NULL;
int* sizes = NULL;
printf("\nPlease enter an amount of vectors:\n");
scanf("%d", &size);
printf("%d\n", init(&vectors, &sizes, size));
printf("size is %d now\n", size);
// for (i = 0; i < size; i++)
// printf("%d ", *(sizes+i));
printf("check 3\n");
free(sizes);
free(vectors);
printf("check 4\n");
printf("check 5\n");
return 0;
}
forgot to mention that init returns 0 if it fails to allocate memory and 1 otherwise.
printing the "checks" was so I could see where the program fails.
the problem is that no matter what,after printing the last check (check 5)
the program fails.(Run-Time Check Failure #2)
if anyone could help me understand what I'm doing wrong I would HIGHLY appreciate it.
thanks alot for reading and have an amazing day.
edit:
i also printed the array sizes/vectors inside init just to see if it prints zeros/nulls,i don't actually need to do it.
One problem of OP's code is in the pointer arithmetic. Given:
int ***vectors;
*vectors = malloc(size * sizeof(int*));
This loop:
for (i = 0; i < size; i++)
{
*(vectors + i) = NULL;
}
Would iterate over the next unallocated pointer to pointer to pointer to int, while what the OP needs is
for (i = 0; i < size; i++)
{
*(*vectors + i) = NULL; // or (*vectors)[i] = NULL;
}
The same holds in the following loops, where *(sizes + j) is used instead of *(*sizes + j) (or (*sizes)[j]).
For example:
[1,2,3] -> [2,4,6]
[9,1] -> [1,8,2]
[6,7,5] -> [1,3,5,0]
I got this question on my first tech interview yesterday (did it in C because that's my best language, so a C answer would be help more) and completely blanked :(
This is what I was thinking:
Start at the end of the array and keeping moving left
At every arr[i], multiply by 2 and see if there're 2 digits (if arr[i]/10 != 0) and if there is a left most digit, carry it over to arr[i-1] as long as a[i-1] != NULL.
I just could not figure out how to actually do this in C. I had something like:
int* multTwo(int* arr, int len) {
int *newarr; // I know i have to malloc, but not sure what size because
// wouldnt the size depend on the new number's size?
int temp, i;
for (i=len-1; i>=0; i--) {
temp = arr[i]*2;
newarr[i] = temp%2;
if(temp/10 != 0)
newarr[i-1] = temp/2;
}
return newarr;
}
But there are a lot of bugs in my code. Is there a better way or am I on the right track?
Some pseudo code. The main idea is to show the depth of C knowledge as part of the interview, not Code golf.
What signature?
// arr is not changed, use `const`
// array indexing best done with `size_t`
int* multTwo(const int* arr, size_t len) {
Size needed and show error handling. Maybe also detect arr == NULL when len > 0
need = len;
// if lead element is 5 or more, add 1.
// Error if element is not in 0-9 range
Allocate memory. Allocating to size of variable de-referenced type is less error prone, easier to review and maintain than coding the variable type. Showing maintenance concerns during a C interview is a good thing. Think if later code changed to unsigned char* multTwo(const unsigned char* arr, size_t len) {, no need to change newarr = malloc(sizeof *newarr * need).
newarr = malloc(sizeof *newarr * need)
Check allocation. An allocation of 0 is OK to return NULL. Yet maybe this routine should still allocate 1 byte, a tad wasteful, to insure a NULL return is an error. Discussing issues like with the interviewer is good. Shows you want to clearly understand the customer's need not just in the meat of the function, but the corner cases.
if (newarr == NULL && need > 0) fail()
Loop though and populate the new array much like OP coded with meaningful variable names and using unsigned array indexing.
size_t arr_i=len;
size_t newarr_i=need;
int carry = 0;
while (arr_i > 0)
sum = arr[--arr_i]*2 + carry;
newarr[--newarr_i] = sum%10;
carry = sum/10;
}
if (carry) {
newarr[--newarr_i] = carry;
}
Return newarr
Best I can think in a short time, like an interview
#include <stdio.h>
#include <stdlib.h>
void invert (int *head, int *tail)
{
int temp;
if (head < tail)
{
temp = *head;
*head = *tail;
*tail = temp;
invert(++head, --tail);
}
}
int* multTwo(int* arr, size_t len)
{
int value = 0;
int n_digits =0 ;
// CONVERT THE ARRAY TO NUMBER
while(len--)
{
value += *arr;
value *=10;
arr++;
}
value /= 10;
// DOUBLE THE NUMBER
value *= 2;
// CONVERT IT TO BUFFER
int *digits = malloc(sizeof(*digits));
while ((value>0) && (digits != NULL))
{
digits[n_digits++] = value%10;
value /= 10;
digits = realloc( digits, sizeof(*digits) * (n_digits+1) );
}
if (digits != NULL)
{
invert(digits, &digits[n_digits-1]);
printf("[ ");
for (int i=0; i<n_digits; i++)
printf("%d, ", digits[i]);
printf("]\n");
}
return digits;
}
int main(void)
{
int array[] = {6,7,5};
multTwo(array, sizeof(array)/sizeof(array[0]));
return 0;
}
I would start by looking to see if either the first digit in arr is 5 or more to check if the newarr array needs to be 1 larger than the original array.
So something like this for initialization:
int* newarr;
int newlen;
if (*arr >= 5)
newlen = len + 1;
else
newlen = len;
newarr = (int*)malloc(sizeof(int) * newlen);
memset(newarr, 0, newlen); //initialize all newarr values to 0
Now obviously we have to do our multiplication now. To get the 1's digit we do use the modulo operator %, and to get the 10's digit we use the division operator /. Of course we only need to do the division if our multiplied value is 10 or greater. So our loop to populate newarr will look something like this:
int i, temp;
for (i = 1; i <= len; i++) {
temp = *(arr + i - 1) * 2;
if (temp < 10) {
*(newarr + i - 1) += temp;
}
else {
*(newarr + i - 1) += temp / 10; //inset 10's digit
*(newarr + i) += temp % 10; //inset 1's digit
}
}
So our full function ends up being
#include <stdlib.h>
#include <string.h>
int* multTwo(int* arr, int len)
{
int* newarr;
int newlen;
if (*arr >= 5)
newlen = len + 1;
else
newlen = len;
newarr = (int*)malloc(sizeof(int) * newlen);
memset(newarr, 0, newlen); //initialize all newarr values to 0
int i, temp;
for (i = 1; i <= len; i++) {
temp = *(arr + i - 1) * 2;
if (temp < 10) {
*(newarr + i - 1) += temp;
}
else {
*(newarr + i - 1) += temp / 10; //insert 10's digit
*(newarr + i) += temp % 10; //inset 1's digit
}
}
return newarr; //don't forget to free once you're done with newarr!
}
I am writing a function that creates a set of primes numbers less than the limit passed to it. For some reason, I am having trouble getting the memory-management right; I keep getting "Segmentation Fault: 11." Here is the code:
#include <stdio.h>
#include <stdlib.h>
void getPrimes(int** primes, int* limit);
int main(void){
int primeLimit = 99;
int* primes;
getPrimes(&primes, &primeLimit);
//Do stuff
free(primes);
return 0;
}
void getPrimes(int** primes, int* limit){
int multiplier; //Number used to multiply by to find numbers that do have factors
int multiple; //Stores the current multiple
int numPrimes = 0; //Number of primes (returned to caller)
int count = 0;
int* marked = (int*)malloc(*limit * sizeof(int)); //Initialize memory and sets it to 0
memset(marked, 0, *limit);
marked[0] = 1; //Set 0 and 1 to be not prime
marked[1] = 1;
for(int base = 2; base < *limit; base++){//Go through each number and mark all its multiples, start with 2
if(!marked[base]){ //If base is already marked, its multiples are marked
multiplier = 2; //Start multiple at 2
multiple = base * multiplier; //Set first multiple for loop
while(multiple < *limit){//Mark each multiple until limit reached
marked[multiple] = 1;
multiplier++;
multiple = base * multiplier;
}
}
}
//Do a sweep to get the number of primes
for(int num = 2; num < *limit; num++){//Go through each number and check if marked
if(!marked[num]){ //Number is prime
numPrimes++; //Increase count of primes if number is prime
}
}
*limit = numPrimes; //update limit to the number of primes
*primes = (int*)malloc(numPrimes * sizeof(int)); //Allocate memory for primes
//Now actually put the primes in the array
printf("Number of Primes: %d\n\n", numPrimes);
for(int num = 2; num < *limit; num++){//Go through each number and check if marked
printf("Num: %d, ", num); //Print it for debugging
printf("Count: %d\n", count);
if(!marked[num]){ //Number is prime
*primes[count] = num; //Append to primes list (returned to caller)
count++; //Increase count of primes if number is prime
}
}
free(marked); //Free the memory used to mark multiples
return;
}
The origin of your problem is :
*primes[count] = num;
It makes an attempt to reach primes[count] and it fails as soon as count>0.
To correct this :
(*primes)[count] = num;
There are some other points to get a correct result :
To initialize marker, do memset(marked, 0, *limit*sizeof(int));. The function memset() comes from string.h : it sets the first *limit*sizeof(int) bytes
In the second loop, for(int num = 2; num < *limit; num++){, *limit has changed, it is not the length of marked anymore. To remove this issue the initial value of *limit may be stored in formerlimit.
Here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void getPrimes(int** primes, int* limit);
int main(void){
int primeLimit = 99;
int* primes;
getPrimes(&primes, &primeLimit);
//Do stuff
free(primes);
return 0;
}
void getPrimes(int** primes, int* limit){
int multiplier; //Number used to multiply by to find numbers that do have factors
int multiple; //Stores the current multiple
int numPrimes = 0; //Number of primes (returned to caller)
int count = 0;
int formerlimit=*limit;
int* marked = (int*)malloc(*limit * sizeof(int)); //Initialize memory and sets it to 0
memset(marked, 0, *limit);
marked[0] = 1; //Set 0 and 1 to be not prime
marked[1] = 1;
for(int base = 2; base < *limit; base++){//Go through each number and mark all its multiples, start with 2
if(!marked[base]){ //If base is already marked, its multiples are marked
multiplier = 2; //Start multiple at 2
multiple = base * multiplier; //Set first multiple for loop
while(multiple < *limit){//Mark each multiple until limit reached
marked[multiple] = 1;
multiplier++;
multiple = base * multiplier;
}
}
}
//Do a sweep to get the number of primes
for(int num = 2; num < *limit; num++){//Go through each number and check if marked
if(!marked[num]){ //Number is prime
numPrimes++; //Increase count of primes if number is prime
}
}
*limit = numPrimes; //update limit to the number of primes
*primes = (int*)malloc(numPrimes * sizeof(int)); //Allocate memory for primes
//Now actually put the primes in the array
printf("Number of Primes: %d\n\n", numPrimes);
for(int num = 2; num < formerlimit; num++){//Go through each number and check if marked
printf("Num: %d, ", num); //Print it for debugging
printf("Count: %d\n", count);
if(!marked[num]){ //Number is prime
(*primes)[count] = num; //Append to primes list (returned to caller)
count++; //Increase count of primes if number is prime
}
}
free(marked); //Free the memory used to mark multiples
return;
}
multiplier is not necessary, it may be changed for multiple+=base;
If it fails on high numbers, think about overflows.
I am using realloc to allocated memory at runtime in dynamic array. Firstly, I allocated a memory with calloc with sizeof a random integer a. In my program, I have taken a=2. After that I want to store some 14 random values generated, so I have to resize the memory using realloc. I am doing the same in a for loop. FOr 1 iteration, realloc works but after that size doesnt increase and a error occurs "corruption in heap". I am not able to understand the problem. Pls help me if you can, in understanding where the problem is occuring and how to solve it.
Thanks a lot.
Below is my code:
j=j*a; //a=3
numbers = (int*) calloc(b, j); //b=14, no of elements I want to store
printf("Address:%p\n",numbers);
if (numbers == NULL)
{
printf("No Memory Allocated\n");
}
else
{
printf("Initial array size: %d elements\n", a);
printf("Adding %d elements\n", b);
}
srand( (unsigned) time( NULL ) );
for(count = 1; count <= b ; count++)
{
if(i <= j)
{
numbers[count] = rand() % 100 + 1;
printf( "Adding Value:%3d Address%p\n", numbers[count],numbers[count] );
i++;
}
if (i > j)
{
printf("Increasing array size from %d bytes to %d bytes\n",j,j*a);
j=j*a;
numbers = (int*) realloc(numbers,j);
printf("Address:%p\n",numbers);
if(numbers == NULL)
{
printf("No Memory allocated\n");
}
}
}
free(numbers);
return 0;
}
The initial array length (length and size are not the same) is b, not a.
Adding b elements? I don't think you are.
Arrays are zero-based in C. You loop should be for(count=0; count<b ; count++).
count is a terrible name for a loop variable. count should hold the number of elements and not be a loop variable.
It's hard to imagine what j could be. Since you use it as the element size in your call to calloc it ought be at least be a multiple of 4, the size of in int. What is it?!
The realloc doesn't seem to bear any relation to the calloc.
I'm sure there are lots of other problems. If you want more help then a clear statement of what your goal is would be required.
EDIT
It sounds like you want something like this:
int capacity = 10;
int count = 40;
int i;
int* array = (int*)malloc(capacity*sizeof(int));
for (i=0; i<count; i++)
{
if (i==capacity)
{
capacity *= 2;
array = (int*)realloc(array, capacity*sizeof(int));
}
array[i] = RandomIntInRange(1, 100);
}
free(array);
Notes:
No error checking. In production code you would check that the allocations succeeded, and the realloc done this way would leak if it failed. But there's no point confusing the message with error checking when you are still at this level of understanding.
No reading input - you can do that.
No writing output - you can do that.
The integer "j" is not initialized in your code, resulting in a = 0 * 3, meaning a will be zero and no memory will be allocated. The segfault is due to you not handling that numbers is NULL. Change to and set j to something meaningful
#include <stdlib.h>
#include <stdio.h>
void
main (int argc, char *argv[])
{
int a = 3;
int j = 1 * a; //a=3
int b = 14;
int *numbers = calloc (b, j); //b=14, no of elements I want to store
int count = 0, i = 0;
printf ("Address:%p\n", numbers);
if (numbers == NULL)
{
printf ("No Memory Allocated\n");
return;
}
else
{
printf ("Initial array size: %d elements\n", a);
printf ("Adding %d elements\n", b);
}
srand ((unsigned) time (NULL));
for (count = 1; count <= b; count++)
{
if (i <= j)
{
numbers[count] = rand () % 100 + 1;
printf ("Adding Value:%3d Address%p\n", numbers[count],
&(numbers[count]));
i++;
}
if (i > j)
{
printf ("Increasing array size from %d bytes to %d bytes\n", j,
j * a);
j = j * a;
numbers = (int *) realloc (numbers, j);
printf ("Address:%p\n", numbers);
if (numbers == NULL)
{
printf ("No Memory allocated\n");
}
}
}
free (numbers);
}
I have a loop that involves a dynamically allocated array in C. For some reason it crashes after flag increments 7 times. This wasn't happening before I was reallocating the size of the array. Here is the code:
for (int i = 0; i < length-1; i++)
{
if (audio_samples[i] > threshold && run)
{
*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] );
if (flag >5) {
printf("%d\n", i);
}
flag++;
run = false;
}
Any ideas? Please keep in mind that the size of the array is indeed the same value as length. Here is an example of my errors:
EDIT 1
FILE ONE:
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);
FILE TWO:
float g_THRESHOLD_FACTOR = 2.3; // THIS INCREASES THE THRESHOLD VALUE.
int event_extractor (int *audio_samples, unsigned int size_of_audio ,int *event_flags)
{
int length = (int)size_of_audio;
// * * * * * * * * * * * * * * * * * *
// RECTIFY VALUES (MAKE ABSOLUTE) (MAKE ALL POSITIVE)
int *rectified_audio = (int *) malloc(length * sizeof(int)); // I took this line from wave header reader. The number is the number of samples of the hip hop track.
make_values_absolute(audio_samples, length, rectified_audio);
// If I convert to signed ints here would the method run more efficiently?
// * * * * * * * * * * * * * * * * * * * *
// LOW PASS FILTER
int *lopass_samples = (int *) malloc(length * sizeof(int)); // I took this line from wave header reader. The number is the number of samples of the hip hop track.
lopass(rectified_audio, length,0.5, lopass_samples);
int number_of_flags = apply_threshold (lopass_samples, length, &event_flags);
printf("\n\n\n NUMBER OF EVENTS AAAA --- %d\n", number_of_flags);
for (int i = 0; i < number_of_flags; i++) {
printf("FLAG %i -- %d \n", i, event_flags[i]);
}
return number_of_flags;
}
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;
printf("LENGTH OF VOCAL AUDIO %d \n", length );
for (int i = 0; i < length-1; i++)
{
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] );
if (flag >5) {
printf("%d\n", i);
}
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;
}
First you shouldn't cast the return of realloc.
Then if I suppose that the type of that variable is int*
*event_flags[flag] = i;
There is one * too much no?
Edit: After your remark on leaving out the cast.
So if your event_flags is effectively int**, you are really on the wrong track. Seeing your use, I would guess you simply want an array of int instead. If you do that and then
event_flags[flag] = i;
without * everywhere, your problem should go away.
If you really need that indirection, you'd have to allocate not only the array event_flags but also all the individual arrays these pointers are pointing to, with something like
for (size_t j = startvalue; j < something; ++j)
event_flags[j] = malloc(whatever);
I think you may have a problem with the precedence of the * operator versus the [] operator. That is *event_flags[flag] and (*event_flags)[flag] do not reference the same memory location. The first one correspond to **(event_flags + flag) (probably not accessible), while the second one correspond to *((*event_flags) + flag) (what you want).
So, you should rewrite your code to:
int** event_flags;
// ...
*event_flags = realloc(*event_flags, sizeof(int) * (flag + 1));
(*event_flags)[flag] = i;