시스템 프로그래밍 클래스에서이 전 학기를 수강했습니다. 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
하는 내장 구현을 사용 합니다. 내장 기능이 비활성화 된 경우 와 동일합니다 .memset
0
glibc
답변
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에서 다음을 인용했습니다.
bzero
ANSI C 함수가 아닙니다. 초기 Berkely 네트워킹 코드에서 파생되었습니다. 그럼에도 불구하고, 우리는 ANSI Cmemset
함수 대신 텍스트 전체에서 그것을 사용합니다 . 왜냐하면 (세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으로 설정해야합니다. 그럼에도 불구하고 오류이며이를 사용하여 피할 수 있습니다
bzero
bzero
함수 프로토 타입을 사용하는 경우 두 인수를 서로 바꾸면 항상 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