c – 双重免费或腐败

前端之家收集整理的这篇文章主要介绍了c – 双重免费或腐败前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在我的C程序中遇到了一个运行时错误“double free or corruption”,它调用了一个可靠的库ANN并使用OpenMP来平行for循环.
  1. *** glibc detected *** /home/tim/test/debug/test: double free or corruption (!prev): 0x0000000002527260 ***

这是否意味着地址0x0000000002527260的内存被释放多次?

错误发生在“_search_struct-> annkSearch(queryPt,k_max,nnIdx,dists,_eps);”内部函数classify_varIoUs_k(),它在函数tune_complexity()内部的OpenMP for循环中.

请注意,当OpenMP有多个线程时会发生错误,并且在单线程情况下不会发生.不知道为什么.

以下是我的代码.如果它不足以进行诊断,请告诉我.谢谢你的帮助!

  1. void KNNClassifier::train(int nb_examples,int dim,double **features,int * labels) {
  2. _nPts = nb_examples;
  3.  
  4. _labels = labels;
  5. _dataPts = features;
  6.  
  7. setting_ANN(_dist_type,1);
  8.  
  9. delete _search_struct;
  10. if(strcmp(_search_neighbors,"brutal") == 0) {
  11. _search_struct = new ANNbruteForce(_dataPts,_nPts,dim);
  12. }else if(strcmp(_search_neighbors,"kdtree") == 0) {
  13. _search_struct = new ANNkd_tree(_dataPts,dim);
  14. }
  15.  
  16. }
  17.  
  18.  
  19. void KNNClassifier::classify_varIoUs_k(int dim,double *feature,int label,int *ks,double * errors,int nb_ks,int k_max) {
  20. ANNpoint queryPt = 0;
  21. ANNidxArray nnIdx = 0;
  22. ANNdistArray dists = 0;
  23.  
  24. queryPt = feature;
  25. nnIdx = new ANNidx[k_max];
  26. dists = new ANNdist[k_max];
  27.  
  28. if(strcmp(_search_neighbors,"brutal") == 0) {
  29. _search_struct->annkSearch(queryPt,_eps);
  30. }else if(strcmp(_search_neighbors,"kdtree") == 0) {
  31. _search_struct->annkSearch(queryPt,_eps); // where error occurs
  32. }
  33.  
  34. for (int j = 0; j < nb_ks; j++)
  35. {
  36. scalar_t result = 0.0;
  37. for (int i = 0; i < ks[j]; i++) {
  38. result+=_labels[ nnIdx[i] ];
  39. }
  40. if (result*label<0) errors[j]++;
  41. }
  42.  
  43. delete [] nnIdx;
  44. delete [] dists;
  45.  
  46. }
  47.  
  48. void KNNClassifier::tune_complexity(int nb_examples,int *labels,int fold,char *method,int nb_examples_test,double **features_test,int *labels_test) {
  49. int nb_try = (_k_max - _k_min) / scalar_t(_k_step);
  50. scalar_t *error_validation = new scalar_t [nb_try];
  51. int *ks = new int [nb_try];
  52.  
  53. for(int i=0; i < nb_try; i ++){
  54. ks[i] = _k_min + _k_step * i;
  55. }
  56.  
  57. if (strcmp(method,"ct")==0)
  58. {
  59.  
  60. train(nb_examples,dim,features,labels );// train once for all nb of nbs in ks
  61.  
  62. for(int i=0; i < nb_try; i ++){
  63. if (ks[i] > nb_examples){nb_try=i; break;}
  64. error_validation[i] = 0;
  65. }
  66.  
  67. int i = 0;
  68. #pragma omp parallel shared(nb_examples_test,error_validation,features_test,labels_test,nb_try,ks) private(i)
  69. {
  70. #pragma omp for schedule(dynamic) nowait
  71. for (i=0; i < nb_examples_test; i++)
  72. {
  73. classify_varIoUs_k(dim,features_test[i],labels_test[i],ks,ks[nb_try - 1]); // where error occurs
  74. }
  75. }
  76. for (i=0; i < nb_try; i++)
  77. {
  78. error_validation[i]/=nb_examples_test;
  79. }
  80. }
  81.  
  82. ......
  83. }

更新:

谢谢!我现在正试图通过使用“#pragma omp critical”来纠正classify_varIoUs_k()中写入相同内存问题的冲突:

  1. void KNNClassifier::classify_varIoUs_k(int dim,int k_max) {
  2. ANNpoint queryPt = 0;
  3. ANNidxArray nnIdx = 0;
  4. ANNdistArray dists = 0;
  5.  
  6. queryPt = feature; //for (int i = 0; i < Vignette::size; i++){ queryPt[i] = vignette->content[i];}
  7. nnIdx = new ANNidx[k_max];
  8. dists = new ANNdist[k_max];
  9.  
  10. if(strcmp(_search_neighbors,"brutal") == 0) {// search
  11. _search_struct->annkSearch(queryPt,_eps);
  12. }else if(strcmp(_search_neighbors,"kdtree") == 0) {
  13. _search_struct->annkSearch(queryPt,_eps);
  14. }
  15.  
  16. for (int j = 0; j < nb_ks; j++)
  17. {
  18. scalar_t result = 0.0;
  19. for (int i = 0; i < ks[j]; i++) {
  20. result+=_labels[ nnIdx[i] ]; // Program received signal SIGSEGV,Segmentation fault
  21. }
  22. if (result*label<0)
  23. {
  24. #pragma omp critical
  25. {
  26. errors[j]++;
  27. }
  28. }
  29.  
  30. }
  31.  
  32. delete [] nnIdx;
  33. delete [] dists;
  34.  
  35. }

但是,“result = _labels [nnIdx [i]];”中存在新的段错误错误.有些想法?谢谢!

解决方法

好的,既然你已经声明它在单线程情况下可以正常工作,那么“普通”方法将不起作用.您需要执行以下操作:

>查找并行访问的所有变量
>特别是看看那些经过修改
>不要在共享资源上调用delete
>查看在共享资源上运行的所有库函数 – 检查它们是否不进行分配/释放

这是双重删除的候选人列表:

  1. shared(nb_examples_test,ks)

此外,此代码可能不是线程安全的:

  1. for (int i = 0; i < ks[j]; i++) {
  2. result+=_labels[ nnIdx[i] ];
  3. }
  4. if (result*label<0) errors[j]++;

因为两个或多个进程可能会尝试写入错误数组.

还有一个很好的建议 – 在线程模式下尝试不访问(特别是修改!)任何东西,这不是函数的参数!

猜你在找的C&C++相关文章