벡터입니다.크기 조정 기능이 손상될 때 메모리 크기가 너무 크

StackOverflow https://stackoverflow.com/questions/1615518

  •  06-07-2019
  •  | 
  •  

문제

무슨 일이 일어나 나는 독서 패킷 암호화 및 발생하는 손상된 패킷을 제공하는 다시 매우 큰 임의의 숫자를 위한 길이 있습니다.

size_t nLengthRemaining = packet.nLength - (packet.m_pSource->GetPosition() - packet.nDataOffset);

seckey.SecretValues.m_data.resize(nLengthRemaining);

이 코드에서 m_data 가 std::vector<unsigned char>.nLengthRemaining 가 너무 크로 인해 손상된 데이터 패킷,따라서 크기 조정 기능이 발생합니다.문제가 되지 않는 크기를 조정 throw(우리는 핸들의 예외를 제외하고),그러나 그의 크기를 조정이 손상된 메모리 이미와 이것은 더 많은 예외니다.

내가 무엇을 하고 싶은 알고 있는 경우의 길이는 너무 큰 전에 나는 크기를 조정한 다음에만 전화를 조정하는 경우 그것은 확인된다.가 이 코드를 호출하기 전에하기:

std::vector<unsigned char>::size_type nMaxSize = seckey.SecretValues.m_data.max_size();
if(seckey.SecretValues.m_data.size() + nLengthRemaining >=  nMaxSize) {
    throw IHPGP::PgpException("corrupted packet: length too big.");
}
seckey.SecretValues.m_data.resize(nLengthRemaining);

이 코드를 사용하는 std::벡터 max_size 원 기능을 테스트하는 경우 nLengthRemaining 가 더 크다.하지 않아야 하는 신뢰할 수 있기 때문에,하지만 nLengthRemaining 는 여전히 미만 nMaxSize 지만,분명히 여전히 큰 일으킬 정도의 크기를 조정하여 문제가 있(nMaxSize 었 4xxxxxxxxx 및 nLengthRemaining 은 3xxxxxxxxx).

또한,나지 않은 무엇인지 결정하는 예외의 크기를 조정이다.그것은 std::length_error 지 않는 std::bad_alloc.어떤 예외 그것은 던지는 정말 없는게 너무 중요하지만,나는 호기심을 알고 있습니다.

btw,아,이 코드가 제대로 작동하는 정상적인 경우.이 경우의 손상된 데이터 패킷은 유일한 장소가 미친.도와주세요!감사합니다.

업데이트:

@마이클.지금 나는 그냥 무시하는 패킷의 경우 보다 더 큰 5 메가바이트.에 대해 설명하겠습니다 다른 팀 구성원에 대한 가능성이 확인 패킷(그것은 이미 있을 수 있습니다 내가 그것을 알고하지 않).바로 그런 사람들이 나를 그렇게 생각해주실 분은 바로 정말 버그에서 우리의 버전의 STL,예외가 발생하지 않도 std::예외는 놀란다.난 알아보십시오에서 나는 감독자의 버전은 무엇 STL 우리는 너무 실행(어떻게 필요할 수 있습니다.).

또 다른 업데이트:나는 그냥을 증명하는 그것이 버그에서 STL 버전을 사용하고 내 Visual Studio6 개발 기계입니다.내가 쓴 이 샘플에서는 응용 프로그램:

//VectorMaxSize.cpp :정의 항목에 포인트를 콘솔 응용 프로그램입니다.//

#include "stdafx.h"
#include <vector>
#include <iostream>
#include <math.h>
#include <typeinfo>

typedef std::vector<unsigned char> vector_unsigned_char;

void fill(vector_unsigned_char& v) {
    for (int i=0; i<100; i++) v.push_back(i);
}


void oput(vector_unsigned_char& v) {
    std::cout << "size: " << v.size() << std::endl;
    std::cout << "capacity: " << v.capacity() << std::endl;
    std::cout << "max_size: " << v.max_size() << std::endl << std::endl;
}

void main(int argc, char* argv[]) {
    {
        vector_unsigned_char v;

        fill(v);

        try{
            v.resize(static_cast<size_t>(3555555555));
        }catch(std::bad_alloc&) {
            std::cout << "caught bad alloc exception" << std::endl;
        }catch(const std::exception& x) {
            std::cerr << typeid(x).name() << std::endl;
        }catch(...) {
            std::cerr << "unknown exception" << std::endl;
        }

        oput(v);    
        v.reserve(500);
        oput(v);
        v.resize(500);
        oput(v);
    }

    std::cout << "done" << std::endl;
}

