문제

alloca() 를 할당하는 메모리에 스택보다는 힙의 경우와 같이 malloc().그래서 내가 다시 돌아올 때 일상에서 메모리를 해제됩니다.그래서,실제로 이를 해결이 내 문제의 해방까지 동적으로 할당되는 메모리.유롭게 할당되는 메모리를 통해 malloc() 중요한 두통과하는 경우게 이르는 모든 종류의 메모리 문제입니다.

왜 사용 alloca() 낙담에도 불구하고 위의 기능이?

도움이 되었습니까?

해결책

대답은 바로 거기에 있습니다 man 페이지 (적어도 켜져 있습니다 리눅스):

반환 값 Alloca () 함수는 할당 된 공간의 시작 부분에 대한 포인터를 반환합니다. 할당으로 인해 스택 오버 플로우가 발생하면 프로그램 동작이 정의되지 않습니다.

그것은 결코 사용해서는 안된다고 말하는 것은 아닙니다. 내가 작업하는 OSS 프로젝트 중 하나는 광범위하게 사용하며, 당신이 그것을 남용하지 않는 한 (alloca'큰 가치), 괜찮습니다. "수백 바이트"마크를 지나면 사용할 시간입니다. malloc 대신 친구. 여전히 할당 실패를 얻을 수 있지만 적어도 스택을 날려 버리는 대신 실패를 표시 할 수 있습니다.

다른 팁

내가 가진 가장 기억에 남는 버그 중 하나는 사용한 인라인 함수와 관련이있었습니다. alloca. 프로그램 실행의 임의의 지점에서 스택 오버플로 (스택에 할당하기 때문에)로 나타납니다.

헤더 파일에서 :

void DoSomething() {
   wchar_t* pStr = alloca(100);
   //......
}

구현 파일에서 :

void Process() {
   for (i = 0; i < 1000000; i++) {
     DoSomething();
   }
}

그래서 컴파일러가 감소한 일이 일어났습니다 DoSomething 기능과 모든 스택 할당이 내부에서 발생했습니다 Process() 기능을 수행하고 스택을 불어냅니다. 내 방어에서 (그리고 나는 문제를 발견 한 사람이 아니 었습니다. 나는 그것을 고칠 수 없었을 때 선임 개발자 중 한 명에게 울어야했습니다) alloca, 그것은 ATL 문자열 변환 매크로 중 하나였습니다.

따라서 교훈은 - 사용하지 않는 것입니다 alloca 당신이 생각할 수 있다고 생각하는 기능에서.

오래된 질문이지만 아무도 가변 길이 배열로 대체되어야한다고 언급하지 않았습니다.

char arr[size];

대신에

char *arr=alloca(size);

표준 C99에 있으며 많은 컴파일러에서 컴파일러 확장으로 존재했습니다.

Alloca ()는 표준 로컬 변수를 사용할 수없는 경우 크기를 런타임에 결정해야하며 이 기능이 반환 된 후에도 Alloca ()에서 얻은 포인터가 사용되지 않을 것이라고 절대 보장합니다..

당신은 당신이한다면 상당히 안전 할 수 있습니다

  • 포인터 또는 포함하는 것을 반환하지 마십시오.
  • 힙에 할당 된 구조에 포인터를 저장하지 마십시오.
  • 다른 스레드가 포인터를 사용하도록하지 마십시오

실제 위험은 다른 사람이 언젠가 이러한 조건을 위반할 가능성에서 비롯됩니다. 이를 염두에두고 버퍼를 텍스트를 형식화하는 함수로 전달하는 것이 좋습니다. :)

언급 한 바와 같이 이 뉴스 그룹 게시, 사용 이유 몇 가지 이유가 있습니다 alloca 어렵고 위험한 것으로 간주 될 수 있습니다.

  • 모든 컴파일러가 지원되는 것은 아닙니다 alloca.
  • 일부 컴파일러는 의도 된 동작을 해석합니다 alloca 다르게,이를 지원하는 컴파일러 간에도 휴대 성이 보장되지 않습니다.
  • 일부 구현은 버기입니다.

