Segmentation fault in malloc() - c

I need to create a function which returns an array of ints. This int array should contain all values between min and max (both included).
If min >= max a null pointer should be returned.
The question is why, when min = -2147483468 and max = 2147483647 (and len becomes 4294967296) I get "Segmentation fault"?
My code:
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max)
{
int *range;
long int len;
long int i;
range = NULL;
if (min >= max)
return (NULL);
len = max - min + 1;
if(!(range = (int *)malloc(sizeof(int) * len)))
return (NULL);
i = 0;
while (min < max)
{
range[i] = min;
min++;
i++;
}
range[i] = max;
return (range);
}
int main(void)
{
int max;
int min;
long int len;
int *range;
long int i;
max = 2147483647;
min = -2147483648;
if (max != min)
len = max - min + 1;
else
len = 0;
i = 0;
range = ft_range(min, max);
while (i < len)
{
printf("%d", range[i]);
i++;
}
free(range);
return (0);
}
But, if I enter min = -2147483468 and max = 2147483646 with len = 4294967295 it works.

min and max are type int, which is only guaranteed to be 16 bits signed (-32768, 32767), although the compiler may choose to use more bits to store the values. Therefore, if you were to expect values ranging (-2147483468, 2147483647), these should be of type long int. The program may or may not be be truncating some of the bits when you supply (-2147483468, 2147483647) or (-2147483468, 2147483646) as inputs. This would also apply to the type for range.
Secondly, variable len is long int which is only guaranteed to be 32 bits signed (-2147483468, 2147483647). Since you want to be able to store value 4294967296, this will need to be either long long int or long long unsigned int. Even long unsigned int will only have a range of (0, 4294967295). This would also apply to i.
Additionally, the statement len = max - min + 1;, will need to include a type cast to long long int to avoid overflow when performing the arithmetic. You can do it by adding (long long int) this way: len = (long long int)max - min + 1;; or if you want to be more explicit: len = ((long long int)max - (long long int)min) + 1LL;
To summarize:
#include <stdlib.h>
#include <stdio.h>
int *ft_range(long int min, long int max)
{
long int *range;
long long int len;
long long int i;
range = NULL;
if (min >= max)
return (NULL);
len = (long long int)max - min + 1;
if(!(range = (int *)malloc(sizeof(int) * len)))
return (NULL);
i = 0;
while (min < max)
{
range[i] = min;
min++;
i++;
}
range[i] = max;
return (range);
}
Side note: Range (-2147483468, 2147483647) is going to require around 16 GB of memory to be allocated, so I hope that you are ready for that.

int overflow with max - min + 1;
Use wider math for size calculations.
Use size_t for allocation size and indexing
Add more error checks.
int *ft_range(int min, int max) {
// Add required test explicitly
if (min >= max) {
return NULL;
}
long long size = 1LL + max - min; // Use long long math
if (size > SIZE_MAX/sizeof(int) || size < 1) {
return NULL;
}
size_t usize = (size_t)size;
int *range = malloc(sizeof *range * usize);
if (range == NULL) {
return NULL;
}
size_t i = 0;
while (min < max) {
range[i] = min;
min++;
i++;
}
range[i] = max;
return range;
}

I solved the problem by using len and i as long long int, added long long int this way:
len = (long long int)max - min + 1;
Also I forgot to check if malloc returns NULL in main() function.
This is the correct version:
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max)
{
int *range;
long long int len;
long long int i;
range = NULL;
if (min >= max)
return (NULL);
len = (long long int)max - min + 1;
if(!(range = (int *)malloc(sizeof(int) * len)))
return (NULL);
i = 0;
while (min < max)
{
range[i] = min;
min++;
i++;
}
range[i] = max;
return (range);
}
int main(void)
{
int *range;
int max;
int min;
long long int len;
long long int i;
max = 2147483647;
min = -2147483648;
len = 0;
if (max != min)
len = (long long int)max - min + 1;
i = 0;
if(!ft_range(min, max))
return (0);
range = ft_range(min, max);
while (i < len)
{
printf("%d", range[i]);
i++;
}
free(range);
return (0);
}

Related

Printf function who returning an array of int

