I use xcode 4 on Mac Os X snow leopard.
I am trying to write a function to generate a random number within an interval, except some numbers.
ie:
int num=5;
random(time(NULL),1,100,&num,NULL);
This must generate a number within 1 and 100, except 5.
So I’ve written this code:
//
// main.cpp
// CPPTest
//
// Created by Ramy Al Zuhouri on 3/7/12.
// Copyright 2012 __MyCompanyName__. All rights reserved.
//
#include <iostream>
#include <exception>
#include <cstdarg>
#include <cstdlib>
#include <ctime>
using namespace std;
class cannotGenerate : public exception
{
virtual const char* what()
{
return "Cannot generate any number, maybe the interval is empty, or the exluding vector is too large\n";
}
};
// Random number generation
// min : min number (included)
// max : max number (included)
// seed : generator seed
// excp1 first argument of int pointers (the last must be NULL)
// the int pointers represent the numbers that must be excluded
// so that if such number is generated, it has to be generated again
int random(unsigned int seed=(unsigned int)time(NULL),int min=0,int max=RAND_MAX, int* excp1=NULL , ...)
{
// variables
int result,*ptr;
va_list vl;
static unsigned int count=0;
// instructions
srand(seed+count++);
va_start(vl,excp1);
do // this do-while has the purpose to keep generating numbers until the number is correct
{ // correct = within the [min,max] interval and not a number of the list of pointers
result=rand()%(max-min+1)+min;
ptr=excp1;
do // this do-while has the purpose to check all the va_list and to read all arguments
{ // passed to the function
if(ptr!=NULL)
{ // here there is the exception (with gdb 6.3.50) :
if(result==*ptr) // Thread 1: Program received signal: "EXC_BAD_ACCESS".
result=min-1;
ptr=va_arg(vl,int*);
}
else
{
break;
}
}while(ptr!=NULL && (result<min || result>min));
}while(result<min || result>max);
va_end(vl);
// result
return result;
}
int main (int argc, const char * argv[])
{
int excp[]={1,2,3,4};
int rand;
for(int i=0;i<100;i++)
{
rand=random((unsigned int)time(NULL),1,100,&excp[0],&excp[1],&excp[2],&excp[3],NULL);
if(rand==1 || rand==2 || rand==3 || rand==4)
{
cerr << "error" << endl;
break;
}
else
{
printf("%d\n",rand);
}
}
return 0;
}
But with gdb I’m getting this exception:
Thread 1: Program received signal: “EXC_BAD_ACCESS”.
In that block ptr can’t be NULL, so I can’t figure out the reason of this exception.
The issue is that you don’t reset the variable argument list after the first run through so it ends up pointing to the memory after the NULL input which results in the exception (if you’re lucky).
Try replacing the inner loop in random with the following (note placement of va_start and va_end).