Nice programing

C 표준 라이브러리의 어떤 함수가 일반적으로 나쁜 습관을 유발합니까?

nicepro 2021. 1. 10. 19:57
반응형

C 표준 라이브러리의 어떤 함수가 일반적으로 나쁜 습관을 유발합니까?


이것은

이 질문

strncpy

C에서 매우 안전한 문자열 처리 기능이 아니며

n

내가 알지 못했던 것에 도달 할 때까지 0을 채운다는 것을 알게 된 특정 답변에 대한 의견에서 영감을 얻었 습니다 .특히

R ..

strncpy는 null로 종료되지 않으며 대상 버퍼의 나머지 전체를 null로 채 웁니다. 이는 엄청난 시간 낭비입니다. 자신의 널 패딩을 추가하여 전자를 해결할 수 있지만 후자는 아닙니다. "안전한 문자열 처리"함수로 사용하기위한 것이 아니라 Unix 디렉토리 테이블 및 데이터베이스 파일에서 고정 크기 필드로 작업하기위한 것입니다. snprintf (dest, n, "% s", src)는 표준 C에서 유일하게 올바른 "안전한 strcpy"이지만 훨씬 느릴 수 있습니다. 그건 그렇고, 잘림 자체는 주요 버그가 될 수 있으며 경우에 따라 권한 상승 또는 DoS로 이어질 수 있으므로 문제에서 출력을 자르는 "안전한"문자열 함수를 던지는 것은 "안전"또는 " 안전한". 대신

그리고

Jonathan Leffler에서

strncat ()은 strncpy ()보다 인터페이스에서 훨씬 더 혼란 스럽습니다-정확히 길이 인수는 무엇입니까? strncpy () 등을 제공하는 것에 기반하여 예상 한 것이 아니므로 strncpy ()보다 오류가 발생하기 쉽습니다. 문자열을 복사 할 때 항상 모든 크기를 미리 알고 미리 충분한 공간이 있는지 확인하기 때문에 memmove () 만 필요하다는 강력한 주장이 있다는 의견이 점점 커지고 있습니다. strcpy (), strcat (), strncpy (), strncat (), memcpy () 중 하나보다 선호하는 memmove ()를 사용하십시오.

그래서 저는 C 표준 라이브러리에서 분명히 약간 녹슬 었습니다. 따라서 질문을하고 싶습니다.

어떤 C 표준 라이브러리 함수가 부적절하게 사용되거나 보안 문제 / 코드 결함 / 비효율을 유발할 수있는 방식으로 사용됩니까?

객관성 측면에서 답변에 대한 여러 기준이 있습니다.

  • 가능하다면 문제의 기능 뒤에있는 디자인 이유, 즉 의도 된 목적을 인용하십시오.
  • 현재 코드가있는 오용을 강조하십시오.
  • 오용으로 인해 문제가 발생할 수있는 이유를 설명하십시오. 나는 그것이 명백해야한다는 것을 알고 있지만 그것은 부드러운 대답을 방해합니다.

피하십시오 :

  • 함수의 이름 지정 규칙에 대한 토론 (이로 인해 혼란이 발생하는 경우 제외).
  • "나는 y보다 x를 선호합니다"-선호도는 괜찮습니다. 우리 모두가 가지고 있지만 실제 예상치 못한 부작용과이를 방지하는 방법에 관심이 있습니다.

이것은 주관적인 것으로 간주 될 가능성이 있고 명확한 답변이 없기 때문에 즉시 커뮤니티 위키에 플래그를 지정합니다.나는 또한 C99에 따라 일하고 있습니다.


strtok()

함수 의 일반적인 함정 은 구문 분석 된 문자열이 변경되지 않은 상태로 남아 있다고 가정하고 실제로 구분 문자를

'\0'

.또한

strtok()

전체 문자열이 토큰 화 될 때까지 후속 호출을 수행하는 데 사용됩니다. 일부 라이브러리 구현은

strtok()

의 내부 상태를 전역 변수에 저장 합니다.

strtok()

경우 여러 스레드에서 동시에 호출 되면 약간의 깜짝 놀라게 할 수 있습니다 .

CERT C 표준 코딩 보안

이에 대한 질문이 함정의 많은 목록을.


어떤 C 표준 라이브러리 함수가 부적절하게 / 보안 문제 / 코드 결함 / 비효율을 유발 / 유발할 수있는 방식으로 사용됩니까?

나는 명백한 것으로 갈 것입니다.

char *gets(char *s); 

적절하게 사용하는 것이 단순히 불가능하다는 놀라운 특수성으로.


거의 모든 경우에를 사용

atoi()

해서는 안됩니다 (

atof()

,

atol()

에도 적용됨

atoll()

).이는 이러한 함수가 범위를 벗어난 오류를 전혀 감지하지 못하기 때문입니다. 표준은 단순히

"결과 값을 표현할 수없는 경우 동작이 정의되지 않은 것"이라고 말합니다.

. 따라서 안전하게 사용할 수있는 유일한 시간은 입력이 확실히 범위 내에 있다는 것을 증명할 수있는 경우입니다 (예를 들어 길이가 4 이하인 문자열을에 전달하면

atoi()

범위를 벗어날 수 없음).대신

strtol()

기능 군 중 하나를 사용하십시오 .


더 넓은 의미에서 인터페이스에 대한 질문을 확장 해 보겠습니다.

errno