한 가지 문제는 표준이 아니지만 널리 지원되지만 표준이 아니라는 것입니다. 다른 것들이 동일하기 때문에 항상 공통 컴파일러 확장보다는 표준 기능을 사용합니다.

여전히 alloca 사용하지 않는 이유는?

내가 감지하지 않으면 그러한 합의입니다.많이 강한 장점;몇 단점:

  • C99 제공하는 가변 길이 배열하는 것이 종종 사용될 우선적으로 표기법의 일관성과 함께 고정 길이 배열하고 직관적 인 전체
  • 많은 시스템을 적은 전반적으로 메모리 주소 공간에 사용할 스택보다 그들에 대한 힙 만드는 프로그램으로 약간 더 취약하는 메모리를 소모(을 통해 stack overflow):이것으로 볼 수 있습니다 좋거나 나쁜 일 이유 중 하나는 스택하지 않는 자동으로 성장하는 방법으로 힙 않는 것입을 방지하 제어 프로그램에서는 많은 부정적인 영향에 전체 기계
  • 에서 사용할 때 더 많은 지역의 범위(예: whilefor 루프)또는 여러 가지 범위,메모리 누적당 반복/범위 및 출시할 때까지 기능이 종료됩니다.이러한 방식으로 정상적인 변수에 정의된 범위의 구조물(예: for {int i = 0; i < 2; ++i) { X } 을 것이 축적 alloca-ed 요청한 메모리에서의 X,그러나 메모리를 위한 고정형 배열 재활용 당 반복).
  • 현대 컴파일러에 노출되지 않도록 주의하십시오 inline 함수를 호출하는 alloca, 하지만 경우에 당신은 그들이 다음 alloca 일어날 것입니다에서 호출자의 컨텍스트(예:스까지 공개되지 않습니다 호출자를 반환)
  • 오래 전에 alloca 에서 전환 non-휴대용 기능/해킹을 표준화된 확장자만,일부 부정적인 인식을 수 있습 유지
  • 일생을 바인딩 기능 범위,지 않을 수도 있습니다 또는 맞게 프로그래머보다 더 malloc의 명시적 제어
  • 하는 데 사용 malloc 을 장려에 대해 생각하고 할당 해제-면 관리를 통해 래퍼 기능(예를 들어, WonderfulObject_DestructorFree(ptr)음),는 기능을 제공점 구현에 대한 정 작업(닫기 같이 파일기술자를 확보,포인터 내부 또는 일부 기록)없이 명시적 변경 내용을 클라이언트 코드:때로는 그것의 모델을 채택하는 일관
    • 이사 OO 스타일의 프로그래밍,그것은 자연을 원하는 뭔가 WonderfulObject* p = WonderfulObject_AllocConstructor(); -가능한 경우에는"생성자"가 반환하는 함수 malloc-ed 메모리(으로 메모리에 남아 있는 할당한 후에는 반환 값에 저장할 p어),하지만하지 않는 경우에는"생성자"사용 alloca
      • 매크로전 WonderfulObject_AllocConstructor 을 달성할 수 있었습 이지만"매크로는 악에서"그들이 서로 충돌하는 다른 비 매크로 코드를 만들지 않은 대체과 그에 따른 어려운 문제를 진단
    • free 작업에 의해 검색할 수 있습 ValGrind,정화 등입니다.그러나 누락하는"소멸자는"수없는 항상 감지에서는 모두 하나의 매우 얇은 혜택의 측면에서의 집행위 사용일 alloca() 구현(등 GCC)에 사용하는 인라인된 매크로 alloca(), 므로 런타임의 대체 메모리 사용량 진단 도서관 수 없는 방법입 malloc/realloc/free (예:전기 담)
  • 일부를 구현에는 미묘한 문제점:예를 들어,리눅스 맨페이지에서 확인하십시오:

    많은 시스템에서 alloca()내에서 사용할 수 없습의 목록을 인수의 함수 호출하기 때문에 스택에 공간을 예약에 의해 alloca()에 나타납니다 스택 중간에서 공간의 기능에 대해 인수입니다.


