2017-12-29 80 views
1

여기에 기사를 읽거나 온라인에 게시하면 Eli Bendersky's Website : Binary Representation of Big Numbers이 나오며 함수를 통해 내 IDE에서 테스트하기로 결정했습니다. 이 함수는 & 빌드를 컴파일하지만 코드를 실행할 때 예외를 throw하려고합니다. 쓰기 액세스 위반입니다.쓰기 액세스 예외가 발생하는 함수

/* Note: in and out may be the same string, 
    it will still work OK 
*/ 
void longdiv2(const char* in, char* out) 
{ 
    int carry = 0; 

    while (*in) 
    { 
     int numerator = *in++ - '0'; 
     numerator += carry; 

     carry = (numerator % 2) == 0 ? 0 : 10; 
     *out++ = '0' + (numerator/2); 
    } 

    *out = '\0'; 
} 

I는 다음과 같이 사용 : 여기

는 기능입니다

액세스 위반이 줄에 발생합니다
#include <iostream> 

int main() { 
    char* value = "12345"; 
    char* binResult = '\0'; 

    longdiv2(value, binResult); 

    std::cout << *binResult << std::endl; 

    std::cout << "\nPress any key and enter to quit." << std::endl; 
    char q; 
    std::cin >> q; 

    return 0; 
} 

:

*out++ = '0' + (numerator/2); 

위반이 없다는됩니다 outnullptr이었다.


내가 MS 비주얼 스튜디오에 Win7에 홈 프리미엄 x64를 실행하는 인텔 쿼드 코어 익스트림에 2017 CE이 실행 해요 - 컴파일과 86 콘솔 응용 프로그램으로 내장.

[참고 :] 난 둘 다 C & C++와이 태그 : 기사들이 C를 위해 작성 언급 때문에 나는 그러나 나는 C++에서 동일한 기능을 사용하고, 이런 식으로 태그.

+1

이미 부정적인 비판 ... –

+2

'문자 * binResult = '\ 0'; '기록 효과적으로 동일합니다'문자 * binResult = nullptr; ' – user0042

+1

downvoter에주의하십시오. 그냥'char * binResult = '\ 0';'잘못된 잘못 틀림 –

답변

3

*out++이 유효한 메모리를 가리키고있는 포인터에 액세스하고 있습니다. 따라서 불법적 인 메모리 액세스가 발생한 후 참조를 해제 할 때 액세스 위반이 발생합니다. 이것은 당신이 함수에 통과 할 때 기본적으로 당신이 부패 char*를 전달하는 것입니다 여기에

char binResult[10]; 

작업과 변경 사항을 만들 것입니다.

다른 방법이 또한

binResult =(char*) malloc(10); 
if(binResult == NULL){ 
    perror("Malloc Failed"); 
} 

상세히 설명 할 것, 문제는 포인터가 당신이 결과를 저장할 수있는 버퍼를 가리키는하지 것을 아래로 비등. 에 액세스하려고하면 기본적으로 일부 메모리에 쓰기를 시도하고 있습니다. 권한이 없습니다. 쓰기 액세스 위반). 오류가 발생한 이유는 입니다.

포인터 값을 \0으로 설정하고 액세스하려고하면 더 이상 명확하지 않아야합니다. 첫 번째 반복 자체에서 오류가 발생하여 nullptr에 액세스하게됩니다.

전체 C 코드 : gcc -Wall -Werror progname.c

C++ 해결책이 될 것을

/* Here in and out shouldn't point to same thing */ 

#include <iostream> 
#include <string> 

void longdiv2(std::string in, std::string& out) 
{ 
    int carry = 0; 

    for(auto x:in) 
    { 
     int numerator = x - '0'; 
     numerator += carry; 

     carry = (numerator % 2) == 0 ? 0 : 10; 
     out.push_back('0' + (numerator/2)); 
    } 

} 

int main(void) { 
    std::string value = "12345"; 
    std::string binResult; 

    longdiv2(value, binResult); 

    std::cout<<binResult<<std::endl; 
    return 0; 
} 

같은 :

#include<stdio.h> 
void longdiv2(const char* in, char* out) 
{ 
    int carry = 0; 

    while (*in) 
    { 
     int numerator = *in++ - '0'; 
     numerator += carry; 

     carry = (numerator % 2) == 0 ? 0 : 10; 
     *out++ = '0' + (numerator/2); 
    } 

    *out = '\0'; 
} 


int main(void) { 
    char* value = "12345"; 
    char binResult[10]; 

    longdiv2(value, binResult); 

    printf("%s\n",binResult); 
    return 0; 
} 

gcc 6.3.0를 사용하여 컴파일

06172 

코드를 출력

1

변경 다음

char* binResult = '\0'; 

에 : 설명없이

char binResult[10] {}; 
+0

(컴파일하지 않아야 함) : 아니오 그것은 정수 값입니다. 아마도 경고 일 수도 있지만 포인터를 효과적으로 0으로 설정합니다. –

+0

왜'char * binResult = '\ 0';'는 컴파일하지 말아야합니까? 그것은 완벽하게 유효합니다. – user0042

+0

나는 이미 내 질문에 "컴파일"하고 "빌드"한다고 언급했다. 그것은 런타임에 예외를 던지고있었습니다. 나는 런타임 예외가 무엇인지 안다 : 나의 C는 조금 녹슬었고'C' 스타일의 문자열을 선호하는'C++'std :: string' 이상으로 기억 시키는데 어려움을 겪고 있었다. –