【发布时间】:2021-11-06 16:16:46
【问题描述】:
在这两种情况下,我都使用完全相同的二维数组(它是类的一个字段)。第二个lsh_distances 不允许我删除[] 析构函数中的内部一维数组,并给出free(): invalid size Aborted (core dumped) 的错误。如果我不使用 for 循环删除 [] 内部数组,我当然会有内存泄漏(使用 valgrind 检查)。
为什么会发生这种情况?这没有道理。我不会在其他任何地方删除lsh_distances,我实际上可以打印析构函数中的值。
帮助
这里是代码。
long long int NearestNeighboursSearch::calculate_exact_distances() {
unsigned int q_size = query_dataset.points.size();
unsigned int ind_size = index_dataset.points.size();
exact_distances = new long double*[q_size];
for (int i = 0 ; i < q_size ; i++) {
exact_distances[i] = new long double[ind_size];
}
chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
for (int i = 0 ; i < q_size ; i++) {
for (int j = 0 ; j < ind_size ; j++) {
exact_distances[i][j] = used_distance(*query_dataset.points.at(i), *index_dataset.points.at(j));
}
}
chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
return chrono::duration_cast<chrono::milliseconds>(end - begin).count();
}
long long int NearestNeighboursSearch::calculate_lsh_distances() {
unsigned int q_size = query_dataset.points.size();
unsigned int ind_size = index_dataset.points.size();
lsh_distances = new long double*[q_size];
for (int i = 0 ; i < q_size ; i++) {
lsh_distances[i] = new long double[ind_size];
for (int j = 0 ; j < ind_size ; j++) {
lsh_distances[i][j] = -1.0; // not calculated
}
}
// calculate and fill only distances between points that hash into the same bucket for the L hash tables
chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
for (int i = 0 ; i < q_size ; i++) {
Point *p1 = query_dataset.points.at(i);
Bucket **buckets = index_dataset.get_buckets_for_point(p1); // L buckets
for (int j = 0 ; j < index_dataset.get_hashtables_count(); j++) {
for (int k = 0 ; k < buckets[j]->points.size() ; k++) { // might be empty
const Point *p2 = buckets[j]->points[k];
// update appropriate distance at [i, p2->pos]
lsh_distances[i][p2->pos] = used_distance(*p1, *p2);
}
}
delete[] buckets;
}
chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
return chrono::duration_cast<chrono::milliseconds>(end - begin).count();
}
NearestNeighboursSearch::~NearestNeighboursSearch() {
if (exact_distances != NULL) {
for (int i = 0; i < query_dataset.points.size(); i++) {
delete[] exact_distances[i];
}
delete[] exact_distances;
}
if (lsh_distances != NULL) {
// TODO: Somehow this causes an error (it makes no sense to me)
for (int i = 0; i < query_dataset.points.size(); i++) {
delete[] lsh_distances[i];
}
delete[] lsh_distances;
}
}
编辑:我按照建议使用 valgrind 进行了运行。我得到了这个:
==376== Invalid write of size 4
==376== at 0x11508A: NearestNeighboursSearch::calculate_lsh_distances() (neighbour_search.cpp:66)
==376== by 0x10B2CA: main (lsh_main.cpp:132)
==376== Address 0x4e385c0 is 16 bytes before a block of size 160 alloc'd
==376== at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==376== by 0x114F17: NearestNeighboursSearch::calculate_lsh_distances() (neighbour_search.cpp:52)
==376== by 0x10B2CA: main (lsh_main.cpp:132)
==376==
==376== Invalid write of size 2
==376== at 0x11508A: NearestNeighboursSearch::calculate_lsh_distances() (neighbour_search.cpp:66)
==376== by 0x10B2CA: main (lsh_main.cpp:132)
==376== Address 0x4e385c8 is 8 bytes before a block of size 160 alloc'd
==376== at 0x483C583: operator new[](unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==376== by 0x114F17: NearestNeighboursSearch::calculate_lsh_distances() (neighbour_search.cpp:52)
==376== by 0x10B2CA: main (lsh_main.cpp:132)
==376==
我将对此进行调查...看来 p2->pos 不知何故为
【问题讨论】:
-
请创建一个minimal reproducible example。像这样的崩溃通常是由于在程序的某些其他部分中写入越界而导致的,而找到它的最简单方法是编译并运行一个实际的测试用例,可能使用诸如 AddressSanitizer 或 valgrind 之类的工具。如果您还没有,您也应该自己尝试这些工具。
标签: c++ memory delete-operator