I'm trying this exercice but I don't know how to printf my function in main.
Exercice:
1) Write a function who returning an int tab with all values between min and max
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max)
{
int len;
int *tab;
len = min;
while (len < max)
len++;
tab = (int *)malloc(sizeof(*tab) * len + 1);
while (min < max)
{
*tab = min;
min++;
}
return(tab);
}
int main()
{
ft_range(0, 10);
return(0);
}
returning an int tab with all values between min and max
Depending on the idea of "between", it is an open question if the end values should be included. Given OP's mis-coded +1 in sizeof(*tab) * len + 1, I'll go with the idea both ends should be included.
Miscalculation of len
Rather than loop, simply subtract
//len = min;
//while (len < max)
// len++;
len = max - min + 1;
Allocation miscalculated
Good to use sizeof *pointer, yet the + 1 makes little sense. If anything the ... * len + 1 should have been ... * (len + 1). Yet the +1 is handled with the above fix. Also cast not needed in C.
// tab = (int *)malloc(sizeof(*tab) * len + 1);
tab = malloc(sizeof *tab * len);
Wrong assignment
Code repeatedly assigned the same *tab location.
//while (min < max)
//{
// *tab = min;
// min++;
//}
for (int i = min; i <= max; i++) {
tab[i - min] = i;
}
No allocation error checking nor min, max validation
Potential for int overflow with mix - min
Be sure to free allocations
Alternative
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max) {
if (min > max) {
return NULL;
}
size_t len = (size_t)max - min + 1;
int *tab = malloc(sizeof *tab * len);
if (tab == NULL) {
return NULL;
}
for (size_t i = 0; i < len; i++) {
tab[i] = int(min + i);
}
return tab;
}
int main() {
int mn = 0;
int mx = 10;
int *ft = ft_range(mn, mx);
if (ft) {
int *p = ft;
for (int i = mn; i <= mx; i++) {
printf("%d ", *p++);
}
free(ft);
}
return 0;
}
inside "ft_range", when you are trying to calculate the length the array needs to do, all you have to do is subtract the minimum from the maximum. what you did is much slower and unnecessary.
when allocating memory, you did not need to add a "+1" at the end. you may have seen it done in other examples, but it does not apply here.
the "while" loop inside "ft_range" needs to have a "<=" sign, otherwise it will stop before it reaches the "max" value.
when adding a value to the "tab" int array, you are always doing so by dereferencing it (putting a "*" before it), so every one of your values will come on the first position of the array and overwrite themselves. you need to have another "int i" to keep track of the current index of the array.
make sure to free the memory you allocated with "malloc" after you finish your enumeration. it does not matter right now, but if you ever get to writing more complex programs you will need to do so to keep the performance up, which can be critical.
here's a working code, with a few comments (i'm shit at comments, if you don't understand them, just ask me bro)
#include <stdlib.h>
#include <stdio.h>
int *ft_range(int min, int max)
{
int len;
int * tab;
len = max-min;
tab = (int *)malloc(sizeof(*tab) * len);
// create an index to track the position inside "tab"
int i = 0;
// sign needs to be "<=" so it does not stop before it reaches the max value
while (min <= max)
{
tab[i] = min;
// ++ needs to come before so the variable's value is updated right here
++min;
// increase the i index to the next position in "tab"
++i;
}
return(tab);
}
int main()
{
int min = 5;
int max = 10;
int len = max-min;
int * range = ft_range(min, max);
for(int i = 0; i <= len; ++i)
{
// %d = integer
// \n = move to next line
printf("%d\n", range[i]);
}
getchar();
return(0);
}
You correctly allocate memory to the table, you just need to printf the value in your main by using a loop trough your tab, i write this code who work perfectly.
#include <stdlib.h>
int *ft_range(int min, int max)
{
int *ptr;
int mi;
int i;
int range;
range = (max - min);
mi = min;
ptr = NULL;
if (min > max)
return (NULL);
else
ptr = malloc(sizeof(int) * range);
i = 0;
while (i < range)
{
ptr[i] = mi + i;
i++;
}
return (ptr);
}
// #include <stdio.h>
// int main()
// {
// //int i = 0;
// int min = 1;
// int max = 30;
// while(min < max)
// {
// printf("%d\n", *ft_range(min, max));
// min++;
// }
// }

How to check to make sure there are no repeats when generating 6 random numbers?

