[c] memset보다 bzero를 사용하는 이유는 무엇입니까?

시스템 프로그래밍 클래스에서이 전 학기를 수강했습니다. C에서 기본 클라이언트 / 서버를 구현해야했습니다. sock_addr_in, 또는 버퍼 버퍼 (클라이언트와 서버간에 데이터를주고받는 데 사용 된) 와 같은 구조체를 초기화 할 때 교수 초기화 만하지 bzero말라고 지시 memset했습니다. 그는 왜 그런지 설명하지 않았으며, 이것에 대한 정당한 이유가 있는지 궁금합니다.

나는 여기를 참조하십시오 : http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown 그것은 bzero단지 제로 메모리가 될 것이라는 사실 때문에 더 효율적이므로, 그렇지 않습니다 추가 점검을 memset수행해야합니다. 그래도 memset메모리를 제로화 하는 데 절대 사용하지 않는 이유는 아닙니다 .

bzero는 더 이상 사용되지 않으며 표준 C 함수가 아닙니다. 매뉴얼에 따르면 이러한 이유로 memset선호 bzero됩니다. 그렇다면 왜 아직도 사용 bzero하고 memset싶습니까? 효율성 향상을위한 것입니까, 아니면 더 많은 것입니까? 마찬가지로 새로운 프로그램에 대해 실제로 선호되는 옵션이되는 것 memset이상의 장점은 무엇 bzero입니까?



답변

bzero이상 을 선호 할 이유가 없습니다 memset.

memset반면 표준 C의 함수이다 bzero는 C 표준 기능 적이있다. 이론적 근거는 아마도 함수를 사용하여 정확히 동일한 기능을 달성 할 수 있기 때문일 것입니다 memset.

이제 효율성과 관련하여 컴파일러 는 상수 가 감지 될 때 특정 구현으로 전환 gcc하는 내장 구현을 사용 합니다. 내장 기능이 비활성화 된 경우 와 동일합니다 .memset0glibc


답변

W. Richard Stevens의 UNIX 네트워크 프로그래밍 을 사용했거나 교사의 영향을 받았다고 생각합니다 . 그는 최신 버전에서도 bzero자주 사용하지 memset않습니다. 이 책은 매우 인기가 많기 때문에 네트워크 프로그래밍의 관용구가 된 것 같습니다.

더 이상 사용되지 않으며 이식성이 줄어들 memset기 때문에 간단하게 고수 할 것 bzero입니다. 나는 당신이 하나를 다른 것보다 사용함으로써 실질적인 이익을 볼 것이라고 의심합니다.


답변

내가 생각하는 장점 중 하나 bzero()이상이 memset()제로에 메모리를 설정 만들어지고 실수의 감소 가능성이 있다는 것이다.

한 번 이상 다음과 같은 버그가 발생했습니다.

memset(someobject, size_of_object, 0);    // clear object

컴파일러는 불만을 제기하지 않으며 (어쩌면 일부 컴파일러에서 경고 수준을 높이면 일부 메모리가 지워질 수 있음) 영향을받습니다. 이것은 객체를 휴지통에 버리지 않기 때문에 그냥 내버려두기 때문에 버그가 분명하게 나타나지 않을 가능성이 있습니다.

bzero()표준이 아니라는 사실 은 사소한 자극입니다. (FWIW, 프로그램에서 대부분의 함수 호출이 표준이 아닌 경우 놀라지 않을 것입니다. 사실 그러한 함수를 작성하는 것이 일종의 일입니다).

또 다른 답변에 대한 언급에서 Aaron Newton은 Stevens 등의 1.2 절 (강조 추가)에 의해 Unix Network Programming, Volume 1, 3rd Edition에서 다음을 인용했습니다.

bzeroANSI C 함수가 아닙니다. 초기 Berkely 네트워킹 코드에서 파생되었습니다. 그럼에도 불구하고, 우리는 ANSI C memset함수 대신 텍스트 전체에서 그것을 사용합니다 . 왜냐하면 (세 bzero개의 인수로)보다 memset( 두 개의 인수로) 기억 하기 가 쉽기 때문 입니다 . 소켓 API를 지원하는 거의 모든 벤더는 또한을 제공 bzero하며, 그렇지 않은 경우 unp.h헤더에 매크로 정의를 제공합니다 .

