말록은 스레드 세이프입니까?
이요?malloc()
함수가 중요합니까?
질문: "malloc reentrant?"
답변: 아닙니다.다음은 일상적인 재진입을 가능하게 하는 한 가지 정의입니다.
malloc의 일반적인 버전은 모두 다시 입력할 수 없습니다(신호 핸들러 등).재진입 루틴은 잠금을 사용하지 않을 수 있으며, 존재하는 거의 모든 malloc 버전에서는 잠금(스레드 세이프) 또는 글로벌/스태틱 변수(스레드 비세이프 및 비리엔트)가 사용됩니다.
지금까지의 모든 대답은 "말로크 스레드 세이프?"라고 답한 것은 전혀 다른 질문이다.이 질문에 대한 답은 런타임 라이브러리와 사용하는 컴파일러 플래그에 따라 달라집니다.최신 UNIX에서는 기본적으로 스레드 세이프 malloc을 사용할 수 있습니다.Windows 의 경우는,/MT
,/MTd
,/MD
또는/MDd
플래그를 사용하여 스레드 세이프 런타임 라이브러리를 가져옵니다.
어디서 읽었는데 -pthread로 컴파일하면 malloc이 스레드 세이프가 된다고 합니다.그러나 malloc은 ANSI C이고 스레드는 그렇지 않기 때문에 구현에 의존한다고 확신합니다.
gcc를 말하는 경우:
x86 및 AMD64에서는 -pthread 및 malloc()를 사용한 컴파일 및 링크는 스레드 세이프가 됩니다.
다른 의견, 더 통찰력 있는 의견
glibc-2.2+의 {syslogoc, calloc, realloc, free, posix_memalign}은(는) 스레드 세이프입니다.
http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2005-07/0323.html
이것은 꽤 오래된 질문이기 때문에, 나는 현재의 상황에 따라 신선함을 가져오고 싶다.
네, 현재malloc()
스레드 세이프입니다.
의 GNU C 라이브러리 레퍼런스 매뉴얼에서glibc-2.20 [released 2014-09-07]
:
void * malloc (size_t size)
예비: MT-Safe | ...
... 1.2.2.1 POSIX 안전 개념:
... MT-Safe 또는 Thread-Safe 함수는 다른 스레드가 있을 때 호출해도 안전합니다.MT-Safe에서 MT는 Multi Thread의 약자입니다.
MT-Safe가 된다는 것은 함수가 원자적이라는 의미도 아니고 POSIX가 사용자에게 제공하는 메모리 동기화 메커니즘을 사용하지 않는다는 의미도 아닙니다.MT-Safe 함수를 순서대로 호출하면 MT-Safe 조합이 생성되지 않을 수도 있습니다.예를 들어 스레드가 2개의 MT-Safe 함수를 차례로 호출하도록 해도 다른 스레드의 동시 호출이 파괴적인 방식으로 간섭할 수 있으므로 두 함수의 조합에 대한 원자적 실행과 동등한 동작을 보장하지 않습니다.
라이브러리 인터페이스 간에 함수를 인라인화할 수 있는 전체 프로그램 최적화에서는 안전하지 않은 순서 변경이 발생할 수 있으므로 GNU C 라이브러리 인터페이스 간에 인라인 처리를 수행하는 것은 권장되지 않습니다.문서화된 MT-Safety 상태는 전체 프로그램 최적화에서 보장되지 않습니다.단, 사용자가 볼 수 있는 헤더에 정의된 함수는 인라인에 안전하도록 설계되어 있습니다.
네, POSIX.1-2008에서 malloc
스레드 세이프입니다.
2.9.1 나사산 안전성
POSIX.1-2008의 이 볼륨에서 정의한 모든 기능은 나사산 안전해야 하며, 단, 다음의 기능1은 나사산 안전할 필요가 없습니다.
[포함되지 않은 기능 목록]
malloc
]
간단한 답변: 예, C11에서는 스레드 개념을 포함한 C 표준의 첫 번째 버전입니다.malloc
친구들은 안전해야 합니다스레드 및 C 런타임 모두를 포함하는 많은 운영체제가 C 표준보다 훨씬 전에 이 보증을 섰지만, 저는 모든 것을 맹세할 준비가 되어 있지 않습니다.하지만,malloc
친구는 재입학할 필요가 없고, 또 그런 적도 없다.
즉, 전화하는 것이 안전합니다.malloc
그리고.free
메모리 할당의 다른 규칙(콜 등)을 어기지 않는 한, 동시에 복수의 스레드를 사용할 수 있어 잠길 염려가 없습니다.free
반환되는 포인터마다 한 번만malloc
단, 콜을 중단했을 가능성이 있는 신호 핸들러에서 이들 함수를 호출하는 것은 안전하지 않습니다.malloc
또는free
신호를 처리하는 스레드에 있습니다.ISO C 이외의 기능을 사용하면 신호를 처리하는 스레드가 콜을 중단하지 않았음을 보증할 수 있습니다.malloc
또는free
(예:sigprocmask
그리고.sigpause
하지만 다른 선택이 없는 한 그렇게 하지 마세요. 왜냐하면 완벽하게 맞히는 것은 어렵기 때문입니다.
인용문으로 긴 답변:C 표준은 2011년 개정판에 스레드 개념을 추가하였다(링크는 무료로 공개되는 2011년 표준의 공식 텍스트에 가장 근접한 문서 N1570에 대한 것이다).이 개정에서 섹션 7.1.4 문단 5는 다음과 같이 기술하고 있다.
이어지는 상세 설명에 달리 명시되지 않는 한 라이브러리 기능은 다음과 같이 데이터 경합을 방지해야 한다.라이브러리 함수는 함수의 인수를 통해 직접 또는 간접적으로 객체에 접근하지 않는 한 현재 스레드 이외의 스레드에 의해 접근 가능한 객체에 직접 또는 간접적으로 접근해서는 안 된다.라이브러리 함수는 객체가 함수의 비상수 인수를 통해 직접 또는 간접적으로 액세스되지 않는 한 현재 스레드 이외의 스레드에 의해 액세스 가능한 객체를 직접 또는 간접적으로 수정해서는 안 된다.오브젝트가 사용자에게 표시되지 않고 데이터 레이스로부터 보호되는 경우 구현은 스레드 간에 자체 내부 오브젝트를 공유할 수 있습니다.
[예외:이는 예를 들어 스레드 간에 개체를 명시적으로 공유하지 않는 프로그램에서도 데이터 경합을 일으킬 수 있기 때문에 동기화 없이 구현이 내부 목적으로 정적 개체를 사용할 수 없음을 의미합니다.마찬가지로 memcpy를 구현하면 프로그램이 스레드 간에 바이트를 공유할 경우 데이터 레이스가 발생할 수 있기 때문에 대상 개체의 지정된 길이를 초과하여 바이트를 복사한 후 원래 값을 복원할 수 없습니다.
제가 이해하기로는, 이것은 C 표준에 의해 정의된 라이브러리 함수가 스레드 세이프가 필요하다는 것을 장황하게 말해주는 것입니다(통상적인 의미에서는, 복수의 스레드로부터 동시에 호출할 수 있습니다).다만, 문서 f가 인수로 전달된 데이터에 충돌하지 않는 한, 스스로 잠금을 실시하지 않고, 그것들을 호출할 수 있습니다).아니면 특정 기능이 그렇지 않다고 할 수도 있습니다.
다음으로 7.22.3p2는 malloc, calloc, realloc, aligned_alloc 및 free가 스레드 세이프임을 확인합니다.
데이터 레이스의 존재를 판단하기 위해 메모리 할당 함수는 다른 정적 기간 저장소가 아닌 인수를 통해 액세스할 수 있는 메모리 위치에만 액세스하는 것처럼 동작합니다.그러나 이러한 기능은 할당 또는 할당 해제된 스토리지를 눈에 띄게 변경할 수 있습니다.메모리의 리젼p 의 할당을 해제하는 프리 또는 재할당을 실시하는 콜은, 리젼p 의 전부 또는 일부를 할당하는 임의의 할당 콜과 동기합니다.이 동기화는 할당 해제 함수에 의한 p 액세스 후 및 할당 기능에 의한 이러한 액세스 전에 발생합니다.
7.24.5.8p6의 strtok에 대해 기술되어 있는 내용과 대조합니다.이것은 스레드 세이프가 아니고 지금까지 없었던 것입니다.
strtok 함수는 strtok 함수에 대한 다른 호출과의 데이터 경합을 피하기 위해 필요하지 않습니다.
[예외:대신 strtok_s 함수를 사용하여 데이터 레이스를 회피할 수 있습니다.]
(각주 참조: 사용하지 않음strtok_s
,사용하다strsep
.)
이전 버전의 C 표준에서는 스레드 안전에 대해 전혀 언급하지 않았습니다.다만, 신호는 항상 C 표준의 일부였기 때문에, 재진입에 대해서는 확실히 언급하고 있습니다.최초의 1989년 ANSI C 표준(이 문서는 다음 해에 발표된 ISO C 표준과 거의 동일하지만 섹션 번호는 매우 다르다)으로 돌아가서 다음과 같이 말하고 있습니다.
abort 또는 raise 함수를 호출한 결과 이외에 [a] 신호가 발생하는 경우 신호 핸들러가 신호 함수 자체 이외의 함수를 호출하거나 vola 유형의 정적 저장 기간 변수에 값을 할당하는 것 이외의 정적 저장 기간을 가진 개체를 참조하는 경우 동작은 정의되지 않습니다.타일 sig_atomic_t.또, 이러한 신호 함수에 대한 콜이 SIG_ERR 리턴이 되었을 경우, errno 값은 부정됩니다.
이는 일반적으로 C 라이브러리 기능을 재진입할 필요가 없다는 장황한 표현입니다.C11, 7.14.1.1p5에서도 여전히 매우 유사한 표현이 사용되고 있습니다.
abort 함수 또는 raise 함수를 호출한 결과 이외의 [a]신호가 발생하면 volatile sig_atomic_t로 선언된 객체에 값을 할당하거나 신호 핸들러가 functi를 호출하는 것 외에 잠금 프리 아토믹 객체가 아닌 정적 또는 스레드 저장 기간을 가진 객체를 참조하는 경우 동작은 정의되지 않습니다.첫 번째 인수가 핸들러의 호출을 일으킨 신호에 대응하는 신호 번호와 동일한 신호 함수인 _Exit 함수, quick_Exit 함수 또는 신호 함수입니다.또, 이러한 신호 함수에 대한 콜이 SIG_ERR 리턴이 되었을 경우, errno 값은 부정됩니다.
[예외:비동기 신호 핸들러에 의해 신호가 생성되면 동작은 정의되지 않습니다.]
POSIX는 C 라이브러리의 전체 크기에 비해 훨씬 더 길지만 여전히 짧은 함수 목록을 "비동기 신호 핸들러"에서 안전하게 호출할 수 있어야 하며, 또한 신호가 "중단 또는 상승 함수의 호출 결과"로 인해 발생할 수 있는 상황을 더 자세히 정의합니다.신호에 대해 간단한 조작을 하고 있는 경우는, Windows, MVS, 또는 C의 완전한 호스트 실장이 되어 있지 않은 임베디드 기기와는 달리, Unix 의 성질을 가지는 OS 상에서 동작하도록 의도된 코드를 기술하고 있을 가능성이 높기 때문에, 이러한 OS 에 관한 POSIX 요건과 그 요건을 충분히 이해해 둘 필요가 있습니다.s ISO C 요건.
나는 독서를 추천한다.
§ 31.1 스레드 안전성(및 재진입 검토)
Linux Programming Interface라는 책의 내용은 스레드의 안전성과 재진입성의 차이를 설명하고 있습니다.malloc
.
발췌:
한 함수는 동시에 여러 스레드에 의해 안전하게 호출될 수 있는 경우 스레드 세이프라고 합니다. 반대로, 어떤 함수가 스레드 세이프가 아닌 경우, 다른 스레드에서 실행되는 동안에는 한 스레드에서 호출할 수 없습니다.
....
이 함수는 함수가 스레드 세이프가 아닌 일반적인 이유를 보여줍니다.이 함수는 모든 스레드에서 공유되는 글로벌 변수 또는 정적 변수를 사용합니다....
스레드 안전을 구현하기 위해 중요한 섹션을 사용하는 것은 함수별 뮤텍스 사용보다 크게 개선되었지만 뮤텍스를 잠그거나 잠금 해제하는 데 비용이 들기 때문에 여전히 다소 비효율적입니다.재진입 함수는 뮤텍스를 사용하지 않고 스레드 안전성을 실현합니다.이를 위해 글로벌 변수와 스태틱 변수를 사용하지 않습니다....
그러나 모든 기능을 재진입할 수 있는 것은 아닙니다.일반적인 이유는 다음과 같습니다.
- 그 성질상 일부 기능은 글로벌 데이터 구조에 액세스해야 합니다.malloc 라이브러리의 함수는 좋은 예를 제시합니다.이러한 함수는 힙에서 사용 가능한 블록의 글로벌 링크 목록을 유지합니다.의 기능
malloc
라이브러리는 뮤텍스를 사용하여 스레드 세이프가 됩니다.....
확실히 읽을 가치가 있다.
그리고 당신의 질문에 답하기 위해,malloc
스레드는 안전하지만 재진입하지 않습니다.
GLIBC를 사용하고 있는 경우는, 「Yes, BUT」라고 대답합니다.
구체적으로는 그렇습니다만, malloc와 free는 스레드 세이프이지만 디버깅 기능은 그렇지 않습니다.
특히 매우 유용한 mtrace(), mcheck() 및 mprobe() 함수는 스레드 세이프가 아닙니다.GNU 프로젝트에서 볼 수 있는 가장 짧고 솔직한 답변 중 하나는 다음과 같습니다.
https://sourceware.org/bugzilla/show_bug.cgi?id=9939
ElectricFence, valgrind, dmalloc 등의 대체 기술을 고려해야 합니다.
따라서 "malloc() 및 free() 함수는 스레드 세이프입니까?"를 의미하면 대답은 "예"입니다.그러나 "malloc/free 스위트 전체가 스레드 세이프입니까?"를 의미한다면, 대답은 "아니오"입니다.
다음은 glibc의 malloc.c에서 발췌한 것입니다.
스레드 세이프티: NO_THREADS가 정의되어 있지 않은 한 스레드 세이프
기본적으로 NO_THREADS가 정의되어 있지 않다고 가정하면 malloc은 적어도 Linux에서는 스레드 세이프가 됩니다.
malloc 및 free는 빈 메모리블록을 기록하는 정적 데이터 구조를 사용하기 때문에 재진입하지 않습니다.그 결과 메모리를 할당하거나 해방하는 라이브러리 기능은 재진입할 수 없습니다.
사용하는 C 런타임 라이브러리의 구현에 따라 달라집니다.예를 들어 MSVC를 사용하는 경우 빌드할 라이브러리의 버전을 지정할 수 있는 컴파일러 옵션이 있습니다(즉, 트레드 세이프를 통해 멀티 스레딩을 지원하는 런타임 라이브러리 등).
아니요, 스레드 세이프가 아닙니다.실제로도 있을 수 있습니다.malloc_lock()
그리고.malloc_unlock()
C 라이브러리에서 사용할 수 있는 기능입니다.이것들은 Newlib 라이브러리용으로 존재하는 것을 알고 있습니다.프로세서의 뮤텍스를 구현하기 위해 이 기능을 사용해야 했습니다.이것은 하드웨어에서 멀티 스레드화되어 있습니다.
아니, 그건 아니야.
언급URL : https://stackoverflow.com/questions/855763/is-malloc-thread-safe
'programing' 카테고리의 다른 글
xdebug var_dump가 전체 개체/어레이를 표시하도록 하는 방법 (0) | 2022.09.06 |
---|---|
Vuex 작업이 제대로 작동하지 않습니다.signInWithEmailAndPassword failed:첫 번째 인수 "email"은 유효한 문자열이어야 합니다. (0) | 2022.08.30 |
JavaScript를 사용하여 인덱스별로 배열 요소를 제거하려면 어떻게 해야 합니까? (0) | 2022.08.30 |
'vuex' 경고에서 "export 'createStore'를 찾을 수 없습니다. (0) | 2022.08.30 |
TypeScript에서 @Prop decorator를 사용하면 컴파일러가 프로펠의 초기화를 요구하는 에러를 표시합니다. (0) | 2022.08.30 |