내 VS6dev 기계가 동일한 동작이 있는 암호화 프로젝트,그것은 원인 모든 종류의 혼란이다.을 때 나를 구축하고 실행에 내 Visual Studio2008,기계 크기를 조정하는 것입 std::bad_alloc 예외과 벡터가 손상되지 않을,그냥을 발견하실 수 있습니다!시간 EA 스포츠 미식 축구 도니!

도움이 되었습니까?

해결책

내 생각에는 vector::max_size() 꽤 많은 항상'하드 코딩'일이다-그것은 독립적이 얼마나 많은 메모리 시스템 라이브러리를 준비하는 동적으로 할당합니다.귀하의 문제는 버그가 될 것으로 보인에서 벡터로 구현를 손상시키는 것을 때 할당은 실패합니다.

'버그 수도 너무 강한의 단어입니다. vector::resize() 이의 측면에서 정의 vector::insert() 및 표준 이해 vector::insert():

예외가 발생하는 경우 이외에 복사본을 생성자 또는 할당의 운영자 T 없는 효과

처럼 보이는 시간이 있을 수 있습니다면 resize() 운영이 허용되는 손상 벡터,하지만 여전히 좋은 것으면 작업을 했는 예외 안전한(그리고 나는 생각하지 않을을 줄 기대하는 라이브러리는,그러나 어쩌면 그것을 어렵게 내가 상상하는 것보다).

당신은 몇 가지 합리적인 옵션:

  • 변경 또는 업데이트 라이브러리가 없는 손상을 버그(무엇을 컴파일러/라이브러리 버전을 사용하고 있습니까?)
  • 대신에 대해 검사 vector::max_size() 설정 nMaxSize 당신의 자신의 합리적인 최고 당신은 무엇을 위해야 하지만 사용하는 대신 합니다.

편집:

나는 당신이 사용하는 VC6-가 확실히 버그 vector::resize() 할 수 있는 뭔가를 당신의 문제만을 보고 패치 내가 정직하게 보이지 않는 어떻게(실제로는 그것이 버그 vector::insert(), 지만,언급했듯이, resize() 전화 insert()).난 그것에 가치가 있을 것을 방문하는 Dinkumwares'페이지에 대한 버그 수정을 VC6 고 적용한 해결책을 모색하고 있습니다.

문제도 함께 할 수있는 뭔가가있의 <xmemory> 패치에 있는 페이지 이것이 버그가는 논의가 있지만, vector::insert() 는 전화 _Destroy()vector<> 가 정의는 이름 _Ty 그래서 당신은 실행될 수 있으로는 문제입니다.하나 좋은 것은-당신을 걱정할 필요가 없 관리에 대한 변경 사항을 헤더,Microsoft 은 결코 그들을 감동을 다시.그냥 있는지 확인 패치로 버전을 제어하고 문서화되어 있습니다.

참고에는 스코트 마이어스에서의"효과적인 STL"제안 사용 SGI 의STLPort 의 라이브러리를 더 얻을 STL 보다 지원 제공으로 VC6.수행하지 않았는지 확인하는 방법을 잘 해당 라이브러리 작업(지만 나 또한 사용하지 않은 VC6 와 STL 매우).물론,이동 할 수있는 옵션이 최신 버전의 VC,모든 수단에 의해 수행습니다.


하나 더 편집:

감사에 대한 테스트 프로그램...

VC6 의 _Allocate() 구현을 위한 기본값 할당자(에 <xmemory>)사용하여 서명 int 수를 지정 요소의 할당할 경우 크기에서 전달되는 것은 부정적(분명히 당신이 무엇을 하실에서 테스트 프로그램은 당신이) _Allocate() 기능을 강제로 요청한 할당은 크기로하고 진행됩니다.참고는 제로 크기 할당을 요청하는 것은 거의 항상 성공(하지 않는 vector 를 확인에 대한 어쨌든 실패),그래서 vector::resize() 기능 즐겁게 이동하려고 그 내용으로 새로운 구획,지 않는 아주 큰 충분하다.그래서 힙 손상되면,그것을 가능성이 충돌 잘못된 메모리 페이지와 관계없이-프로그램은 거에요.

그래서인지 요청 VC6 할당보다 더 INT_MAX 체에서 이루어진다.아마도 훌륭한 아이디어에서 대부분의 상황(VC6 또는 그렇지 않으면).

또한,당신은 당신을 유지해야 하는 마음에 VC6 사전 표준 관용구의 반환 0 서 new 할 때는 할당을 던지는 것이 아니라 실패 bad_alloc.

다른 팁