I can get the random numbers into an array but I can't figure out how to check to make sure that they aren't repeating. I print out the code but there are no numbers in the array (prints out nothing).
//puts random numbers into an array
i = 0, j = 0;
srand(time(NULL));
for (i = 0; i < arrSize; i++)
{
randArr[i] = randNums(1,50);
}
i = 0;
for(i = 0; i < arrSize; i++)
{
printf("%d ", randArr[i]);
}
printf("\n\n");
//checks to make sure there are no duplicates
i = 0, j = 0, k = 0, temp = 0;
for (i = 0; i < arrSize; i++)
{
for (j = 1; j <= arrSize;)
{
if (randArr[j] == randArr[i])
{
for (k = j; k <= arrSize; k++)
{
temp = randNums(1,50);
randArr[k + 1] = temp;
}
arrSize--;
}
else
j++;
}
}
//generates random numbers between the inputed max and min
int randNums(int min, int max)
{
int result = 0, low = 0, high = 0;
if (min < max)
{
low = min;
high = max + 1;
}
else
{
low = max + 1;
high = min;
}
result = (rand() % (high - low)) + low;
return (result);
}
Beware! There are many different solutions to this problem and they all have one or another downside. If I was to quickly implement it, I would go for something like this (without too much C-magic going on):
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE (30)
#define RAND_MIN (1)
#define RAND_MAX (50)
static int randNums(int min, int max) {
// ...
}
int main(void) {
(void) srand(time(NULL));
int arr[SIZE];
int used = 0;
while (used < SIZE) {
int num = randNums(RAND_MIN, RAND_MAX);
bool exists = false;
for (int i = 0; i < used; ++i) {
if (arr[i] == num)
exists = true;
}
if (exists == false)
arr[used++] = num;
}
for (int i = 0; i < SIZE; ++i)
(void) printf("%d\n", arr[i]);
return EXIT_SUCCESS;
}
I hope it helps a bit :)
Like this answer, you can do rejection sampling, but the uniform distribution of a fixed number of samples is perfect for a very simple hash set. (Though the asymptotic runtime might be irrelevant for n=6.)
#include <stdlib.h> /* (s)rand */
#include <stdio.h> /* printf */
#include <time.h> /* clock */
#include <assert.h> /* assert */
/* Double-pointers are confusing. */
struct Reference { int *ref; };
/* Simple fixed hash set. */
static struct Reference bins[256];
static int nums[6];
static const size_t no_bins = sizeof bins / sizeof *bins,
no_nums = sizeof nums / sizeof *nums;
static size_t count_num;
/* Uniformly distributed numbers are great for hashing, but possibly clump
together under linear probing. */
static size_t hash(const int n) { return ((size_t)n * 21) % no_bins; }
/* Linear probing. */
static struct Reference *probe(const int n) {
size_t bin_index;
struct Reference *bin;
assert(sizeof bins > sizeof nums);
for(bin_index = hash(n); bin = bins + bin_index,
bin->ref && *bin->ref != n; bin_index = (bin_index + 1) % no_bins);
return bin;
}
/* Return whether it's a new value. */
static int put_in_set(const int n) {
struct Reference *bin = probe(n);
int *num;
assert(count_num < no_nums);
if(bin->ref) return 0; /* Already in hash. */
num = nums + count_num++;
*num = n;
bin->ref = num;
return 1;
}
/* http://c-faq.com/lib/randrange.html */
static int rand_range(const unsigned n) {
unsigned int x = (RAND_MAX + 1u) / n;
unsigned int y = x * n;
unsigned int r;
assert(n > 0);
do {
r = rand();
} while(r >= y);
return r / x;
}
/* Generates random numbers between the inputed max and min without
repetition; [min, max] inclusive. */
static int unique_uniform(const int min, const int max) {
int n;
assert(min <= max && (size_t)(max - min) >= count_num);
do { n = rand_range(max - min + 1) + min; } while(!put_in_set(n));
return n;
}
int main(void) {
int n = 6;
srand((int)clock()), rand(); /* My computer always picks the same first? */
while(n--) { printf("%d\n", unique_uniform(1, 50)); }
return EXIT_SUCCESS;
}
However, if the numbers are densely packed, (eg, unique_uniform(1, 6),) it's going to reject a lot of numbers. Another solution is to take a Poisson distributed numbers as a running sum, (recurrence T(n+1)=T(n)+\mu_{n+1},) where the expected value is the range of numbers divided by the total samples, then take a random permutation.

What is the fastest way to list the elements of the unit group of a given size?