이 질문은 태그 C 지만,C++프로그래머로 나는 C++을 사용하여 잠재적인 유틸리티의 alloca:아래 코드(고 여기에서 ideone)를 만듭니다 벡터 다르게 추적형 다형성 형태는 스택 할당된(함께 일생이 있음을 돌려주는 함수)보다는 오히려 힙 할당됩니다.

#include <alloca.h>
#include <iostream>
#include <vector>

struct Base
{
    virtual ~Base() { }
    virtual int to_int() const = 0;
};

struct Integer : Base
{
    Integer(int n) : n_(n) { }
    int to_int() const { return n_; }
    int n_;
};

struct Double : Base
{
    Double(double n) : n_(n) { }
    int to_int() const { return -n_; }
    double n_;
};

inline Base* factory(double d) __attribute__((always_inline));

inline Base* factory(double d)
{
    if ((double)(int)d != d)
        return new (alloca(sizeof(Double))) Double(d);
    else
        return new (alloca(sizeof(Integer))) Integer(d);
}

int main()
{
    std::vector<Base*> numbers;
    numbers.push_back(factory(29.3));
    numbers.push_back(factory(29));
    numbers.push_back(factory(7.1));
    numbers.push_back(factory(2));
    numbers.push_back(factory(231.0));
    for (std::vector<Base*>::const_iterator i = numbers.begin();
         i != numbers.end(); ++i)
    {
        std::cout << *i << ' ' << (*i)->to_int() << '\n';
        (*i)->~Base();   // optionally / else Undefined Behaviour iff the
                         // program depends on side effects of destructor
    }
}

다른 모든 대답은 정확합니다. 그러나, 당신이 사용하려는 것이 alloca() 합리적으로 작습니다. 나는 그것이 사용하는 것보다 더 빠르고 편리한 좋은 기술이라고 생각합니다. malloc() 그렇지 않으면.

다시 말해, alloca( 0x00ffffff ) 위험하고 오버플로를 유발할 가능성이 높습니다. char hugeArray[ 0x00ffffff ]; 이다. 조심하고 합리적이라면 괜찮을 것입니다.

모든 사람들은 이미 스택 오버플로에서 정의되지 않은 동작의 잠재적 인 행동을 이미 지적했지만 Windows 환경에는 구조화 된 예외 (SEH) 및 가드 페이지를 사용하여이를 포착 할 수있는 훌륭한 메커니즘이 있다고 언급해야합니다. 스택은 필요에 따라 자라기 때문에이 가드 페이지는 할당되지 않은 영역에 있습니다. (스택을 넘쳐서) 할당하면 예외가 발생합니다.

이 SEH 예외를 잡고 _resetstkoflw로 전화하여 스택을 재설정하고 메리 방식으로 계속하십시오. 이상적이지는 않지만 물건이 팬에 부딪 칠 때 적어도 무언가 잘못되었음을 알 수있는 또 다른 메커니즘입니다. *닉스는 내가 알지 못하는 것과 비슷한 것을 가질 수 있습니다.

Alloca를 감싸고 내부적으로 추적하여 최대 할당 크기를 캡핑하는 것이 좋습니다. 당신이 그것에 대해 정말로 하드 코어라면, 당신은 당신의 기능의 상단에 몇 가지 스코프 센트를 던질 수 있으며, 기능 범위에 Alloca 할당을 추적하고 사전은 프로젝트에 허용되는 최대 금액에 대해 이것을 점검 할 수 있습니다.

또한, 메모리 누출을 허용하지 않을뿐만 아니라 Alloca는 메모리 조각화를 유발하지 않습니다. 나는 당신이 지능적으로 사용한다면 Alloca가 나쁜 연습이라고 생각하지 않습니다. 이것은 기본적으로 모든 것에 사실입니다. :-)

