I am trying to implement a sort function (counting sort, it is probably wrong):
void countingsortmm(int* numbers, int len, int min, int max) {
printf("Sorting %d integers with the min: %d and max: %d\n",len,min,max);
int countLen = max-min+1;
/* create an array to store counts for the occurences of a number. */
int* countingArray = (int*)malloc(countLen);
/* init all values to 0 */
for(int i = 0; i < countLen; i++) countingArray[i] = 0;
/* increment at indexes where a number occurs */
for(int i = 0; i < len; i++) countingArray[numbers[i]]++;
/* add previous indexes */
for(int i = 1; i < countLen; i++) countingArray[i] += countingArray[i-1];
/* Array where numbers will be places in a sorted order. */
int* sortedArray = (int*)malloc(len);
/* put numbers in proper place in new array and decrement */
for(int i = len-1; i >= 0; i--) sortedArray[countingArray[numbers[i]]--] = numbers[i];
/* copy contents of new sorted array to the numbers parameter. */
for(int i = 0; i < len-1; i++) numbers[i] = sortedArray[i];
free(sortedArray);
free(countingArray);
}
But I get the following error:
malloc: *** error for object 0x7f8728404b88: incorrect checksum for freed object - object was probably modified after being freed.
I get a break-point at int* sortedArray = (int*)malloc(len);.
I use malloc() twice to create two different arrays within the function and I free() them both at the end of the function when they are no longer needed. I do not explicitly modify or access their contents afterwards.
So what is causing this problem?
It means you're corrupting your heap. Perhaps you meant malloc(countLen * sizeof(int)); and malloc(len * sizeof(int));? malloc takes its size in bytes.
Related
I have a function named num_to_binary, which is used to convert a decimal number stored in the form of array. The prototype for this function num_to_binary is as below:
void num_to_binary(int *number_b, int size_of_number);
Here:
number_b is pointer to array which stores my number. For example, if I would like to convert the number 12345 to binary, then I will be storing 12345 in number_b as follows:
number_b[0] = 1
number_b[1] = 2
number_b[2] = 3
number_b[3] = 4
number_b[4] = 5
Also, size_of_number is the number of digits in the number (or it is the number of elements in the array number_b). So for the number 12345, size_of_number has the value 5.
Below is the full declaration of the function num_to_binary:
void num_to_binary(int *number_b, int size_of_number)
{
int *tmp_pointer = malloc(1 * sizeof(int));
int curr_size = 1;
int i = 0;
while(!is_zero(number_b,size_of_number))
{
if(i != 0)
{
curr_size += 1;
tmp_pointer = realloc(tmp_pointer, curr_size * sizeof(int));
}
if(number_b[size_of_number - 1] % 2 == 1)
{
tmp_pointer[i] = 1;
divide_by_2(number_b,size_of_number);
i = i + 1;
}
else
{
tmp_pointer[i] = 0;
divide_by_2(number_b,size_of_number);
i = i + 1;
}
}
int *fin_ans;
fin_ans = malloc(curr_size * sizeof(int));
for(int j = 0 ; j < curr_size; j++)
{
fin_ans[curr_size-1-j] = tmp_pointer[j];
}
}
In the above function:
tmp_pointer: It is initially allocated some memory using malloc(), and is used to store the reverse of the binary representation of the number stored in number_b
curr_size: It stores the current size of tmp_pointer. It is initially set to 1.
i: It is used to keep track of the while loop. It is also used to reallocation purpose, which I have explained a bit later.
is_zero(number_b, size_of_number): It is a function, which returns 1 if the number stored in number_b is 0, else it returns 1.
divide_by_2(number_b, size_of_number): It divides the number stored in number_b by 2. It does NOT change the size of the array number_b.
fin_ans: It is an integer pointer. Since the binary representation stored in the array tmp_pointer will be the reverse of the actual binary representation of the number, so fin_ans will store the correct binary representation of number by reversing the content of tmp_pointer.
Below is the how this function works :
First of all, tmp_pointer is allocated a memory equal to the
size of 1 int. So, now tmp_pointer can store an integer.
We now go into the while loop. The loop will terminate only
when the number stored in number_b equals 0.
Now, we check if i is equal to 0 or not. If it is not equal to
zero, then this means than the loops has been run atleast once, and
in order to store the next binary digit, we resize the memory
allocated to tmp_pointer so that it can store the next bit.
If the last digit of the number is odd, then that implies that the
corresponding binary digit will be 1, else it will be 0. The
if and else condition do this task. They also increment
i each time one of them is executed, and also divide the number by 2.
Now, we are out of the loop. It's time to reverse the binary number
stored in tmp_pointer to get the final answer.
For this, we create a new pointer called fin_ans, and allocate
it the memory which will be used for storing the correct binary
representation of the number.
The last for loop is used to reverse the binary representation
and store the correct binary representation in fin_ans.
The problem:
The code runs for small numbers such as 123, but for large numbers such as 1234567891, it gives a segmentation fault error. This can be checked by trying to print the digits stored in fin_ans.
I tried using GDB Debugger, and got to know that the reason for Segmentation Fault lies in the while loop. I am sure that the functions divide_by_2 and is_zero are not the reason for Segmentation Fault, since I have tested them thoroughly.
I also used DrMemory, which indicated that I am trying to access (read or write) a memory location which has not been allocated. Unfortunately, I am not able to figure out where the error lies.
I suspect realloc() to be the cause of Segmentation Fault, but I am not sure.
Apologies for such a long question, however, I would highly appreciate any help provided to me for this code.
Thanks in advance for helping me out !
There are multiple problems in the code:
you do not check for memory allocation failure
you forget to free tmp_pointer before leaving the function.
you allocate a new array fin_ans to reserve the array tmp_pointer and perform the reverse operation but you do not return this array to the caller, nor do you have a way to return its size. You should change the prototype to return this information.
if the number of zero, the converted number should probably have 1 digit initialized as 0, but you use malloc which does not initialize the array it allocates so tmp_pointer[0] is uninitialized.
you did not provide the code for is_zero() nor divide_by_two(). It is possible that bugs in these functions cause the segmentation fault, especially if the loop does not reach zero and memory is eventually exhausted during this infinite loop.
Here is a modified version:
int *num_to_binary(int *number_b, int size_of_number, int *binary_size) {
int i, j, curr_size;
int *p, *newp;
curr_size = 1;
p = malloc(1 * sizeof(int));
if (p == NULL)
return NULL;
p[0] = 0;
for (i = 0; !is_zero(number_b, size_of_number); i++) {
if (i != 0) {
curr_size += 1;
newp = realloc(p, curr_size * sizeof(int));
if (newp == NULL) {
free(p);
return NULL;
}
p = newp;
}
p[i] = number_b[size_of_number - 1] % 2;
divide_by_2(number_b, size_of_number);
}
for (i = 0, j = curr_size; i < j; i++)
int digit = p[--j];
p[j] = p[i];
p[i] = digit;
}
*binary_size = curr_size;
return p;
}
There is no need for multiple memory reallocations. Result memory buffer size could be easily evaluated as binary logarithm of the decimal input value. Calculation of the number binary representation could also be simplified:
//Transform binary array to actual number
int arr2int(int* pIntArray, unsigned int nSizeIn) {
if (!pIntArray || !nSizeIn)
return 0;
int nResult = 0;
for (unsigned int i = 0; i < nSizeIn; ++i)
nResult += pIntArray[i] * (int)pow(10, nSizeIn - i - 1);
return nResult;
}
int* int2bin(int* pIntArray, unsigned int nSizeIn, unsigned int* nSizeOut){
//0) Converting int array to the actual value
int nVal = arr2int(pIntArray, nSizeIn);
//1)Evaluating size of result array and allocating memory
if(!nVal)
*nSizeOut = 1;
else
*nSizeOut = (int)floor(log2(nVal)) + 1;
//2)Allocate and init memory
int* pResult = malloc(*nSizeOut);
memset(pResult, 0, *nSizeOut * sizeof(int));
//3) Evaluate binary representation
for (unsigned int i = 0; i < *nSizeOut; ++i){
int nBinDigit = (int)pow(2, i);
if (nBinDigit == (nVal & nBinDigit))
pResult[*nSizeOut - i - 1] = 1;
}
return pResult;
}
Testing:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define _DC 9
int main()
{
int test[_DC];
for (int i = 0; i < _DC; ++i)
test[i] = i;
unsigned int nRes = 0;
int* pRes = int2bin(test, _DC, &nRes);
for (unsigned int i = 0; i < nRes; ++i)
printf("%d", pRes[i]);
free(pRes);
return 0;
}
So basically according to definition of array we cannot change array size. But if I am adding element to a same array by shifting other elements to the right of array, so the array size is going to increase.
How this is possible?
#include<stdio.h>
int main() {
int n, j, k, item;
printf("Enter size of array:\n");
scanf("%d", &n);
printf("Enter element to insert and position of element:\n");
scanf("%d,%d", &item, &k);
int a[n];
for (j = 0; j < n; j++) {
printf("Enter a[%d] element:\n", j);
scanf("%d", &a[j]);
}
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j];
j = j - 1;
}
a[k - 1] = item;
for (j = 0; j <= n; j++) {
printf("%d\n", a[j]);
}
}
Shifting the contents of the array to the right will not resize the array. If the array was not already large enough to hold the result of the shift, then you have overrun the array object, and have induced undefined behavior.
There is no way to dynamically increase the size of a variable with static or auto duration (e.g., global or local variables), and this includes arrays. If your compiler supports variable length arrays (VLAs), changing the value of the expression controlling the dimension of the array does not affect the array's size.
int main (void) {
int n = 3;
int v[n];
printf("%zu\n", sizeof(v));
++n;
printf("%zu\n", sizeof(v));
}
The program above will print the same value twice.
I am not entirely sure what you're asking, but for any readers interested in knowing how to dynamically change the size of an array in C: if an array is declared in stack memory, its size cannot change. However, a block of memory intended to be used as an array is declared on the heap (i.e. with malloc or calloc), can be reallocated with a different size if necessary:
int *data = malloc(10 * sizeof(int)), *data2 = NULL;
int i;
if(data == NULL)
{
perror("malloc");
exit(EXIT_FAILURE);
}
for (i = 0; i < 10; i++)
{
data[i] = i;
}
data2 = realloc(data, 11 * sizeof(int));
if(data2 == NULL)
{
free(data);
perror("realloc");
exit(EXIT_FAILURE);
}
else
{
data = data2;
}
data[10] = 10;
for (i = 0; i < 11; i++)
printf("%d ", data[i]);
free(data);
data = NULL;
Shifting elements in an array down one element will not change its size.
If you declare an array as
T a[N]; // assume N is a constant expression
then a can only ever hold N elements of type T - no more, no less. You cannot add extra elements to the array, nor can you remove elements from the array.
However...
C does not force any bounds checking on array subscripting, so it's possible that you can read or write past the end of the array such as
a[N + 2] = x;
The behavior on doing so is undefined - your program may work as expected, or it may crash immediately, or you may corrupt other objects in the program. The runtime environment will (most likely) not throw an IndexOutOfBounds-type exception.
There is a thing called a variable-length array that was added in C99, where the array size is not a constant expression:
size_t size = some_value();
T a[size];
Variable length arrays are only variable length in the sense that their size isn't determined until runtime - however, once defined, their size is fixed throughout their lifetime, and like regular arrays, they cannot grow as new items are added.
If you dynamically allocate a chunk of memory using
T *a = malloc( sizeof *a * some_size );
then you can grow or shrink that chunk of memory using realloc:
T *tmp = realloc( a, sizeof *a * (some_size * 2) );
if ( tmp )
{
a = tmp;
some_size *= 2;
}
.... array we cannot change .. But if I (do something special) ... the array size is going to increase.
How this is possible?
Undefined behavior
Arrays cannot change size once defined.
Code attempts to assign a[j + 1] with j = n-1 and that is a[n]. This is outside array a[] and so undefined behavior. Rest of code is irrelevant for at that point anything is possible, code crash, error report, even apparent successful array expansion, etc.
int a[n];
...
j = n - 1;
while (j >= k - 1) {
a[j + 1] = a[j]; // To attempt access to `a[n]` is UB
I'm having an issue with my code. Disclaimer btw, I'm new to C. Trying to learn it on my own. Anyways, I'm trying to get the minimum and maximum of an array. I broke the array into 4 parts to make 4 separate arrays and then used those 4 to pass in one of the parameters of each thread. With that being said, I'm only able to get the maximum for each part of the array and not the minimum and I don't understand why.
I think we can simplify your code, avoid all these unnecessary malloc calls, and simplify your algorithm for finding a min/max pair in an array.
Start by having a thread function that takes as input the following: an array (represented by a pointer), an index into the array from where to start searching on, and an index in the array on where to stop. Further, this function will need two output parameters - smallest and largest integer found in the array subset found.
Start with the parameter declaration. Similar to your MaxMin, but has both input and output parameters:
struct ThreadParameters
{
// input
int* array;
int start;
int end;
// output
int smallest;
int largest;
};
And then a thread function that scans from array[start] all the way up to (but not including) array[end]. And it puts the results of its scan into the smallest and largest member of the above struct:
void* find_min_max(void* args)
{
struct ThreadParameters* params = (struct ThreadParameters*)args;
int *array = params->array;
int start = params->start;
int end = params->end;
int smallest = array[start];
int largest = array[start];
for (int i = start; i < end; i++)
{
if (array[i] < smallest)
{
smallest = array[i];
}
if (array[i] > largest)
{
largest = array[i];
}
}
// write the result back to the parameter structure
params->smallest = smallest;
params->largest = largest;
return NULL;
}
And while we are at it, use capitol letters for your macros:
#define THREAD_COUNT 4
Now you can keep with your "4 separate arrays" design. But there's no reason to since the thread function can scan any range of any array. So let's declare a single global array as follows:
#define ARRAY_SIZE 400
int arr[ARRAY_SIZE];
The capitol letter syntax is preferred for macros.
fillArray becomes simpler:
void fillArray()
{
for (int i = 0; i < ARRAY_SIZE; i++)
{
arr[i] = rand() % 1000 + 1;
}
}
Now main, becomes a whole lot simpler by doing these techniques.:
We'll leverage the stack to allocate our thread parameter structure (no malloc and free)
We'll simply start 4 threads - passing each thread a pointer to a ThreadParameter struct. Since the thread won't outlive main, this is safe.
After starting each thread, we just wait for each thread to finish)
Then we scan the list of thread parameters to get the final smallest and largest.
main becomes much easier to manage:
int main()
{
int smallest;
int largest;
// declare an array of threads and associated parameter instances
pthread_t threads[THREAD_COUNT] = {0};
struct ThreadParameters thread_parameters[THREAD_COUNT] = {0};
// intialize the array
fillArray();
// smallest and largest needs to be set to something
smallest = arr[0];
largest = arr[0];
// start all the threads
for (int i = 0; i < THREAD_COUNT; i++)
{
thread_parameters[i].array = arr;
thread_parameters[i].start = i * (ARRAY_SIZE / THREAD_COUNT);
thread_parameters[i].end = (i+1) * (ARRAY_SIZE / THREAD_COUNT);
thread_parameters[i].largest = 0;
pthread_create(&threads[i], NULL, find_min_max, &thread_parameters[i]);
}
// wait for all the threads to complete
for (int i = 0; i < THREAD_COUNT; i++)
{
pthread_join(threads[i], NULL);
}
// Now aggregate the "smallest" and "largest" results from all thread runs
for (int i = 0; i < THREAD_COUNT; i++)
{
if (thread_parameters[i].smallest < smallest)
{
smallest = thread_parameters[i].smallest;
}
if (thread_parameters[i].largest > largest)
{
largest = thread_parameters[i].largest;
}
}
printf("Smallest is %d\n", smallest);
printf("Largest is %d\n", largest);
}
I have implemented counting sort according to its pseudocode ( that's written on the blackboard in this video explanation ) but for some mysterious reason, it doesn't seem to work properly.
Every time I run this function, I get a segmentation fault as a result, although theoretically it should work.
My question is: I want to know why the code below will give Segmentation fault as an output.
void counting(int * array, int n){
int *copy, *out, i,j, max, counter;
out = (int*) malloc(sizeof(int) * n );
max = array[0];
// Find maximum value in main array and make a copy array of the same size
for(i=0;i<n;++i) if(array[i] > max) max = array[i];
copy = (int*) malloc(sizeof(int) * (max+1));
// initialize copy array
for(i=0;i<max;++i) copy[i] = 0;
// count how often each value occurs
for(i=0;i<n;++i) ++copy[array[i]];
// perform cumulative sum over the array
for(i=1;i<max;++i) copy[i] += copy[i-1];
// sort
for(i=n-1;i>=1;--i){
out[copy[array[i]]] = array[i];
--copy[array[i]];
}
// free memory
free(copy);
free(out);
// copies end result to original array
// for(i=0;i<n;++i) array[i] = out[i];
}
Both the for loops should be run till max value, not for max-1.
Following changes should help.
for(i=0;i<=max;++i) copy[i] = 0;
// count how often each value occurs
for(i=0;i<n;++i) ++copy[array[i]];
// perform cumulative sum over the array
for(i=1;i<=max;++i) copy[i] += copy[i-1];
Hope it helps!
The problem seems to arise from the fact that the explanation in the video assumes 1-based array indexes, while C of course uses 0-based array indexes. So a number of changes in the loops and the assignment in the out array are required:
void counting(int *array, int n){
int *copy, *out, i, j, max, counter;
out = malloc(sizeof(int) * n);
max = array[0];
for(i=1;i<n;++i) if(array[i] > max) max = array[i]; // 0 unnecessary
copy = malloc(sizeof(int) * (max+1));
for(i=0;i<=max;++i) copy[i] = 0; // <=max for complete array
for(i=0;i<n;++i) ++copy[array[i]];
for(i=1;i<=max;++i) copy[i] += copy[i-1]; // <=max for complete array
for(i=n-1;i>=0;--i){ // >=0 for complete array
out[copy[array[i]] - 1] = array[i]; // -1 because 0-based index
--copy[array[i]];
}
for(i=0;i<n;++i) array[i] = out[i];
free(copy);
free(out);
}
With these changes the code compiles without errors and gives the correct result.
So, I'm just working on C code, particularly a function which accepts 3 arguments: an array, the size of the array, and the number of max elements you want returned.
Here's my code:
int* findMaxElements(int base_array[],int size_of_base_array, int number_of_elements_to_find);
int main( void )
{
printf("Find Max Values in an Array\n\n");
// Set up array
int kinch[6] = {1,2,3,4,5,6};
// Pass to function and get a pointer to new array filled with only the max elements
int *given = findMaxElements(kinch,6,3);
for(int i = 0; i < 3; i++)
{
printf("\nMax Value = %d\n", *(given + i));
}
return 0;
}
int* findMaxElements(int base_array[],int size_of_base_array, int number_of_elements_to_find)
{
// Set up all initial variables
int i,k,c,position;
int maximum = 0;
int returnArray[100];
/*Actual Algorythm */
for(i = 0; i < number_of_elements_to_find; i++)
{
// Get the max value in the base array
for(k = 0; k < size_of_base_array; k++)
{
if(base_array[k] > maximum)
{
maximum = base_array[k];
}
}
// Find the position of the max value
for(position = 0; position < size_of_base_array; position++)
{
if(base_array[position] == maximum)
{
break;
}
}
// Delete the maximum value from the array and shift everything
for(c = position - 1; c < size_of_base_array - 1; c++)
{
base_array[c] = base_array[c+1];
}
// Reduce the size of the array
size_of_base_array -= 1;
// Push max value into return array
returnArray[i] = maximum;
// Reset max value
maximum = 0;
}
return returnArray;
}
I have a feeling somewhere in the function something goes wrong.
// Set up array
int kinch[6] = {1,2,3,4,5,6};
// Pass to function and get a pointer to new array filled with only the max elements
int *given = findMaxElements(kinch,6,3);
for(int i = 0; i < 3; i++)
{
printf("\nMax Value = %d\n", *(given + i));
}
This should output the numbers 6, 5, and 4, because they are the three largest in the array, however the output I get is always 6, 6, and 6. What's wrong with it?
This may not be your only problem, but in the lines
for(c = position - 1; c < size_of_base_array - 1; c++)
{
base_array[c] = base_array[c+1];
}
You copy the element at [c+1] (which is the maximum) to [c] - so you keep finding the max...
You should start the loop with c = position, not c = position - 1.
And add keyword static in front of the array you use to store the return values, so they remain valid (this is one way to address the issue that Jonathan Leffler identified).
One problem is that you are returning a pointer to a local variable, returnArray, in the function. You can't do that reliably — it leads to undefined behaviour.
There may well be other problems too, but that's enough to be a show-stopper on its own.
The whole approach to find the Kth largest element is not efficient and elegant. I will suggest you to modify your algorithm, although with above suggestions it will work fine, but it's not good way to solve this problem.
I will suggest you to look into below link to modify your algorithm
http://www.geeksforgeeks.org/k-largestor-smallest-elements-in-an-array/