Valgrind는 힙에 남아있는 객체에 대한 느린 참조를 감지하는 데 유용합니다. 그러나 스택에서 범위를 벗어나는 변수에 대한 참조가 오래 머무르는 경우에는이 기능이없는 것 같습니다. 예를 들어 CharHolder('x')
가 빨리 p1
의 구성이 완료되면 소멸되므로 p1
와C++에서 범위를 벗어난 스택 변수에 대한 참조를 검색하는 방법은 무엇입니까?
#include <iostream>
struct CharHolder {
const char ch;
CharHolder(char _ch) : ch(_ch) {}
};
struct Printer {
const CharHolder& ref;
Printer(const CharHolder& _ref) : ref(_ref) {}
void print() {
std::cout << &ref << ": " << ref.ch << std::endl;
}
};
int main() {
// g++ -O0: prints 'x'
// g++ -O3: prints undefined character
Printer p1(CharHolder('x'));
p1.print();
// g++: prints undefined character
CharHolder* h = new CharHolder('x');
Printer p2(*h);
delete h;
p2.print();
}
첫 번째 예는, 프린터가 범위 밖 스택 변수에 대한 참조를 유지 한 것이다. p2
와
p2
시도
print()
에서 참조하기 전에 free되기를되는 더미 변수에 대한 참조를 유지 한 것이다.
Valgrind의 두 번째 예를 뿌려 :
==82331== Invalid read of size 1
==82331== at 0x400A8E: Printer::print()
==82331== by 0x400967: main
==82331== Address 0x5a1c040 is 0 bytes inside a block of size 1 free'd
==82331== at 0x4C2C2BC: operator delete(void*)
==82331== by 0x40095F: main
어떻게 아마도 Valgrind의 같은 도구를 사용하여 제 1 종 오류를 감지 할 수 있습니까?
'valgrind'는 정적 분석 도구가 아닙니다. – immibis
필자가 전달한 함수 인수보다 오래 지속되는 방식으로 전달 된 참조를 저장하는 것은 좋지 않은 아이디어 인 객체 레슨 (말장난 의도) 일뿐입니다. 모든 호출에 대해 전달 된 참조는 임시 객체를 참조 할 수 있습니다. 돌아 오면 잘못된 개체를 참조하게되고 회원은 쓸모 없게됩니다. 그러한 상황에 대한 경고를 생성하기 위해 컴파일러를 만들어야 할 수도 있습니다. –
@BlairHoughton - 컴파일러가 임시 참조를 매개 변수로 전달하는 함수 호출을 컴파일 할 때 호출 된 함수가 전달 된 참조를 어딘가에 저장한다는 것을 어떻게 알 수 있습니까? 소스 코드를 호출 된 함수에, 알려진 기록의 어떤 시점에서, 시간이 오래 전에 시작 되었기 때문에? –