Alloca () 멋지고 효율적이지만 ... 또한 깊이 깨졌습니다.

  • 범위가 깨진 동작 (블록 범위 대신 기능 범위)
  • Malloc과 일관성이없는 사용 (Alloca ()-Ted 포인터는 해방되지 않아야하므로 포인터가 어디에서 오는지 추적해야합니다. 무료() 당신이 가진 사람들 만 malloc ())
  • 당신이 또한 당신이 또한 인라인을 사용할 때의 나쁜 행동 (범위는 Callee가 상환되는 경우에 따라 발신자 기능으로 이동합니다).
  • 스택 경계 검사가 없습니다
  • 실패의 경우 정의되지 않은 동작 (Malloc처럼 Null을 반환하지 않습니다 ... 그리고 실패는 어쨌든 스택 경계를 확인하지 않기 때문에 의미합니다 ...)
  • ANSI 표준이 아닙니다

대부분의 경우 로컬 변수와 주요 원 크기를 사용하여 교체 할 수 있습니다. 큰 물체에 사용된다면 힙에 넣는 것이 일반적으로 더 안전한 아이디어입니다.

실제로 필요한 경우 C는 VLA를 사용할 수 있습니다 (C ++의 VLA 없음). 범위 행동과 일관성과 관련하여 Alloca ()보다 훨씬 낫습니다. 내가 알듯이 VLA 일종의입니다 Alloca () 제대로 만들었습니다.

물론 필요한 공간의 중이자를 사용하는 로컬 구조 또는 어레이는 여전히 더 좋습니다. 일반 Malloc ()를 사용하여 그러한 주요 힙 할당이 없다면 아마도 제정신 일 것입니다. 나는 당신이 정말로 정말로 필요한 제정신 유스 케이스가 없습니다. Alloca () 또는 VLA.

의 많은 재미있는 대답이"old"라는 질문,심지어 일부 상대적으로 새로운 답변이지만,나를 찾을 수 없는 이것을 언급....

사용할 때 적절하고 배려,의 일관된 사용 alloca() (아마도 응용 프로그램)을 처리 작은 가변 길이 할당 (또는 C99 블라스,어디에 사용할 수)할 수 있으로 이어질 낮은 전체 스택 성장 보다 그렇지 않으면 해당 사용하여 구현하는 대형 현지 배열의 고정 길이입니다.그래서 alloca()에 좋은 스 는 경우에 당신은 신중하게 그것을 사용하세요.

내가 발견을 견적합니다.확인을 내가 만든 것 견적니다.하지만 정말로,그것에 대해 생각합니다....

@j_random_hacker 은 아주 오른쪽에서 그의 코멘트는 아래에서 다른 답변:의 사용을 피하는 alloca() 찬성의 대형 로컬 배열을 만들지 않는 프로그램이 안전한 스택에서 오버플로(하지 않으면 컴파일이 오래된 할 수 있도록 충분히 인라인 기능을 사용하는 alloca() 어떤 경우에 당신은 업그레이드해야 또는 사용하지 않는 경우 alloca() 내부 루프,어떤 경우에 당신이 해야 합니다....를 사용하지 alloca() 내부 루프).

일했 데스크탑/서버 환경 및 임베디드 시스템입니다.많은 임베디드 시스템을 사용하지 않는 힙에서는 모두(지에서 링크를 지원한다)를 포함 하는 이유는 인식을 동적으로 할당된 메모리 악으로 위험의 메모리 누수 응용 프로그램에서는 절대로 재부팅에 대한 년 시간에,또는 더 합리적인 정당성이 있는 동적인 메모리이기 때문에 위험할 수 있는지에 대 한 알려진 특정 응용 프로그램이지 않는 조각의 힙 점 거짓의 메모리 부족으로 인해 발생합니다.그래서 포함된 프로그래머는 왼쪽으로 몇 가지 대안입니다.

alloca() (나 블라스)일 수 있는 권리 도구에 대한 직업입니다.

