I have a simple test program in C to scramble an array of values on the heap. Sidenote: I know the random logic here has a flaw that will not allow the "displaced" value to exceed RAND_MAX, but that is not the point of this post.
The point is that when I run the code with N = 10000, every once in a while it will crash with very little information (screenshots posted below). I'm using MinGW compiler. I can't seem to reproduce the crash for lower or higher N values (1000 or 100000 for example).
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
const int N = 10000;
int main() {
int i, rand1, rand2, temp, *values;
/* allocate values on heap and initialize */
values = malloc(N * sizeof(int));
for (i = 0; i < N; i++) {
values[i] = i + 1;
}
/* scramble */
srand(time(NULL));
for (i = 0; i < N/10; i++) {
rand1 = (int)(N*((double)rand()/(double)RAND_MAX));
rand2 = (int)(N*((double)rand()/(double)RAND_MAX));
temp = values[rand1];
values[rand1] = values[rand2];
values[rand2] = temp;
}
int displaced = 0;
for (i = 0; i < N; i++) {
if (values[i] != (i+1)) {
displaced++;
}
}
printf("%d numbers out of order\n", displaced);
free(values);
return 0;
}
it may be because rand() generates a random number from 0 to RAND_MAX inclusive so (int)(N*((double)rand()/(double)RAND_MAX)) can be N, which exceeds the array boundary. however, i don't see why that would vary with array size (it does explain why it only crashes sometimes, though).
try /(1+(double)RAND_MAX) (note that addition is to the double, to avoid overflow, depending on the value of RAND_MAX) (although i'm not convinced that will always work, depending on the types involved. it would be safer to test for N and try again).
also, learn to use a tool from Is there a good Valgrind substitute for Windows? - they make this kind of thing easy to fix (they tell you exactly what went wrong when you run your program).
Related
I wrote the code for a problem in codeforces and even though I believe I was doing it in the best time complexity it was exceeding the time limit on the 7th test case. After some testing, it seemed to me that the major amount of time was being taken by printf, which seemed odd since using printf some 3 * 10^5 times shouldn't be such a big deal. So I searched a lot and found this: https://codeforces.com/blog/entry/105687#comment-940911
Now I made the conclusion that using this line at the top of my code will make printf faster:
#define __USE_MINGW_ANSI_STDIO 0
So I ran my code with the above included and voila what was exceeding the time limit of 1s earlier now with the inclusion of just one line of code got accepted in merely 62 ms.
I didn't understand most of the other stuff that was talked about in the link like MinGW implementations and all.
So my question is, firstly why does it work this way? Secondly, can I/should I keep using the above line of code in all my programs on codeforces from now on?
P.S. I also found this blog: https://codeforces.com/blog/entry/47180
It was too confusing for me to grasp for the time being but maybe someone else can understand it and shed some light on the matter.
Also, here is the codeforces problem: https://codeforces.com/contest/1774/problem/C
Here is my solution:
https://codeforces.com/contest/1774/submission/185781891
I don't know the entire input as codeforces doesn't share it and it'd be very very big. But I know that the value inputted to the tests variable is 3, the values inputted to n[0], n[1], n[2] are 100000, 100000, 100000
Here is my code:
#define __USE_MINGW_ANSI_STDIO 0
#include <stdio.h>
#include <stdlib.h>
// #include <math.h>
// #include <string.h>
// #define lint long long int
// Function Declarations
int main(void)
{
int tests;
scanf("%i", &tests);
int **answers = malloc(tests * sizeof(int*));
int *n = malloc(sizeof(int) * tests);
for (int i = 0; i < tests; i++)
{
scanf("%i", &n[i]);
char *enviro = malloc((n[i]) * sizeof(int));
answers[i] = malloc((n[i] - 1) * sizeof(int));
int consec = 1; // No. of same consecutive elements at the very
// end.
scanf("%s", enviro);
answers[i][0] = 1; // Case where x = 2;
for (int x = 3; x < n[i] + 1; x++)
{
// comparing corresponding to current x vs previous x
if (enviro[x - 2] == enviro[x - 3])
{
consec++;
}
else
{
consec = 1;
}
answers[i][x - 2] = x - consec;
}
// Free loop variables
free(enviro);
}
/* if (tests == 3)
{
printf("n[%i] = %i\n", i, n[i]);
} */
for (int i = 0; i < tests; i++)
{
for (int j = 0; j < n[i] - 1; j++)
{
printf("%i ", answers[i][j]);
}
printf("\n");
free(answers[i]);
}
// Free variables
free(answers);
return 0;
}
EDIT: So I tried the following code for the same problem on codeforces (https://codeforces.com/contest/1774/submission/185788962) just to see the execution time:
// #define __USE_MINGW_ANSI_STDIO 0
#include <stdio.h>
#include <math.h>
int main(void)
{
int n = pow(10, 5);
for (int i = 0; i < n; i++)
{
printf("*");
}
}
Without the #define __USE_MINGW_ANSI_STDIO 0 it gave an e.t. of 374ms. With it, it gave e.t. of 15ms.
It seems like MinGW defined their own printf() functions, __mingw_printf(). This is done to fix format specifiers' problems on some old Windows operating systems, as seen in their wikis. The macro __USE_MINGW_ANSI_STDIO is set to 0 if you don't want to use MinGW's implementation, and 1 if you do.
It also seems like MinGW's implementation is slower, so not using it will make your code faster.
Alright, so, just for fun, I was working on the sieve of eratosthenes.
It was working fine intially so I sought out to improve its runtime complexity. and now, I on't know why, but I'm gettig a segmentation fault.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int* check = malloc(1000000000 * sizeof(int));
long long int i;
for(i = 0;i < 1000000000;i++)
{
check[i] = 0;
}
int j = 0;
for(i = 2;i <= 1000000002;i++)
{
if(check[i] == 0)
{
printf("%lld\n", i);
for(j = 1;j < (1000000001/i);j++)
{
check[j*i] == 1;
}
}
}
return 0;
}
Any help as to why it fails would be appreciated.
Your code has multiple errors, any of which could explain a segfault. First, you have not checked the return value of malloc, which may be NULL, even when you are totally sure it couldn't be.
Second, you are exceeding the bounds of the array you've allocated when you iterate i from 2 to 1000000002. With so many zeros it's hard to eyeball, so here are your figures with separators:
Initial allocation: 1,000,000,000
Range of i: 2 to 1,000,000,002 inclusive
At the end of that loop you are accessing memory past the end of your array.
#include <stdio.h>
#include <stdlib.h>
#if 1
static const size_t N = 1000 * 1000 * 1000;
#else
static const size_t N = 1000;
#endif
Don't use a magic number, define it as a constant. 1000000000 is also hard to read. Your C compiler can do calculation for you before it emits an executable. And you should have started with a small number. If you change #if 1 into #if 0, then the #else clause defining N as 1,000 will take effect.
int main(void)
{
char* check = malloc(N + 3);
When you essentially use check as a boolean array, it doesn't have to be of type int. int occupies 4 bytes whereas char only 1 byte.
if (NULL == check) {
perror("malloc");
abort();
}
malloc silently returns NULL when it failed to find a memory chunk of the specified length. But if you work with 64 bit OS and compiler, I don't think it's likely to fail...
long long int i;
memset(check, 0, sizeof(check[0]) * (N + 3));
memset fills an array with the value of the 2nd parameter (here 0.) The third parameter takes the number of BYTES of the input array, so I used sizeof(check[0]) (this is not necessary for a char array becuase sizeof(char)==1 but I always stick to this practice.)
int j = 0;
for(i = 2;i <= N+2;i++)
{
if(check[i] == 0)
{
printf("%lld\n", i);
for(j = 1;j < ((N+1)/i);j++)
{
check[j*i] = 1;
You wrote check[j*i] == 1 but it was an equality test whose result didn't have any effects.
}
}
}
free(check);
It is a good practice to always free the memory chunk that you allocated with malloc, regardless whether free is necessary or not (in this case no, because your program just exits at the end of sieve calculation.) Perhaps until you become really fluent with C.
return 0;
}
Hello friends I need your help.
My program is such an array size 1000 where the numbers should be between 0-999. These numbers should be determined randomly (rand loop) and the number must not be repeated. Would be considered the main part, I have to count how many times I used rand().
My idea is that: one loop where it initializes all the 1000 numbers, and if in this loop they check whether the number appears twice, if the number appears twice is set it again until that not appear twice (maybe this is not the best way but ...)
It is my exercise (Here I need your help)-
#include <stdio.h>
#include <stdlib.h>
int main()
{
int const arr_size = 1000;
int i, j, c;
int arr[arr_size];
int loop = 0;
for(i = 0; i<arr_size; i++)
{
arr[i] = rand() % 1000;
loop++;
if (arr[i] == arr[i - 1])
{
arr[i] = rand() % 1000;
loop++;
}
}
printf("%d\n",loop);
}
So if anyone can give me advice on how I can make it work I appreciate your help.
Thanks.
As suggested, shuffling the set will work but other indirect statistical quantities might be of interest, such as the distribution of the loop variable as a function of the array index.
This seemed interesting so I went ahead and plotted the distribution of the loop as a function of the array index, which generally increases as i increases. Indeed, as we get near the end of the array, the chance of getting a new random number that is not already in the set decreases (and hence, the value of the loop variable increases; see the code below).
Specifically, for an array size = 1000, I recorded the non-zero values generated for loop (there were around 500 duplicates) and then made a plot vs the index.
The plot looks like this:
The code below will produce an array with the unique random values, and then calculate the value for loop. The loop values could be stored in another array and then saved for later analysis, but I didn't include that in the code below.
Again, I'm not exactly sure this fits the application, but it does return information that would not necessarily be available from an approach using a shuffle algorithm.
NOTE: some folks expressed concerns about how long this might take but it runs pretty quick, on my 2011 Macbook Pro it took a about a second for an array size of 1000. I didn't do a big-O analysis as a function of the array size, but that would be interesting too.
NOTE 2: its more elegant to use recursion for the numberInSet() function but it seemed best to keep simple.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h> /* If C99 */
const int ARR_SIZE = 1000;
/* Check if the number is in the set up to the given position: */
bool numberInSet(int number, int* theSet, int position);
int main()
{
int* arr = malloc(sizeof(int)*ARR_SIZE);
srand((unsigned int)time(NULL));
/* Intialize array with rand entries, possibly duplicates: */
for(int i = 0; i < ARR_SIZE; i++)
arr[i] = rand() % ARR_SIZE;
/* Scan the array, look for duplicate values, replace if needed: */
for(int i = 0; i < ARR_SIZE; i++) {
int loop = 0;
while ( numberInSet(arr[i], arr, i-1) ) {
arr[i] = rand() % ARR_SIZE;
loop++;
}
/* could save the loop values here, e.g., loopVals[i] = loop; */
}
for(int i = 0; i < ARR_SIZE; i++)
printf("i = %d, %d\n",i,arr[i]);
/* Free the heap memory */
free(arr);
}
bool numberInSet(int number, int* theSet, int position) {
if (position < 0)
return false;
for(int i = 0; i <= position; i++)
if (number == theSet[i])
return true;
return false;
}
To make sure all random number you get in the same program are different, you must seed once the random generator:
srand (time(NULL)); //seed the random generator
//in the loop, rand will use the seeded value
rand() % 1000
I am working on a small piece of code that generates all the primes between two numbers for a set. I decided to use a sieve (and i know theres probably a much more efficient way to do what I want than the way my code is using it) and for some reason I am getting a SIGSEGV (segmentation fault). I have looked over it quite a bit and I don't know what's wrong. I haven't been able to reproduce the error on my local machine. I get this error generally occurs when accessing out of bounds, but I don't know if thats the case here. Be Gentle, I am pretty new to C, always stuck to the higher level stuff.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char argv){
int numberOfSets;
scanf("%d", &numberOfSets);
int i;
int lowerBound, upperBound;
for(i=0; i < numberOfSets; i++){
scanf("%d %d", &lowerBound, &upperBound);
//allocating memory and initializing to Zero
int (*sieve) = malloc(sizeof(int) * (upperBound+1));
memset(sieve, 0, (sizeof(int) * (upperBound+1)));
//iterating through sieve for even numbers and marking them as non prime
int counter = 2;
if(sieve[counter] == 0)
sieve[counter] = 1;
int multiplier = 2;
int multiple = counter * multiplier;
while(multiple <= upperBound){
sieve[multiple] = -1;
multiplier++;
multiple = multiplier * counter;
}
//iterating through sieve (incrementing by two) and filling in primes up to upper limit
counter = 3;
while( counter <= upperBound){
if(sieve[counter] == 0)
sieve[counter] = 1;
multiplier = 2;
multiple = counter * multiplier;
while(multiple < upperBound){
sieve[multiple] = -1;
multiplier++;
multiple = multiplier * counter;
}
counter = counter + 2;
}
int newCount = lowerBound;
//check and print which numbers in the range are prime
while (newCount <= upperBound){
if(sieve[newCount] == 1)
printf("%d\n", newCount);
newCount=newCount+1;
}
//free the allocated memort
free(sieve);
}
}
The problem was that I was not checking the result of Malloc. I was attempting to allocate an array that was to large and the allocation was failing. This left the array I was assigning to null and thus I was accessing out of its bounds.
I'm writing a program in C to do a simple dynamic programming algorithm where you return the minimum number of coins needed to add up to a certain amount. Here's my code:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
/*
This function returns the minimum number of stamps required for a given value.
It assumes that the given array contains the available stamp sizes, and that it
always contains 1, so a solution is always possible
*/
int min_number_of_stamps(const int* array, size_t array_size, int request) {
/* Construct a table with dimensions (array_size+1)*(request+1) */
int numRows = array_size + 1;
int numCols = request + 1;
int **DPtable;
DPtable = malloc(numRows*sizeof(int));
int i;
for (i = 0; i < numRows; i++) {
DPtable[i] = malloc(numCols*sizeof(int));
}
printf("%d",DPtable[4][0]);
int r, c, useIt, loseIt;
for (r = 0; r < numRows; r++) {
for (c = 0; c < numCols; c++) {
printf("%d,%d\n", r, c);
if (c==0) {
printf("1\n");
//if the amount of change is 0, 0 coins are needed
DPtable[r][c] = 0;
}
else if ((r==0) || c < array[r-1]) {
printf("2\n");
//if there are no coins or if the change needed is less than
//the smallest coin available, then 'infinity' coins are needed
DPtable[r][c] = INT_MAX;
}
else {
printf("3\n");
useIt = DPtable[r][c-array[r-1]] + 1;
loseIt = DPtable[r-1][c];
if (useIt <= loseIt) {
//if 'use it' requires fewer coins than 'lose it,' then
//'use it' coins are needed.
DPtable[r][c] = useIt;
}
else {
//if 'lose it' requires fewer coins, 'lose it' coins are needed
DPtable[r][c] = loseIt;
}
}
}
}
return DPtable[numRows][numCols];
}
int main() {
const int array[] = {1,5,10,25};
const int* stamps = &array[0];
printf("%d", min_number_of_stamps(stamps, 4, 44));
}
I'm getting a segfault when my inner for loop gets to the case where r=4 and c=0. I left my debugging print statements in because I'm lazy, but you can see where I got stuck. If I access the same place in the array outside of my for loops, there's no problem. But in the for loop, I get a `Segmentation fault: 11' message after it outputs "4,0" for the array element and "1" for the if case it's in. Can anyone see what I'm missing?
Learn to enable warnings & debugging for your compiler, i.e. gcc -g -Wall on Linux.
Learn to use a debugger, i.e. gdb -tui on Linux.
Consider using valgrind
EDIT
Many tutorials (in several languages, e.g. English, French, ....) for GCC, GDB, and ValGrind are easily found on the Web.
You're allocating dpTable incorrectly. It should be
DPtable = malloc(numRows*sizeof(int*));
See if that fixes the problem.
return DPtable[numRows][numCols];
thats out of bounds isn't it?