C++ 액세스 위반 예외 발생

조회수 6871회
#include <iostream>
#include <stdlib.h>
#include <ctime>

class Date
{
private:
    time_t t = time(NULL);
    struct tm* ptime = localtime(&t);

    int year = ptime->tm_year + 1900;
    int month = ptime->tm_mon + 1;
    int day = ptime->tm_mday;
public:
    int getyear() {
        return year;
    }
    int getmonth() {
        return month;
    }
    int getday() {
        return day;
    }
};

int main(void) {
    Date currtime;
    char* pc1 = new char[11];
    if (pc1 == NULL) {
        printf("동적 메모리 할당에 실패했습니다.\n");
        exit(1);
    }
    char* pc2 = new char[5];
    if (pc2 == NULL) {
        printf("동적 메모리 할당에 실패했습니다.\n");
        exit(1);
    }
    int num, byear, bmonth, bday;
    int curryear = currtime.getyear();
    int currmonth = currtime.getmonth();
    int currday = currtime.getday();

    printf("학과명, 학번, 이름, 생년월일(생년 월 일)을 순서대로 입력하시오 > ");
    scanf_s("%s %d %s %d %d %d", pc1, 11, &num, pc2, 5, &byear, &bmonth, &bday);
    printf("%s %d %s님 %d년 %d월 %d일생 %d년 %d월 %d일 현재 나이는 %d세 입니다.", *pc1, num, *pc2, byear, bmonth, bday, curryear, currmonth, currday, curryear - byear + 1);

    delete(pc1); delete(pc2);

    return 0;
}

위의 프로그램을 실행하는데 계속해서 main함수의 scanf_s 줄에서

0x7AD01F4C(ucrtbased.dll)에(Project2.exe의) 처리되지 않은 예외가 있습니다. 
0xC0000005: 0xFFFFFFCD 위치를 읽는 동안 액세스 위반이 발생했습니다.

라는 예외가 발생합니다. scanf_s 말고 scanf를 써도, scanf_s로 문자열을 입력받을 때에는 메모리 크기를 지정해줘야한다해서 메모리 크기도 지정했으나 예외가 계속 발생합니다. SDL검사같은 것도 비활성화시켜도봤고 이거저거 다해봤어요.. 당최 해결을 못하겠네요. Visual Studio 사용중입니다.