나는 좋은 당신 확인을 위해 데이터의 손상 부르기 전에 라이브러리 함수가 함께 어쩌면 잘못된 인수!

어떤 종류의 사용은 해시 코드 또는 체크인 합계 알고리즘에서의 패킷입니다.할 수 없습에 의존 라이브러리하는 데 도움 당신 때문에 그렇지 않을 할 수 있:그것은 있을 수 있습니 그것에게 손상되었지만 아직도 유효한(의 관점에서 이 라이브러리)크기는 진짜 큰 그래서 그것을 할당하는 예를 들어 768 메가바이트 RAM.이 있는 경우 작동이 충분한 메모리에서 시스템을 수도 있지만 실패하는 경우 다른 프로그램을 실행하는 것을 너무 많이 섭취의 메모리 1024MB 기계입니다.

그래서 위에서 말했듯이:먼저 확인!

나는 아무 생각이 무엇을 의미할 때 당신이 말하는"크기를 조정이 손상된 메모리".어떻게 당신이 결정하는가?

FWIW,내가 동의하지 않는다 마이클의 응답.는 경우 std::vector<>::resize() 에 발생 벡터장,나는 두 개의 가능성:

  1. 중 하나 생성자를 채우는 데 사용되는 새로운 공간(또는 사본 요소의)던졌나
  2. 할당자가 사용 성장하는 벡터았
  3. 또는 벡터 결정하기 전에 손는 요청의 크기가 너무 많이 발생합니다.

std::vector<unsigned char> 우리는 할 수 있게 해제#1 도록,잎#2.를 사용하지 않는 경우에는 모든 특별 할당,다음 std::allocator 를 사용하여야 하며,AFAIK,는 전화 new 하여 메모리를 할당합니다.고 newstd::bad_alloc.그러나,당신이 말할 수 없습니다 이지 어떻게 알려드립니다.

그것이 무엇이든간에,그것이 있어야에서 파생 std::exception, 다,그래서 당신이 할 수있을 찾아웃:

try {
  my_vec.resize( static_cast<std::size_t>(-1) );
} catch(const std::exception& x) {
  std::cerr << typeid(x).name() << '\n';
}

What's 의 결과는?

어쨌든 그것이 무엇이든간에,저는 확실해 손상되지 않 메모리입니다.하나의 버그에서 당신의 std lib 구현(지 않는 경우에,당신이 나에게,을 사용하지 않는 경우에는 아주 오래된 중 하나)또는 당신이 뭔가 잘못된 다른 곳에서.


편집 이제는 당신이 당신 말을 사용하여 VS6...

당신이 있어야 한다고 말했이다.VC6 출시되었 년 이상 전,후 MS 을 잃었 그들의 투표에 표준 위원회가 있기 때문에 그들이 등장하는 회의를 너무 깁니다.Std lib 구현을 그들이 발송되었에서 Dinkumware(좋은)지만,때문에 법적인 문제는 그것을 위해 하나 VC5(아주 나쁜),많이 가지고있는 작은 버그하지 않도에 대한 지원이 멤버 템플릿지만,VC6 컴파일러 지원됩니다.정직하게,무엇을 기대에서 같은 오래된 제품인가요?

수 없는 경우에는 스위치 제 VC 버전(내가 권하고 싶어 VC7.1aka VS.NET 2003 로 하나를 만든 주요 도약을 향한 표준 준수),이상 참조하는 경우 Dinkumware 여전히 판매 VC6t 버전의 자신의 우수한 라이브러리입니다.(사실,저는 놀라게 될 것이지만,그들이 하나를 가지고하는 데 사용되며,...)

로에 대한 예외:이전 VC 버전(이 포함 VC6 포함하지 않습니다 VC8aka VS.NET 2005 년,나에 대한 확실하지 않 VC7.1 만)에 의해 기본 액세스 위반이 잡힐 수 있습에 의해 catch(...).그렇다면 이러한 catch 블록 무언가를 잡았다,당신은 여부를 알 수 없이었 C++예외는 아니다.나의 통보하는 것에만 사용 catch(...) 에 confunction 과 throw; 하기 위해서는 예외에 전달합니다.당신이 경우에,당신은 진정한 충돌에서 AV 의할 수 있는 스택 추적에서 그들을 디버거.지 않는 경우,AV 의 것을 삼켰고 그 다음 당신이 붙어 있는 응용 프로그램으로 사라 졌어요 당신도 광고 있습니다.하지만 아무것도 하지만 중단 AV'ed 응용 프로그램은 아무 의미가 없습니다.AV 은 한 결과 정의되지 않은 동작 그 후,모든 베팅은 꺼져 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top