:기술적으로 변수, 매크로, 암시 적 함수 호출이 무엇인지 명확하지 않습니까? 실제로 현대 시스템에서는 대부분 스레드 특정 오류 상태를 갖도록 함수 호출로 변환되는 매크로입니다. 그것은 악하다 :

  • 호출자가 값에 액세스하여 "오류"(예외 이벤트 일 수 있음)를 확인하는 오버 헤드가 발생할 수 있기 때문입니다.
  • 호출자가 라이브러리 호출을하기 전에이 "변수"를 지우도록 일부 장소에서 부과하기 때문에
  • 라이브러리의 전역 상태를 설정하여 간단한 오류 반환을 구현하기 때문입니다.

다가오는 표준은

errno

좀 더 솔직한 정의를 얻지 만 이러한 추함은 여전히 ​​남아 있습니다.


종종 strtok_r이 있습니다.realloc의 경우 이전 포인터를 사용해야하는 경우 다른 변수를 사용하는 것이 그렇게 어렵지 않습니다. 프로그램이 할당 오류로 실패하면 이전 포인터를 정리할 필요가없는 경우가 많습니다.


나는 둘 것입니다

printf

scanf

이 목록에 꽤 높은 최대. 형식 지정자를 정확히 맞아야한다는 사실은 이러한 함수를 사용하기 까다 롭고 잘못하기 매우 쉽게 만듭니다. 데이터를 읽을 때 버퍼 오버런을 피하는 것도 매우 어렵습니다. 더욱이 "printf 형식 문자열 취약성"은 선의의 프로그래머가 클라이언트 지정 문자열을 printf에 대한 첫 번째 인수로 지정했을 때 수많은 보안 허점을 일으켰을 때 스택이 부숴지고 보안이 수년 동안 손상되었음을 발견 할뿐입니다.


Any of the functions that manipulate global state, like gmtime() or localtime(). These functions simply can't be used safely in multiple threads.

EDIT: rand() is in the same category it would seem. At least there are no guarantees of thread-safety, and on my Linux system the man page warns that it is non-reentrant and non-threadsafe.


One of my bêtes noire is strtok(), because it is non-reentrant and because it hacks the string it is processing into pieces, inserting NUL at the end of each token it isolates. The problems with this are legion; it is distressingly often touted as a solution to a problem, but is as often a problem itself. Not always - it can be used safely. But only if you are careful. The same is true of most functions, with the notable exception of gets() which cannot be used safely.


There's already one answer about realloc, but I have a different take on it. A lot of time, I've seen people write realloc when they mean free; malloc - in other words, when they have a buffer full of trash that needs to change size before storing new data. This of course leads to potentially-large, cache-thrashing memcpy of trash that's about to be overwritten.

If used correctly with growing data (in a way that avoids worst-case O(n^2) performance for growing an object to size n, i.e. growing the buffer geometrically instead of linearly when you run out of space), realloc has doubtful benefit over simply doing your own new malloc, memcpy, and free cycle. The only way realloc can ever avoid doing this internally is when you're working with a single object at the top of the heap.

If you like to zero-fill new objects with calloc, it's easy to forget that realloc won't zero-fill the new part.

And finally, one more common use of realloc is to allocate more than you need, then resize the allocated object down to just the required size. But this can actually be harmful (additional allocation and memcpy) on implementations that strictly segregate chunks by size, and in other cases might increase fragmentation (by splitting off part of a large free chunk to store a new small object, instead of using an existing small free chunk).

I'm not sure if I'd say realloc encourages bad practice, but it's a function I'd watch out for.


How about the malloc family in general? The vast majority of large, long-lived programs I've seen use dynamic memory allocation all over the place as if it were free. Of course real-time developers know this is a myth, and careless use of dynamic allocation can lead to catastrophic blow-up of memory usage and/or fragmentation of address space to the point of memory exhaustion.

In some higher-level languages without machine-level pointers, dynamic allocation is not so bad because the implementation can move objects and defragment memory during the program's lifetime, as long as it can keep references to these objects up-to-date. A non-conventional C implementation could do this too, but working out the details is non-trivial and it would incur a very significant cost in all pointer dereferences and make pointers rather large, so for practical purposes, it's not possible in C.

My suspicion is that the correct solution is usually for long-lived programs to perform their small routine allocations as usual with malloc, but to keep large, long-lived data structures in a form where they can be reconstructed and replaced periodically to fight fragmentation, or as large malloc blocks containing a number of structures that make up a single large unit of data in the application (like a whole web page presentation in a browser), or on-disk with a fixed-size in-memory cache or memory-mapped files.


On a wholly different tack, I've never really understood the benefits of atan() when there is atan2(). The difference is that atan2() takes two arguments, and returns an angle anywhere in the range -π..+π. Further, it avoids divide by zero errors and loss of precision errors (dividing a very small number by a very large number, or vice versa). By contrast, the atan() function only returns a value in the range -π/2..+π/2, and you have to do the division beforehand (I don't recall a scenario where atan() could be used without there being a division, short of simply generating a table of arctangents). Providing 1.0 as the divisor for atan2() when given a simple value is not pushing the limits.


Another answer, since these are not really related, rand:

  • it is of unspecified random quality
  • it is not re-entrant

Some of this functions are modifying some global state. (In windows) this state is shared per single thread - you can get unexpected result. For example, the first call of rand in every thread will give the same result, and it requires some care to make it pseudorandom, but deterministic (for debug purposes).


basename() and dirname() aren't threadsafe.

ReferenceURL : https://stackoverflow.com/questions/4588581/which-functions-in-the-c-standard-library-commonly-encourage-bad-practice

반응형

'Nice programing' 카테고리의 다른 글

javax.servlet은 어디에 있습니까?  (0) 2021.01.10
일반 인터페이스  (0) 2021.01.10
Android에서 Spinner 비활성화  (0) 2021.01.10
iframe src를 동적으로 설정  (0) 2021.01.10
jquery 데이터 테이블 기본 정렬  (0) 2021.01.10