본 시간과 시간을 다시 프로그래머 만드는 스택 할당된 버퍼"충분히 큰 손잡이 가능한 모든 경우".에 깊이 중첩된 통화 나무,반복 사용의 것(방지?)패턴 리드하는 과장된 스택 사용.(상상 통화를 나무는 20 수준의 깊은 곳에서 각 수준에 대한 다른 이유로,이 기능을 맹목적으로 이상 버퍼를 할당하의 1024 바이트"안전을 때"일반적으로만 사용하여 16 개의 더 적은 그들만에서 매우 드문 경우 사용할 수 있을 것이다.) 대안을 사용하는 것입 alloca() 나 블라스 및 할당할 만큼 stack 공간으로 당신의 기능 요구를 방지하기 위해,불필요하게 부담 스택입니다.희망이 있을 때 하나 함수 호출에서 트리 요구에 보다 더 큰 정상적인 할당,다른 사람에 전화 나무에 여전히 사용하여 그들의 정상적인 작은 할당,전체적인 응용 프로그램 스택 사용가보다 훨씬 적은 경우 모든 기능을 맹목적으로 사용되는 로컬 버퍼입니다.

하지만 경우에 당신을 선택 사용 alloca()...

에 따라 다른 답변 이 페이지에서,그것은 보인다 블라스는 안전해야(지 않는 화합물 스택 할당 호출한 경우 루프 안에서),하지만 당신이 사용하는 경우 alloca(), 하지 않도록 주의하십시오 그것을 사용 루프 안에,그리고 확인 확인 귀하의 기능을 수 없는 인라인이 있다면 어떤 기회를 받아들 내에서 또 다른 기능의 반복입니다.

이유는 다음과 같습니다.

char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;

누구도이 코드를 작성하는 것이 아니라 당신이 전달하는 크기의 주장 alloca 거의 확실하게 어떤 종류의 입력에서 나옵니다. alloca 그런 거대한 것. 결국, 크기가 입력을 기반으로하지 않거나 크게 큰 가능성이 없다면, 왜 작은 고정 크기 로컬 버퍼를 선언하지 않았습니까?

사실상 모든 코드를 사용합니다 alloca 및/또는 C99 VLA에는 심각한 버그가있어 충돌 (운이 좋으면) 또는 특권 타협 (운이 좋지 않은 경우)이 발생합니다.

장소 alloca() 특히 위험합니다 malloc() 커널은 일반적인 운영 체제의 커널에는 헤더 중 하나에 고정 된 크기의 스택 공간이 하드 코딩되어 있습니다. 응용 프로그램 스택만큼 유연하지 않습니다. 전화를 걸어 alloca() 부적절한 크기로 커널이 충돌 할 수 있습니다. 특정 컴파일러는 사용을 경고합니다 alloca() 커널 코드를 컴파일하는 동안 켜져야하는 특정 옵션에서는 하드 코딩 된 한계에 의해 고정되지 않은 힙에 메모리를 할당하는 것이 좋습니다.

실수로 할당 된 블록 너머로 글을 쓰는 경우 alloca (예를 들어 버퍼 오버플로로 인해) 그러면 반송 주소 당신의 기능 중 하나는 스택에 "위"에 위치하고 있기 때문에, 즉 ~ 후에 할당 된 블록.

_alloca block on the stack

이것의 결과는 두 가지입니다.

  1. 이 프로그램은 화려하게 충돌하며 그 이유 또는 위치를 알 수있는 것은 불가능합니다 (스택은 쓰레기가 쓴 프레임 포인터로 인해 임의의 주소로 긴장을 풀 가능성이 높습니다).

  2. 악의적 인 사용자는 스택에 넣을 특수 페이로드를 만들 수 있기 때문에 버퍼 오버플로가 여러 배 더 위험하게 만듭니다. 따라서 결국 실행될 수 있기 때문입니다.

대조적으로, 힙에 블록 너머로 글을 쓰면 "그냥"힙 부패를 얻으십시오. 이 프로그램은 아마도 예기치 않게 종료 될 것이지만 스택을 올바르게 풀어 악성 코드 실행 가능성이 줄어 듭니다.

하나의 함정 alloca 그게 다 longjmp 그것을 되감기.