2 답변

  • 크게 2곳이 문제입니다.

    우선 학과명과 이름을 입력하기 위한 공간이 너무 적어요. 넉넉히 늘려야 합니다.

    char* pc1 = new char[11];
    char* pc2 = new char[5];
    

    위 코드를 예를 들어 아래와 같이 수정해야 합니다. 이름을 받기 위한 충분한 공간을 확보하지 못하면 공간보다 더 긴 문자열이 입력되었을 때 문제가 생길 수 있습니다.

    char* pc1 = new char[20];
    char* pc2 = new char[20];
    

    두번째 문제는 printf로 문자열을 출력할 때에 %s와 매칭된 곳에 주소값을 넣어줘야 하는데 질문에서는 *pc1과 같이 주소를 넣지 않고 주소를 통한 실제 값을 넣었습니다.

    printf("%s %d %s님 %d년 %d월 %d일생 %d년 %d월 %d일 현재 나이는 %d세 입니다.", *pc1, num, *pc2, byear, bmonth, bday, curryear, currmonth, currday, curryear - byear + 1);
    

    위의 코드를 아래와 같이 수정하세요.

    printf("%s %d %s님 %d년 %d월 %d일생 %d년 %d월 %d일 현재 나이는 %d세 입니다.", pc1, num, pc2, byear, bmonth, bday, curryear, currmonth, currday, curryear - byear + 1);
    

    아래 전체 코드와 결과 참고하세요.

    • 코드
    #include <iostream>
    #include <stdlib.h>
    #include <ctime>
    
    class Date
    {
    private:
        time_t t = time(NULL);
        struct tm* ptime = localtime(&t);
    
        int year = ptime->tm_year + 1900;
        int month = ptime->tm_mon + 1;
        int day = ptime->tm_mday;
    public:
        int getyear() {
            return year;
        }
        int getmonth() {
            return month;
        }
        int getday() {
            return day;
        }
    };
    
    int main(void) {
        Date currtime;
        char* pc1 = new char[20];
        if (pc1 == NULL) {
            printf("동적 메모리 할당에 실패했습니다.\n");
            exit(1);
        }
        char* pc2 = new char[20];
        if (pc2 == NULL) {
            printf("동적 메모리 할당에 실패했습니다.\n");
            exit(1);
        }
        int num, byear, bmonth, bday;
        int curryear = currtime.getyear();
        int currmonth = currtime.getmonth();
        int currday = currtime.getday();
    
        printf("학과명, 학번, 이름, 생년월일(생년 월 일)을 순서대로 입력하시오 > ");
        scanf_s("%s %d %s %d %d %d", pc1, 20, &num, pc2, 20, &byear, &bmonth, &bday);
        printf("%s %d %s님 %d년 %d월 %d일생 %d년 %d월 %d일 현재 나이는 %d세 입니다.", pc1, num, pc2, byear, bmonth, bday, curryear, currmonth, currday, curryear - byear + 1);
    
        delete(pc1); delete(pc2);
    
        return 0;
    }
    
    • 결과

    이미지

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 그러면 정확하게 액세스 위반 예외가 발생한 이유는 무엇인가요? 접근해서는 안되는 메모리 영역에 접근하면 발생하게 된다는 예외라는데 학과명과 이름을 입력하기 위한 공간이 부족해서 접근해서는 안되는 메모리 영역까지 주소가 할당되게 된것인가요? 그리고 포인터형 변수에서 그 주소 자체의 값이 아닌 주소에 있는 실제값을 가져올 때에는 *을 붙이는게 아닌가요? 알 수 없는 사용자 2021.3.5 00:02
    • 무슨 컴파일러와 운영체제를 쓰시는지 모르겠으나 저는 비주얼 스튜디오 2019와 윈도우 10을 쓰는데 액세스 위반 예외는 발생하지 않았습니다. 참고로 질문의 코드를 빌드했을 때 다음과 같은 경고가 떴었습니다. "(45,12): warning C4477: 'printf' : 서식 문자열 '%s'에 'char *' 형식의 인수가 필요하지만 variadic 인수 3의 형식이 'int'입니다." 알 수 없는 사용자 2021.3.5 01:00
  • vs2015 로 질문자의 코드를 컴파일해서 실행시켜보니 동일한 오류가 발생합니다. 디버그모드로 실행하여 예외가 발생했을 때의 스택을 살펴보면 다음과 같습니다.

        ucrtbased.dll!common_strnlen_c<0,unsigned char>(const unsigned char * const string, const unsigned int maximum_count) 줄 72    C++
        ucrtbased.dll!common_strnlen_simd<0,1,unsigned char>(const unsigned char * const string, const unsigned int maximum_count) 줄 130  C++
        ucrtbased.dll!common_strnlen<0,unsigned char>(const unsigned char * const string, const unsigned int maximum_count) 줄 185 C++
        ucrtbased.dll!strnlen(const char * string, unsigned int maximum_count) 줄 201  C++
        ucrtbased.dll!__crt_stdio_output::output_processor<char,__crt_stdio_output::string_output_adapter<char>,__crt_stdio_output::standard_base<char,__crt_stdio_output::string_output_adapter<char> > >::type_case_s_compute_narrow_string_length(const int maximum_length, char __formal) 줄 2281  C++
        ucrtbased.dll!__crt_stdio_output::output_processor<char,__crt_stdio_output::string_output_adapter<char>,__crt_stdio_output::format_validation_base<char,__crt_stdio_output::string_output_adapter<char> > >::type_case_s() 줄 2268 C++
        ucrtbased.dll!__crt_stdio_output::output_processor<char,__crt_stdio_output::stream_output_adapter<char>,__crt_stdio_output::standard_base<char,__crt_stdio_output::stream_output_adapter<char> > >::state_case_type() 줄 2012  C++
        ucrtbased.dll!__crt_stdio_output::output_processor<char,__crt_stdio_output::stream_output_adapter<char>,__crt_stdio_output::standard_base<char,__crt_stdio_output::stream_output_adapter<char> > >::process() 줄 1657  C++
        ucrtbased.dll!common_vfprintf::__l2::<람다>() 줄 46  C++
        ucrtbased.dll!__crt_seh_guarded_call<int>::operator()<void <람다>(void),int <람다>(void) &,void <람다>(void) >(__acrt_lock_stream_and_call::__l2::void <람다>(void) && setup, common_vfprintf::__l2::int <람다>(void) & action, __acrt_lock_stream_and_call::__l2::void <람다>(void) && cleanup) 줄 204    C++
        ucrtbased.dll!__acrt_lock_stream_and_call<int <람다>(void) >(_iobuf * const stream, common_vfprintf::__l2::int <람다>(void) && action) 줄 256  C++
        ucrtbased.dll!common_vfprintf<__crt_stdio_output::standard_base,char>(const unsigned __int64 options, _iobuf * const stream, const char * const format, __crt_locale_pointers * const locale, char * const arglist) 줄 34  C++
        ucrtbased.dll!__stdio_common_vfprintf(unsigned __int64 options, _iobuf * stream, const char * format, __crt_locale_pointers * locale, char * arglist) 줄 58    C++
    >   ConsoleApplication5.exe!_vfprintf_l(_iobuf * const _Stream, const char * const _Format, __crt_locale_pointers * const _Locale, char * _ArgList) 줄 639 C++
        ConsoleApplication5.exe!printf(const char * const _Format, ...) 줄 954 C++
    

    예외는 printf 쪽에서 발생했던 거구요. 더 정확한 원인은 디버그모드로 실행하여 살펴보시기 바랍니다.

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)