LINUX.ORG.RU

Загадка с аалокаторами с С++


0

0

Итак, есть такой вот "несложный" тип:
rand.h:

#ifndef _RAND_H_
#define _RAND_H_
#include <iostream>

#include <vector>

namespace mod_sim {

/*Class for uniform random number generator*/
class Uniform_Rand {
int dummy; // first sequence
int dummy2; // second sequence
int iy; // counter value
double max; // maximum value of the random number
std::vector<int> iv;

/*Realization of the unform random algoritm*/
double lecuyer(); // L`Ecuyer algorithm (modifiction of Park & Miller techinque)

public:
/*Constructor: maximm number*/
Uniform_Rand(double);

inline double get() { double l = lecuyer(); return max*l;}; // get next random number
};

}

#endif

rand.cc:
#include "rand.h"
#include <time.h>

namespace mod_sim {
/** Constant section*/
/*Constants neede by L`Ecuyer*/
const int ntab=32;
const int nwup = 8;
const int iq1 = 53668;
const int iq2 = 52774;
const int ia1 = 40014;
const int ia2 = 40692;
const int ir1 = 12211;
const int ir2 = 3791;
const int im1 = 2147483563;
const int im2 = 2147483399;
const int imm1 = im1 - 1;
const int ndiv = 1 + imm1/ntab;
const double am = 1.0/2147483647;
const double rnmx = 1.0;

/** Private section*/
/*Realization of the L`Ecuyer algorithm for generation of uniform sequence of random number*/
double Uniform_Rand::lecuyer()
{
int k; // intermediate value
double temp; // prior result

/*Initialize the random sequence (first set of coefficients, the routine close to
that in the function above*/
if ( (dummy <= 0) || !iy )
{
/*Avoid negative or zero seed*/
if ( dummy<0 ) dummy = -dummy;
else if ( dummy == 0 ) dummy = 1;
dummy2 = dummy;

/*After NWUP warmups, initialize shuffle table*/
for (int j=ntab+nwup-1; j>=0; j--)
{
k = dummy/iq1;
if ( (dummy=ia1*(dummy-k*iq1)-ir1*k)<0 ) dummy += im1;
if ( j < ntab ) iv[j]=dummy;
}
iy = iv[0]; // first specimen from the table
}

/*Regular work: generate 2 sequences*/
k=dummy/iq1;
if ( (dummy=ia1*(dummy-k*iq1)-ir1*k)<0 ) dummy += im1;
k=dummy/iq2;
if ( (dummy2=ia2*(dummy-k*iq2)-ir2*k)<0 ) dummy2 += im2;

/*Shuffle output combining 2 sequences*/
iy = iv[iy/ndiv] - dummy2;
iv[iy/ndiv] = dummy;
if ( iy < 1 ) iy += imm1;

/*Return results*/
if ( (temp=am*iy)>rnmx ) return rnmx;
else return temp;
}

/** Public section*/
/*Constructor:
n is a maximm number of generated value*/
Uniform_Rand::Uniform_Rand(double n):
dummy2(0), dummy(time(0)), iy(0), max(n)
{
for(int i =0; i<ntab; i++) iv.push_back(0);
}

}

Пока этот мега числоплодитель в программе не создан (числа плодим встроенным генератором) все работает цветет и пахнет (прога по моделированию физ процессов). Стоит только создать сие объект, и ... через некоторое время в произвольных местах начинают сыпаться аллокаторы в STL, а именно попытки создания новых объектов в контейнерах типа vector<double>, map <unsigned, long> приводят к чему-то типа: "Ошибка шины", "Ошибка сегментации", "Аварийный останов" и пр. Valgring утечек памяти в проге не показал, обращения по аварийным адресам идут грубоко внутри STL а не в проге. Кады сего объекта нет STL работает нормально.

Народ поделитесь мыслями что не так? (В этом объекте vector менялся на массив, картина та же только еще хуже...)

anonymous
Ответ на: комментарий от dilmah

А что вот это в конструкторе не дотягивает размер до нормального (порнографично но всеже):

for(int i =0; i<ntab; i++) iv.push_back(0);

Потом если он имеет нулевой размер на момент обращения к несуществующим его элементам то ошибки будут в местах подобных обращений (или я не прав?) а ошибки возникают в местах вставки элементов в совершенно других контейнерах в совершенно других местах!

anonymous
()
Ответ на: комментарий от anonymous

> А что вот это в конструкторе не дотягивает размер до нормального (порнографично но всеже): for(int i =0; i<ntab; i++) iv.push_back(0);

дотягивает, я не заметил

> то ошибки будут в местах подобных обращений (или я не прав?) а ошибки возникают в местах вставки элементов в совершенно других контейнерах в совершенно других местах!

если портится память то ошибки могут потом проявиться где угодно. Undefined Behaviour..

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

у тебя много оперций с ndiv, ntab -- ты там точно нигде на единицу не ошибся?

dilmah ★★★★★
()

Запусти под valgrind.

anonymous
()

Замени iv[] на iv.at(), который проверяет индексы.

anonymous
()

в строке

iy = iv[iy/ndiv] - dummy2;

iy становиться отрицательным (по крайней мере в некоторых случаях) и в следующей строке ты обращяешься к элементу с отрицательным смещением.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.