즉, 컨텍스트를 저장하면 setjmp, 그 다음에 alloca 그러면 약간의 기억 longjmp 맥락에서, 당신은 잃을 수 있습니다 alloca 메모리 (어떤 종류의 통지없이). 스택 포인터가 다시있는 곳으로 돌아와서 메모리가 더 이상 예약되지 않습니다. 기능을 호출하거나 다른 기능을하는 경우 alloca, 당신은 원본을 닫을 것입니다 alloca.

명확히하기 위해, 내가 여기에서 구체적으로 언급하는 것은 longjmp Where의 기능에서 벗어나지 않습니다 alloca 일어났다! 오히려 함수는 컨텍스트를 함께 저장합니다 setjmp; 그런 다음 메모리를 할당합니다 alloca 그리고 마지막으로 LongJMP는 그 맥락에서 발생합니다. 그 기능 alloca 기억이 모두 해방 된 것은 아닙니다. 그 이후로 할당 한 모든 기억 만 setjmp. 물론, 나는 관찰 된 행동에 대해 이야기하고 있습니다. 그러한 요구 사항은 문서화되어 있지 않습니다 alloca 내가 아는 것.

문서의 초점은 일반적으로 alloca 메모리는 a와 관련이 있습니다 기능 블록이 아닌 활성화; 그 여러 번의 호출 alloca 함수가 종료 될 때 모두 해제되는 더 많은 스택 메모리를 잡습니다. 별로; 메모리는 실제로 절차 컨텍스트와 관련이 있습니다. 컨텍스트가 복원 될 때 longjmp, 이전도 마찬가지입니다 alloca 상태. 스택 포인터 레지스터 자체가 할당에 사용되며 (반드시) (반드시) 저장 및 복원 된 결과입니다. jmp_buf.

또한, 이런 식으로 작동한다면, 이것은 의도적으로 할당 된 메모리를 자유롭게 해제하기위한 그럴듯한 메커니즘을 제공합니다. alloca.

나는 이것을 버그의 근본 원인으로 만났다.

컴파일러가 함수의 스택 프레임의 크기를 알 수 없기 때문에 함수에서 Alloca를 사용하면 기능에 적용될 수있는 일부 최적화를 방해하거나 비활성화합니다.

예를 들어, C 컴파일러에 의한 공통 최적화는 함수 내에서 프레임 포인터의 사용을 제거하는 것입니다. 대신 스택 포인터에 대해 프레임 액세스가 이루어집니다. 따라서 일반적인 용도로 등록이 하나 더 있습니다. 그러나 함수 내에서 Alloca가 호출되면 SP와 FP의 차이는 함수의 일부에 대해 알려지지 않았 으므로이 최적화를 수행 할 수 없습니다.

사용의 희귀 성과 표준 기능으로서의 그늘진 상태를 감안할 때 컴파일러 디자이너는 아마도 비활성화 할 수 있습니다. 어느 최적화 ~할 것 같다 Alloca와 함께 일할 수 있도록 약간의 노력이 필요하다면 Alloca에 문제가 발생합니다.

업데이트:가변 길이의 로컬 어레이가 C 및 C ++에 추가되었으므로, 이들은 Alloca와 같이 컴파일러와 매우 유사한 코드 생성 문제를 제시하기 때문에 '사용의 희귀 성과 그늘 상태'가 기본 메커니즘에 적용되지 않는다는 것을 알 수 있습니다. 그러나 나는 여전히 Alloca 또는 VLA의 사용이 그것들을 사용하는 함수 내에서 코드 생성을 손상시키는 경향이 있다고 의심합니다. 컴파일러 디자이너의 피드백을 환영합니다.

슬프게도 정말 대단합니다 alloca() 거의 멋진 TCC에서 누락되었습니다. GCC는 가지고 있습니다 alloca().

  1. 그것은 자신의 파괴의 씨앗을 뿌린다. 소멸자로 돌아와서.

  2. 처럼 malloc() 실패에 대한 유효하지 않은 포인터를 반환하여 MMU가있는 최신 시스템에서 Segfault (그리고 없이는 다시 시작).

  3. 자동 변수와 달리 실행 시간에 크기를 지정할 수 있습니다.

