Encontré un error de tiempo de ejecución "double free or corruption" en mi programa C++ que llama a una biblioteca confiable ANN y usa OpenMP para paralizar un ciclo for.double free or corruption
*** glibc detected *** /home/tim/test/debug/test: double free or corruption (!prev): 0x0000000002527260 ***
¿Significa que la memoria en la dirección 0x0000000002527260 se libera más de una vez?
El error ocurre en "_search_struct-> annkSearch (queryPt, k_max, nnIdx, dists, _eps);" dentro de la función classify_various_k(), que a su vez está dentro de OpenMP for-loop dentro de la función tune_complexity().
Tenga en cuenta que el error ocurre cuando hay más de un subproceso para OpenMP, y no ocurre en el caso de un solo subproceso. No estoy seguro por qué.
El siguiente es mi código. Si no es suficiente para diagnosticar, házmelo saber. ¡Gracias por tu ayuda!
void KNNClassifier::train(int nb_examples, int dim, double **features, int * labels) {
_nPts = nb_examples;
_labels = labels;
_dataPts = features;
setting_ANN(_dist_type,1);
delete _search_struct;
if(strcmp(_search_neighbors, "brutal") == 0) {
_search_struct = new ANNbruteForce(_dataPts, _nPts, dim);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct = new ANNkd_tree(_dataPts, _nPts, dim);
}
}
void KNNClassifier::classify_various_k(int dim, double *feature, int label, int *ks, double * errors, int nb_ks, int k_max) {
ANNpoint queryPt = 0;
ANNidxArray nnIdx = 0;
ANNdistArray dists = 0;
queryPt = feature;
nnIdx = new ANNidx[k_max];
dists = new ANNdist[k_max];
if(strcmp(_search_neighbors, "brutal") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps); // where error occurs
}
for (int j = 0; j < nb_ks; j++)
{
scalar_t result = 0.0;
for (int i = 0; i < ks[j]; i++) {
result+=_labels[ nnIdx[i] ];
}
if (result*label<0) errors[j]++;
}
delete [] nnIdx;
delete [] dists;
}
void KNNClassifier::tune_complexity(int nb_examples, int dim, double **features, int *labels, int fold, char *method, int nb_examples_test, double **features_test, int *labels_test) {
int nb_try = (_k_max - _k_min)/scalar_t(_k_step);
scalar_t *error_validation = new scalar_t [nb_try];
int *ks = new int [nb_try];
for(int i=0; i < nb_try; i ++){
ks[i] = _k_min + _k_step * i;
}
if (strcmp(method, "ct")==0)
{
train(nb_examples, dim, features, labels);// train once for all nb of nbs in ks
for(int i=0; i < nb_try; i ++){
if (ks[i] > nb_examples){nb_try=i; break;}
error_validation[i] = 0;
}
int i = 0;
#pragma omp parallel shared(nb_examples_test, error_validation,features_test, labels_test, nb_try, ks) private(i)
{
#pragma omp for schedule(dynamic) nowait
for (i=0; i < nb_examples_test; i++)
{
classify_various_k(dim, features_test[i], labels_test[i], ks, error_validation, nb_try, ks[nb_try - 1]); // where error occurs
}
}
for (i=0; i < nb_try; i++)
{
error_validation[i]/=nb_examples_test;
}
}
......
}
ACTUALIZACIÓN:
Gracias! Ahora estoy tratando de corregir el conflicto de escritura al mismo problema de memoria en classify_various_k() mediante el uso de "#pragma omp crítico":
void KNNClassifier::classify_various_k(int dim, double *feature, int label, int *ks, double * errors, int nb_ks, int k_max) {
ANNpoint queryPt = 0;
ANNidxArray nnIdx = 0;
ANNdistArray dists = 0;
queryPt = feature; //for (int i = 0; i < Vignette::size; i++){ queryPt[i] = vignette->content[i];}
nnIdx = new ANNidx[k_max];
dists = new ANNdist[k_max];
if(strcmp(_search_neighbors, "brutal") == 0) {// search
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}else if(strcmp(_search_neighbors, "kdtree") == 0) {
_search_struct->annkSearch(queryPt, k_max, nnIdx, dists, _eps);
}
for (int j = 0; j < nb_ks; j++)
{
scalar_t result = 0.0;
for (int i = 0; i < ks[j]; i++) {
result+=_labels[ nnIdx[i] ]; // Program received signal SIGSEGV, Segmentation fault
}
if (result*label<0)
{
#pragma omp critical
{
errors[j]++;
}
}
}
delete [] nnIdx;
delete [] dists;
}
Sin embargo, hay un nuevo error de segmento a "número + = _ etiquetas [nnIdx [yo] ];". ¿Alguna idea? ¡Gracias!
Pruébalo sin openmp: ¿funciona correctamente? –
Recomiendo compilar con -g y ejecutar a través de valgrind si está en OSX o Linux. Eso debería señalar el error para usted. –
@Kornel: funciona correctamente para el caso de una sola rosca. – Tim