There are several fast algorithms to calculate prime numbers up to a given number n. But, what is the fastest implementation to list all the numbers r relatively prime to some number n in C? That is, find all the elements of the multiplicative group with n elements as efficiently as possible in C. In particular, I am interested in the case where n is a primorial.
The n primorial is like the factorial except only prime numbers are multiplied together and all other numbers are ignored. So, for example 12 primorial would be 12#=11*7*5*3*2.
My current implementation is very naive. I hard code the first 3 groups as arrays and use those to create the larger ones. Is there something faster?
#include "stdafx.h"
#include <stdio.h> /* printf, fgets */
#include <stdlib.h> /* atoi */
#include <math.h>
int IsPrime(unsigned int number)
{
if (number <= 1) return 0; // zero and one are not prime
unsigned int i;
unsigned int max=sqrt(number)+.5;
for (i = 2; i<= max; i++)
{
if (number % i == 0) return 0;
}
return 1;
}
unsigned long long primorial( int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k];
}
return answer;
}
unsigned long long EulerPhi(int Primes[], int size)
{
unsigned long long answer = 1;
for (int k = 0;k < size;k++)
{
answer *= Primes[k]-1;
}
return answer;
}
int gcd( unsigned long long a, unsigned long long b)
{
while (b != 0)
{
a %= b;
a ^= b;
b ^= a;
a ^= b;
}
//Return whethere a is relatively prime to b
if (a > 1)
{
return false;
}
return true;
}
void gen( unsigned long long *Gx, unsigned int primor, int *G3)
{
//Get the magic numbers
register int Blocks = 30; //5 primorial=30.
unsigned long long indexTracker = 0;
//Find elements using G3
for (unsigned long long offset = 0; offset < primor; offset+=Blocks)
{
for (int j = 0; j < 8;j++) //The 8 comes from EulerPhi(2*3*5=30)
{
if (gcd(offset + G3[j], primor))
{
Gx[indexTracker] = offset + G3[j];
indexTracker++;
}
}
}
}
int main(int argc, char **argv)
{
//Hardcoded values
int G1[] = {1};
int G2[] = {1,5};
int G3[] = {1,7,11,13,17,19,23,29};
//Lazy input checking. The world might come to an end
//when unexpected parameters given. Its okey, we will live.
if (argc <= 1) {
printf("Nothing done.");
return 0;
}
//Convert argument to integer
unsigned int N = atoi(argv[1]);
//Known values
if (N <= 2 )
{
printf("{1}");
return 0;
}
else if (N<=4)
{
printf("{1,5}");
return 0;
}
else if (N <=6)
{
printf("{1,7,11,13,17,19,23,29}");
return 0;
}
//Hardcoded for simplicity, also this primorial is ginarmous as it is.
int Primes[50] = {0};
int counter = 0;
//Find all primes less than N.
for (int a = 2; a <= N; a++)
{
if (IsPrime(a))
{
Primes[counter] = a;
printf("\n Prime: : %i \n", a);
counter++;
}
}
//Get the group size
unsigned long long MAXELEMENT = primorial(Primes, counter);
unsigned long long Gsize = EulerPhi(Primes, counter);
printf("\n GSize: %llu \n", Gsize);
printf("\n GSize: %llu \n", Gsize);
//Create the list to hold the values
unsigned long long *GROUP = (unsigned long long *) calloc(Gsize, sizeof(unsigned long long));
//Populate the list
gen( GROUP, MAXELEMENT, G3);
//Print values
printf("{");
for (unsigned long long k = 0; k < Gsize;k++)
{
printf("%llu,", GROUP[k]);
}
printf("}");
return 0;
}
If you are looking for a faster prime number check, here is one that is reasonably fast and eliminates all calls to computationally intensive functions (e.g. sqrt, etc..)
int isprime (int v)
{
int i;
if (v < 0) v = -v; /* insure v non-negative */
if (v < 2 || !((unsigned)v & 1)) /* 0, 1 + even > 2 are not prime */
return 0;
for (i = 2; i * i <= v; i++)
if (v % i == 0)
return 0;
return 1;
}
(note: You can adjust the type as required if you are looking for numbers above the standard int range.)
Give it a try and let me know how it compares to the once you are currently using.