재귀와 잘 작동합니다. 정적 변수를 사용하여 꼬리 재귀와 유사한 것을 달성하고 다른 몇 가지 다른 반복에 정보를 전달할 수 있습니다.

너무 깊이 밀면 segfault (MMU가있는 경우)가 보장됩니다.

주목하십시오 malloc() 시스템이 메모리가 아닌 경우 NULL (할당하면 SEGFAULT)을 반환 할 때 더 이상 제공하지 않습니다. 즉, 당신이 할 수있는 모든 것은 보석금이나 어떤 식 으로든 할당하려고 시도하는 것입니다.

사용 malloc() 나는 글로벌을 사용하고 null을 할당합니다. 포인터가 무효가되지 않으면 사용하기 전에 자유롭게 해제합니다. malloc().

당신은 또한 사용할 수 있습니다 realloc() 기존 데이터를 복사하려면 일반적인 경우. 후에 복사하거나 연결하려는 경우 운동하기 전에 포인터를 확인해야합니다. realloc().

3.2.5.2 Alloca의 장점

프로세스에는 사용 가능한 스택 공간이 제한되어 있습니다. malloc().

사용하여 alloca() 스택 오버플로 오류를 얻을 가능성이 크게 높아집니다 (운이 좋으면 또는 그렇지 않은 경우 설명 할 수없는 충돌이 발생합니다).

그다지 예쁘지는 않지만 성능이 실제로 중요하다면 스택의 일부 공간을 경찰 할 수 있습니다.

이미 메모리의 최대 크기가 필요하고 오버플로 점검을 유지하려면 다음과 같은 작업을 수행 할 수 있습니다.

void f()
{
    char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
    SomeType *p = (SomeType *)array;

    (...)
}

실제로 Alloca는 스택을 사용하는 것이 보장되지 않습니다. 실제로, GCC-2.95 Alloca의 구현은 Malloc 자체를 사용하여 힙으로부터 메모리를 할당한다. 또한 그 구현은 버그가되며, GOTO를 추가로 사용하여 블록 내부라고 부르는 경우 메모리 누출과 예상치 못한 동작으로 이어질 수 있습니다. 말하자면, 당신은 그것을 사용해서는 안되지만, 때때로 Alloca는 Frome보다 더 많은 오버 헤드로 이어집니다.

Alloca 기능은 훌륭하고 모든 Naysayers는 단순히 FUD를 퍼 뜨리고 있습니다.

void foo()
{
    int x = 50000; 
    char array[x];
    char *parray = (char *)alloca(x);
}

배열과 앵무새는 정확히 동일한 위험과 동일합니다. 하나는 다른 것보다 낫다고 말하는 것은 기술적 인 선택이 아니라 구문 선택입니다.

스택 변수와 힙 변수를 선택하는 것은 스코프 내 수명을 가진 변수에 대한 힙 위에 스택을 사용하여 장기 실행 프로그램에 많은 장점이 있습니다. 힙 조각화를 피하고 사용되지 않는 (사용할 수없는) 힙 공간으로 프로세스 공간을 성장하지 않을 수 있습니다. 청소할 필요가 없습니다. 프로세스에서 스택 할당을 제어 할 수 있습니다.

이것이 왜 나쁘니?

IMHO, Alloca는 모든 사람이 스택 크기 제한을 소진하는 것을 두려워하기 때문에 나쁜 관행으로 간주됩니다.

이 스레드와 다른 링크를 읽음으로써 많은 것을 배웠습니다.

나는 주로 Alloca를 사용하여 MSVC 및 GCC에서 C89 스타일, #ifdef _msc_ver 등을 변경하지 않고 MSVC 및 GCC에서 컴파일 할 수 있도록합니다.

고맙습니다 ! 이 스레드는 나를이 사이트에 가입하게 만들었습니다 :)

제 생각에는 사용 가능한 경우 Alloca ()는 제한된 방식으로 만 사용해야합니다. "Goto"의 사용과 매우 흡사합니다. 많은 합리적인 사람들은 Alloca ()의 사용뿐만 아니라 존재에 대한 강한 혐오감을 가지고 있습니다.

