C++

C++23 : stacktrace

Sorting 2022. 11. 27. 16:16
반응형

Visual Studio 2022 의 최신 C++ 도입내용을 살펴보다 반가운 내용이 있어 오랜만에 블로그를 열었다.

드디어 콜스택을 확인할 수 있는 헤더를 VS에서 사용할 수 있게 되었다.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0881r7.html

 

A Proposal to add stacktrace library

template string to_string(const basic_stacktrace & st); template basic_ostream & operator<< (basic_ostream & os, const basic_stacktrace & st); template string to_string(const vector & st); template basic_ostream & operator<< (basic_ostream & os, const vect

www.open-std.org

 

C++에서 콜스택을 로깅하려면 각 운영체제 별로 제공하는 API를 통해 StackWalker 를 별도로 구현해야했다.

이제 새로 C++를 배우시는 학생분들은 이러한 어려움에서 한발 벗어날 수 있을 것으로 보이고,

가르치는 사람 입장에서도 콜스택을 보다 빠른 시점에 직관적으로 가르칠 수 있을 것으로 보인다.

 

stacktrace 사용법


사용법은 간단하다.

먼저 VS2022 C++프로젝트에서, 프로젝트 속성의 C++ 언어 표준을 /std:c++latest 로 설정한다.

위와 같이 프로젝트 설정을 할 경우 사용할 수 있다.

 

그리고 stacktrace 헤더를 포함시킨 뒤 다음과 같이 함수 하나만 호출해주면 된다.

std::stacktrace::current()

#include <iostream>
#include <stacktrace>

int main()
{
    std::stacktrace callstack = std::stacktrace::current();
    std::cout << callstack << std::endl;
}

 

그러면 다음과 같이 콜스택 정보를 바로 확인할 수 있다.

std::to_string() 등으로 문자열로 변환하여 로깅하면 

문제되는 상황의 콜스택을 쉽게 로깅할 수 있을 것이다.

 

결과 :

0> C:\source\repos\CppPractice\CppPractice\stacktrace.cpp(6): CppPractice!main+0x63
1> D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(79): CppPractice!invoke_main+0x39
2> D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(288): CppPractice!__scrt_common_main_seh+0x12E
3> D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl(331): CppPractice!__scrt_common_main+0xE
4> D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp(17): CppPractice!mainCRTStartup+0xE
5> KERNEL32!BaseThreadInitThunk+0x10
6> ntdll!RtlUserThreadStart+0x2B

 

응용


 

std::stacktrace 는 다음과 같이 stacktrace_entry 의 스트림이다.

using stacktrace = basic_stacktrace<allocator<stacktrace_entry>>;

따라서 다음과 같이 콜스택을 순회하며, 필요한 정보만을 기입할 수도 있다.

 

#include <iostream>
#include <stacktrace>

int main()
{
    std::stacktrace callstack = std::stacktrace::current();
    
    for (auto& entry : callstack)
    {
        std::cout << "source_file : " << entry.source_file() << std::endl;
        std::cout << "source_line : " << entry.source_line() << std::endl;
        std::cout << "description : " << entry.description() << std::endl;
        std::cout << "-----------" << std::endl;
    }
}

 

결과 : 

source_file : C:\source\repos\CppPractice\CppPractice\stacktrace.cpp
source_line : 6
description : CppPractice!main+0x63
-----------
source_file : D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl
source_line : 79
description : CppPractice!invoke_main+0x39
-----------
source_file : D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl
source_line : 288
description : CppPractice!__scrt_common_main_seh+0x12E
-----------
source_file : D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl
source_line : 331
description : CppPractice!__scrt_common_main+0xE
-----------
source_file : D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp
source_line : 17
description : CppPractice!mainCRTStartup+0xE
-----------
source_file :
source_line : 0
description : KERNEL32!BaseThreadInitThunk+0x10
-----------
source_file :
source_line : 0
description : ntdll!RtlUserThreadStart+0x2B
-----------

 

 

보다 자세한 내용은 다음의 문서에서 확인할 수 있다.

https://en.cppreference.com/w/cpp/header/stacktrace

 

Standard library header <stacktrace> (C++23) - cppreference.com

This header is part of the general utility library. [edit] Synopsis namespace std { // class stacktrace_entry class stacktrace_entry;   // class template basic_stacktrace template class basic_stacktrace;   // basic_stacktrace typedef names using stacktra

en.cppreference.com

 

반응형