Fermat Primality Test failure in C

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#define MAXNUM 2000000000
#define MINNUM 1990000001
#define MAXTRIES 10
unsigned long long b, e, m, result;
int modulo(b, e, m)
{
result = 1;
while(e > 0)
{
if(e % 2 == 1)
{
result = (result * b);
}
b = (b * b) % m;
e = e / 2;
}
return result % m;
}
int isPrime(n)
{
unsigned long long a;
int i;
for(i = 1; i <= 10; i++)
{
a = rand() % (n - 1) + 1;
if(modulo(a, n - 1, n) != 1)
{
return 0;
}
}
return 1;
}
int main()
{
unsigned int prime = 0;
unsigned int flag = 0;
unsigned int tries;
unsigned int start;
long curtime;
unsigned long long p;
curtime = time(NULL);
srand((unsigned int) curtime);
printf("Checking range [1990000001, 2000000000] for prime numbers.\n");
if(MINNUM % 2 == 0)
{
start = MINNUM + 1;
}
else
{
start = MINNUM;
}
printf("Trying Fermat test with seed %ld \n\n",curtime);
prime = 0;
for(tries = 1; tries <= MAXTRIES; tries++)
{
clock_t tic = clock();
for(p = start; p <= MAXNUM; p += 2)
{
if(isPrime(p))
prime++;
}
clock_t toc = clock();
printf("Probabilistic algorithm: Found %ld primes in %f seconds.(tries = %d)\n", prime, (double)(toc - tic) / CLOCKS_PER_SEC,tries);
prime = 0;
}
return 0;
}
So the problem is that the algorithm finds in every try 5000000 prime numbers when it should find around 466646 with some deviation. Which means that in every try it should find a number of primes close to the one mentioned above.
It looks like the main problem is caused by integer overflows in the modulo() function. Specifically, result=(result*b) is going to overflow quite regularly. You need to store these variables in 64-bit unsigned integers, and calculate the modulus of this result every time.
This will work (with a few minor corrections elsewhere):
#include <inttypes.h>
#define MAXNUM 2000000000
#define MINNUM 1990000001
#define MAXTRIES 10
uint64_t modulo(uint64_t b, uint64_t e, uint64_t m){
uint64_t result=1;
while(e>0){
if(e%2==1){
result=(result*b)%m;
}
b=(b*b)%m;
e=e/2;
}
return result%m;
}
Result:
Checking range [1990000001, 2000000000] for prime numbers.
Trying Fermat test with seed 1416322197
Probabilistic algorithm: Found 466646 primes in 5.157485 seconds.(tries=1)

Computer freezes when more memory is malloced

I am trying to run a C program which mallocs the memory as per the input given by user.
Whenever I input something as big as 1000000000 rather than returning NULL value, my Ubuntu 14.04 machine freezes completely! I am damn sure that malloc is the culprit...
But I am surprised to see Ubuntu freeze!
Does anyone have any idea about why this may be happening?
I have a laptop with 12GB RAM, i5 processor and 500GB harddisk. and Ubutnu 14.04 OS
Here is the code:
#include<stdio.h>
#include<stdlib.h>
#define LEFT(x) (2*(x)+1)
#define RIGHT(x) (2*(x)+2)
long long int *err, *sorted, *size, *id;
short int *repeat;
void max_heapify(long long int *arr, long long int length, long long int index)
{
long long int largest, left, right, temp, flag = 1;
while (flag)
{
left = LEFT(index);
right = RIGHT(index);
if (left < length && arr[left] > arr[index])
largest = left;
else
largest = index;
if (right < length && arr[right] > arr[largest])
largest = right;
if (largest != index)
{
temp = arr[index];
arr[index] = arr[largest];
arr[largest] = temp;
index = largest;
}
else
flag = 0;
}
}
void build_max_heap(long long int *arr, long long int length)
{
long long int i, j;
j = (length / 2) - 1;
for (i = j; i >= 0; i--)
max_heapify(arr, length, i);
}
void heapsort(long long int *arr, long long int length)
{
long long int i, temp, templength;
build_max_heap(arr, length);
templength = length;
for (i = 0; i < templength; i++)
{
temp = arr[0]; // maximum number
arr[0] = arr[length - 1];
arr[length - 1] = temp;
length--;
max_heapify(arr, length, 0);
}
}
int main()
{
long long int n, k, p, i, j;
scanf("%lld%lld%lld",&n, &k, &p);
err = (long long int*)malloc((n + 1) * sizeof(long long int));
//repeat = (short int*)calloc(1000000001 , sizeof(short int));
sorted = (long long int*)malloc((n + 1) * sizeof(long long int));
j = 0;
for(i = 0; i < n; i++)
{
scanf("%lld",&err[i]);
sorted[j++] = err[i];
}
heapsort(sorted, j);
for(i = 0; i < j; i++)
printf("%lld, ",sorted[i]);
//These malloc statements cause the problem!!
id = (long long int*)malloc((sorted[j - 1] + 1) * sizeof(long long int));
size = (long long int*)malloc((sorted[j - 1] + 1) * sizeof(long long int));
for(i = 0; i <= sorted[j - 1]; i++)
{
id[i] = i;
size[i] = 1;
}
return 0;
}
Basically I am trying to sort the numbers and then allocate the array of size of maximum element. This program works for smaller input but when I enter this
5 5 5
1000000000 999999999 999999997 999999995 999999994
It freezes ubuntu ..I even added the condition to check if id or size is NULL but that didn't help! If system is unable to allocate that much memory then it should return NULL but system freezes! And this code works fine on MAC!
Thanks!

Resources