실제로, TCPv3의 저자 [TCP / IP Illustrated, Volume 3-Stevens 1996]는 memset첫 번째 인쇄에서 두 번째와 세 번째 인수를 10 번 으로 바꾸는 실수를 했습니다 . 두 인수가 모두 같은 유형이므로 AC 컴파일러는이 오류를 포착 할 수 없습니다. 실제로 두 번째 인수는 일반 int적이고 세 번째 인수는 size_t일반적으로 unsigned int이지만 다른 유형의 인수에는 각각 0과 16으로 지정된 값을 memset여전히 사용할 수 있습니다. 소켓 함수 중 일부는 실제로 인터넷 소켓 주소 구조의 마지막 8 바이트를 0으로 설정해야합니다. 그럼에도 불구하고 오류이며이를 사용하여 피할 수 있습니다
bzerobzero함수 프로토 타입을 사용하는 경우 두 인수를 서로 바꾸면 항상 C 컴파일러에서 잡을 수 있기 때문 입니다.

또한 대부분의 호출 memset()은 메모리를 0으로 하는 것이라고 생각 하므로 해당 사용 사례에 맞는 API를 사용하지 않겠습니까?

가능한 단점 bzero()은 컴파일러가 memcpy()표준이기 때문에 최적화 할 가능성이 높기 때문에이를 인식하도록 작성 될 수 있다는 것입니다. 그러나 올바른 코드는 여전히 최적화 된 잘못된 코드보다 낫습니다. 대부분 bzero()bzero()경우을 사용 하면 프로그램 성능에 눈에 띄는 영향을 미치지 않으며으로 확장되는 매크로 또는 인라인 함수일 수 있습니다 memcpy().


답변

bzero 대 memset 인수에 대해 언급하고 싶었습니다. ltrace를 설치 한 후 후드에서 수행하는 작업을 비교하십시오. libc6 (2.19-0ubuntu6.6)을 사용하는 Linux에서 호출은을 통해 정확히 동일합니다 ltrace ./test123.

long m[] = {0}; // generates a call to memset(0x7fffefa28238, '\0', 8)
int* p;
bzero(&p, 4);   // generates a call to memset(0x7fffefa28230, '\0', 4)

나는 libc깊은 창 이나 많은 커널 / 시스템 콜 인터페이스에서 작업하지 않는 한 걱정할 필요 가 없다고 들었 습니다. 내가 걱정해야 할 것은 호출이 버퍼 제로화 요구 사항을 충족한다는 것입니다. 다른 사람들은 어느 것이 다른 것보다 선호되는지 언급 했으므로 여기서 멈 춥니 다.


답변

당신은 아마 사용 bzero사실은 표준 C 아니다, 그것은 POSIX 일이었다.

그리고 단어 “했다”참고 – 그것이 되지 POSIX.1-2001과 제거 당신은 더 나은 표준 C 함수를 사용하여 길 이죠, 그래서 memset 함수에 복종에 POSIX.1-2008에.


답변

memset 함수 함수, 제 2 인수가 인 int세 번째 인자 인 size_t,

void *memset(void *s, int c, size_t n);

이것은 일반적으로 unsigned int이지만 0 and 16두 번째 및 세 번째 인수에 대한 값이 각각 16 및 0과 같은 잘못된 순서로 입력되면 memset에 대한 호출은 여전히 ​​작동 할 수 있지만 아무것도하지 않습니다. 초기화 할 바이트 수는로 지정되어 있기 때문 0입니다.

void bzero(void *s, size_t n)

함수 프로토 타입을 사용하는 경우 두 인수를 bzero로 바꾸는 것은 항상 C 컴파일러에 의해 잡히므로 bzero를 사용하면 이러한 오류를 피할 수 있습니다.


답변

한마디로 : memset 더 많은 어셈블리 작업이 필요합니다 bzero.

이것은 소스입니다 :
http://fdiv.net/2009/01/14/memset-vs-bzero-ultimate-showdown