最终形成指南支持库的无效内存访问
Invalid memory access with finally form the Guideline Support Library
我正在试验指南支持库。
此代码运行良好,valgrind 没有显示内存问题
#include <gsl>
#include <iostream>
int main() {
const int length = 10;
int *arr = new int [length];
auto _ = gsl::finally([arr] { delete[] arr; });
for (int i = 0; i<length; i++){
arr[i] = i;
}
for (int i = 0; i<length; i++){
std::cout << arr[i] << " ";
}
}
如果删除 finally
语句对 auto _
的赋值,valgrind 将显示以下无效 reads/writes。为什么我需要将 finally 语句赋给一个值,这个值之后就不再需要了?
我使用 gsl-lite,版本 0.28.0。
损坏的代码:
#include <gsl>
#include <iostream>
int main() {
const int length = 10;
int *arr = new int [length];
gsl::finally([arr] { delete[] arr; });
for (int i = 0; i<length; i++){
arr[i] = i;
}
for (int i = 0; i<length; i++){
std::cout << arr[i] << " ";
}
}
Valgrind 输出:
==15802== Memcheck, a memory error detector
==15802== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15802== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==15802== Command: ./a.out
==15802==
==15802== Invalid write of size 8
==15802== at 0x400E1A: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e040 is 0 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid write of size 8
==15802== at 0x400E24: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e050 is 16 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid write of size 4
==15802== at 0x400E2B: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e060 is 32 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid write of size 4
==15802== at 0x400E34: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e064 is 36 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid read of size 4
==15802== at 0x400E45: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e040 is 0 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
0 1 2 3 4 5 6 7 8 9 ==15802==
==15802== HEAP SUMMARY:
==15802== in use at exit: 0 bytes in 0 blocks
==15802== total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==15802==
==15802== All heap blocks were freed -- no leaks are possible
==15802==
==15802== For counts of detected and suppressed errors, rerun with: -v
==15802== ERROR SUMMARY: 16 errors from 5 contexts (suppressed: 4 from 4)
这里只是猜测,但似乎当 gsl::finally
returns 的对象被销毁时,它调用释放内存的 lambda。
在第一种情况下,这个返回的对象被分配给变量 _
,它被销毁一次 main
returns。在第二种情况下,对象在调用 gsl::finally
后立即被销毁,导致之后对内存的任何访问都是无效的。
我正在试验指南支持库。
此代码运行良好,valgrind 没有显示内存问题
#include <gsl>
#include <iostream>
int main() {
const int length = 10;
int *arr = new int [length];
auto _ = gsl::finally([arr] { delete[] arr; });
for (int i = 0; i<length; i++){
arr[i] = i;
}
for (int i = 0; i<length; i++){
std::cout << arr[i] << " ";
}
}
如果删除 finally
语句对 auto _
的赋值,valgrind 将显示以下无效 reads/writes。为什么我需要将 finally 语句赋给一个值,这个值之后就不再需要了?
我使用 gsl-lite,版本 0.28.0。
损坏的代码:
#include <gsl>
#include <iostream>
int main() {
const int length = 10;
int *arr = new int [length];
gsl::finally([arr] { delete[] arr; });
for (int i = 0; i<length; i++){
arr[i] = i;
}
for (int i = 0; i<length; i++){
std::cout << arr[i] << " ";
}
}
Valgrind 输出:
==15802== Memcheck, a memory error detector
==15802== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==15802== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==15802== Command: ./a.out
==15802==
==15802== Invalid write of size 8
==15802== at 0x400E1A: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e040 is 0 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid write of size 8
==15802== at 0x400E24: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e050 is 16 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid write of size 4
==15802== at 0x400E2B: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e060 is 32 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid write of size 4
==15802== at 0x400E34: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e064 is 36 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
==15802== Invalid read of size 4
==15802== at 0x400E45: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Address 0x4c3e040 is 0 bytes inside a block of size 40 free'd
==15802== at 0x4A0862D: operator delete[](void*) (vg_replace_malloc.c:621)
==15802== by 0x400E04: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802== Block was alloc'd at
==15802== at 0x4A07898: operator new[](unsigned long) (vg_replace_malloc.c:423)
==15802== by 0x400DF4: main (in /data/home/gwe/projekte/clean_code/gsl/a.out)
==15802==
0 1 2 3 4 5 6 7 8 9 ==15802==
==15802== HEAP SUMMARY:
==15802== in use at exit: 0 bytes in 0 blocks
==15802== total heap usage: 1 allocs, 1 frees, 40 bytes allocated
==15802==
==15802== All heap blocks were freed -- no leaks are possible
==15802==
==15802== For counts of detected and suppressed errors, rerun with: -v
==15802== ERROR SUMMARY: 16 errors from 5 contexts (suppressed: 4 from 4)
这里只是猜测,但似乎当 gsl::finally
returns 的对象被销毁时,它调用释放内存的 lambda。
在第一种情况下,这个返回的对象被分配给变量 _
,它被销毁一次 main
returns。在第二种情况下,对象在调用 gsl::finally
后立即被销毁,导致之后对内存的任何访问都是无效的。