내장 된 사용의 경우, 스택 크기가 알려진 곳 및 할당 크기에 대한 컨벤션 및 분석을 통해 한계를 부과 할 수 있으며 C99+를 지원하기 위해 컴파일러를 업그레이드 할 수없는 곳, Alloca ()의 사용은 괜찮으며, 나는 그랬습니다. 그것을 사용하는 것으로 알려져 있습니다.

사용 가능한 경우 VLAS는 Aloca ()에 비해 몇 가지 장점이있을 수 있습니다. 컴파일러는 배열 스타일 액세스를 사용할 때 방향으로 액세스 할 수있는 스택 제한 검사를 생성 할 수 있습니다 (컴파일러 가이 작업을 수행하는지 모르겠지만 가능합니다. 수행) 및 코드의 분석은 배열 액세스 표현식이 올바르게 제한되어 있는지 여부를 결정할 수 있습니다. 자동차, 의료 장비 및 항공 전자와 같은 일부 프로그래밍 환경 에서이 분석은 자동 (스택) 및 정적 할당 (글로벌 또는 로컬) 모두 고정 된 크기 어레이에 대해서도 수행해야합니다.

스택에 데이터와 리턴 주소/프레임 포인터를 모두 저장하는 아키텍처에서 (내가 아는 바에서, 그 모든 것), 모든 스택 할당 변수는 변수의 주소를 취할 수 있고 체크되지 않은 입력 값이 허용 될 수 있기 때문에 위험 할 수 있습니다. 모든 종류의 장난.

이식성은 임베디드 공간에서 우려가 적지 만 신중하게 통제 된 상황 이외의 Alloca () 사용에 대한 좋은 주장입니다.

임베디드 공간 밖에서, 나는 Alloca () 주로 효율성을 위해 내부 로깅 및 서식 함수를 사용했으며, 비수체적인 어휘 스캐너에서 임시 구조 (Alloca ()를 사용하여 할당 된)가 토큰 화 및 분류 중에 생성되는 경우 함수가 반환되기 전에 물체 (Malloc ()을 통해 할당)가 채워집니다. 더 작은 임시 구조에 대한 Alloca ()의 사용은 지속적인 물체가 할당 될 때 단편화를 크게 줄입니다.

여기서 대부분의 답변은 요점을 그리워합니다. _alloca() 스택에 큰 물체를 저장하는 것보다 잠재적으로 더 나쁩니다.

자동 저장소와의 주요 차이점 _alloca() 후자는 추가 (심각한) 문제로 고통 받고 있다는 것입니다. 할당 된 블록은 컴파일러에 의해 제어되지 않습니다, 컴파일러가 컴파일러를 최적화하거나 재활용 할 수있는 방법이 없습니다.

비교하다:

while (condition) {
    char buffer[0x100]; // Chill.
    /* ... */
}

와 함께:

while (condition) {
    char* buffer = _alloca(0x100); // Bad!
    /* ... */
}

후자의 문제는 분명해야합니다.

나는 아무도 이것을 언급했다고 생각하지 않지만 Alloca는 또한 Malloc과 함께 반드시 존재하지 않는 심각한 보안 문제가 있습니다 (이러한 문제는 스택 기반 배열에서도 동적 여부에 관계없이 발생합니다). 메모리가 스택에 할당되므로 버퍼 오버플로/언더 플로우는 Malloc보다 훨씬 더 심각한 결과를 초래합니다.

특히 함수의 리턴 주소는 스택에 저장됩니다. 이 값이 손상되면 코드가 메모리의 실행 가능한 영역으로 이동할 수 있습니다. 컴파일러는 이것을 어렵게 만들기 위해 큰 길이로 이동합니다 (특히 주소 레이아웃을 무작위화하여). 그러나 가장 좋은 경우는 반환 값이 손상된 경우 가장 좋은 경우는 segfault이기 때문에 스택 오버플로보다 분명히 나쁩니다. 그러나 임의의 메모리를 실행하기 시작하거나 최악의 경우 프로그램의 보안을 손상시키는 메모리 영역을 시작할 수도 있습니다. .

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