Debug 출력

Debug 출력

Rust에서 디버그 정보를 출력하기 위해, {:?}, {:#?} 포맷과 dbg!() 매크로 등을 사용한다. 보통 (단순한 타입이 아닌) 복합 타입이나 커스텀 타입의 경우 Debug 포맷팅이나 dbg! 매크로를 사용하여 데이타를 출력하곤 한다.

{:?}, {:#?} 포맷

단순한 타입(Primitive 타입)들은 기본적으로 println!("{}",...) 와 같이 {} 을 사용하여 데이타를 출력할 수 있다. {} 포맷은 std::fmt::Display 을 호출하는 것으로 Primitive 타입들을 이 Display 함수를 기본적으로 구현하고 있다.

배열이나 튜플 같은 좀 복잡한 타입이나 struct와 같은 Custom 타입의 경우는 std::fmt::Display 으로 호출하지 않고, {:?} 혹은 {:#?} 와 같은 포맷으로 호출하는데, 이들 포맷은 std::fmt::Debug 을 사용한다. 배열이나 튜플은 이미 std::fmt::Debug을 구현하고 있어서, {:?} 혹은 {:#?} 과 같은 디버깅 포맷을 사용할 수 있다.

아래 예제에서 배열을 출력할 때, {} 을 사용하면 배열은 std::fmt::Display 을 가지지 않기 때문에 에러가 발생하지만, {:?} (혹은 {:#?}) 을 사용하면 배열의 std::fmt::Debug 이 호출되어 데이타가 출력되게 된다.

fn main() {

    let arr: [i32; 5] = [1,2,3,4,5];
    
    //println!("{}", arr); // 에러: doesn't implement `std::fmt::Display`
    println!("{:?}", arr); 
}

구조체(struct)는 Custom 타입으로 std::fmt::Debug 이 기본적으로 구현되어 있지 않지만, 아래와 같이 struct 정의 위에 #[derive(Debug)] 라는 특성(attribute)을 지정하면, std::fmt::Debug 을 사용할 수 있다. #[derive(Debug)] 이 지정된 구조체는 {:?} 혹은 {:#?}을 사용할 수 있는데, {:?}은 한 라인으로 구조체 필드 데이타를 모두 출력하고, {:#?}는 좀 더 예쁘게 여러 라인으로 한 라인 당 하나의 필드 데이타를 출력한다.

#[derive(Debug)]
struct Rect {
    width: u32,
    height: u32
}

fn main() {
    let rect = Rect {
        width: 100,
        height: 50
    };
    println!("{:?}", &rect);
    println!("{:#?}", &rect); 
}

dbg! 매크로

dbg! 매크로는 파라미터에 지정된 변수의 데이타를 출력하는 디버깅 매크로이다. dbg! 매크로는 Primitive 타입과 #[derive(Debug)]이 지정된 구조체(struct)에 사용할 수 있는데, 해당 변수의 데이타를 출력할 뿐 만 아니라, 데이타 앞에 소스파일명과 라인번호를 함께 출력해 준다.

#[derive(Debug)]
struct Rect {
    width: u32,
    height: u32
}

fn main() {
    let mut i = 1;
    i = i + 100;
    dbg!(i);
    
    let rect = Rect {
        width: 100,
        height: 50
    };
    dbg!(&rect); 
}

위 프로그램을 실행하면, 아래와 같이 소스파일명과 라인수가 데이타 값과 함께 출력된다.

[src/main.rs:10] i = 101
[src/main.rs:16] &rect = Rect {
    width: 100,
    height: 50,
}

This site is not affiliated with or endorsed by the Rust Foundation or Rust Project.