MSVC에 대한 __attribute__(형식(printf, 1, 2))?
GCC를 사용하면 다음과 같이 지정할 수 있습니다.__attribute__((format(printf, 1, 2)))
, 컴파일러에게 이 함수가 printf 형식 지정자인 다양한 매개 변수를 사용한다고 말합니다.
이것은 vsprintf 함수 패밀리와 같은 경우에 매우 유용합니다.가질 수 있습니다extern void log_error(const char *format, ...) __attribute__((format(printf, 1, 2)));
그리고 내가 이 함수를 호출할 때마다 gcc는 printf와 같이 인수의 종류와 개수가 주어진 형식 지정자에 부합하는지 확인하고 그렇지 않으면 경고를 발행할 것입니다.
마이크로소프트 C/C++ 컴파일러에 유사한 것이 있습니까?
SAL 주석을 사용하여 사용할 수 있습니다._Printf_format_string_
(VS2k8는 VS2k10준)준__format_string
VS2k5우):
#undef FORMAT_STRING
#if _MSC_VER >= 1400
# include <sal.h>
# if _MSC_VER > 1400
# define FORMAT_STRING(p) _Printf_format_string_ p
# else
# define FORMAT_STRING(p) __format_string p
# endif /* FORMAT_STRING */
#else
# define FORMAT_STRING(p) p
#endif /* _MSC_VER */
/* use /analyze or _USE_ATTRIBUTES_FOR_SAL for checking */
extern void log_error(FORMAT_STRING(const char* format), ...);
@RustyX 에서 와 같이printf
VC2015 기준으로 포맷 검사가 기본적으로 지원됩니다.그것은 없는 것입니다./analyze
정적 분석 패스.유감스럽게도 사용자 정의 래퍼 기능을 표시하는 메커니즘은 아직 없습니다.
이것은 printf로 전화하는 명백한 해결책을 제시합니다.이는 사용자 정의 함수와 함께 사용자 정의 함수를 모두 호출하는 매크로를 정의하는 것입니다.printf
그 자체. 는 최적화되어야 할 막다른 길에 있습니다후자는 최적화되어야 할 막다른 길에 있습니다.
이를 통해 다른 컴파일러에 대한 어느 정도의 이식성을 달성할 수 있는 추가적인 이점이 있습니다.
int printf_wrapper_(const char *format, ...);
#define printf_wrapper(...) \
(printf || printf(__VA_ARGS__), printf_wrapper_(__VA_ARGS__))
단점은 VC2015가 포맷 검사 전에 기본적인 데드 코드 제거를 수행하고 남은 라이브 코드만 테스트한다는 것입니다.
따라서sizeof
그렇지 않으면 일정한 조건식이 실패합니다.경험칙상 디버그 빌드에서 런타임 코드가 발생하면 경고 메시지가 표시되지만 나중에 릴리스 빌드에서 전달되면 여전히 호출이 중단될 수 있습니다.
이로 인해 향후 컴파일러 버전에서 변경될 가능성이 있는 이동 대상이 됩니다.비록 비교적 양성이지만요.
GCC는 -W 형식이 활성화된 경우 형식 지정자를 검사하지만 VC++는 표준 기능에 대해서도 이러한 검사가 없으므로 이와 동등한 기능이 없습니다.__attribute__
-W 형식과 동등한 형식이 없기 때문입니다.
(C89만 지원하면서 C++에 대한 ISO 준수를 유지하는 것으로 입증됨) 마이크로소프트가 C++를 강조한 것도 VC++에 포맷 지정자 검사가 없는 이유일 수 있다고 생각합니다.<iostream>
형식 지정자는 불필요합니다.
코드 프로젝트에 대한 Alexander Gorobets http://www.codeproject.com/KB/cpp/ValidateprintfFunction.aspx 의 "스타트업 검증을 위한 C++ 템플릿 사용"이라는 주제의 흥미로운 기사가 있습니다.
매크로를 가질 수 있도록 수정했습니다.PRINTF_VALIDATE(format, ...)
모든 형식 오류를 프로그램 상태 정보에 기록합니다(코드를 실제로 실행할 필요가 없음).이것은 다음과 같은 것을 만들어냅니다.
test.cpp(147) : error : 'printf' format character 'f' at position 1 does not match parameter type INT
test.cpp(147) : error : 'printf' too many arguments (3 instead of 2)
예를 들어 다음과 같이 사용할 수 있습니다.
#define LOG(fmt, ...) do { PRINTF_VALIDATE(fmt, __VA_ARGS__); WriteLog(fmt, __VA_ARGS__); } while(0)
이것은 컴파일러 지원만큼 유용하지는 않지만 비주얼 스튜디오 2005에서 작동합니다...
MSVS, GCC 및 clang에 대한 해결 방법: "만약 매크로를 사용하여 printf와 같은 함수를 호출하는 경우 도우미 매크로를 사용하여 다음과 같은 컴파일 시간 형식 검사를 받을 수 있습니다.
#define CHECK_FORMAT(...) \
do { \
char const dummy = sizeof(printf(__VA_ARGS__)); \
(void)dummy; \
} while (false)
#define MY_FMT(...) \
do { \
CHECK_FORMAT(__VA_ARGS__); \
MyFormatFunc(__FILE__, __LINE__, __VA_ARGS__); \
} while (false)
https://godbolt.org/z/38PaG5fx6
크기의 printf call은 평가되지 않아 코드가 생성되지 않지만, MSVC, GCC, Clang의 현재 버전은 여전히 형식 문자열 검사를 수행하므로 경고를 받습니다.로컬 더미 변수도 -O2와 함께 최적화됩니다."
휴대성에 대한 매크로를 정의하고 다음과 같은 코드를 작성하게 됩니다.
void stringPrintf(std::string* out, FOLLY_PRINTF_FORMAT const char* format, ...)
FOLLY_PRINTF_FORMAT_ATTR(2, 3);
정의(정적 함수 등 선언이 없을 수 있음)의 경우, GCC는 다음을 지원합니다.FOLLY_PRINTF_FORMAT_ATTR
처음에, 그래서 당신은 거기서 결국
FOLLY_PRINTF_FORMAT_ATTR(2, 3)
static void stringPrintf(std::string* out, FOLLY_PRINTF_FORMAT const char* format, ...)
{
///
}
머리말은
// compiler specific attribute translation
// msvc should come first, so if clang is in msvc mode it gets the right defines
// NOTE: this will only do checking in msvc with versions that support /analyze
#ifdef _MSC_VER
#include <stddef.h>
#ifdef _USE_ATTRIBUTES_FOR_SAL
#undef _USE_ATTRIBUTES_FOR_SAL
#endif
/* nolint */
#define _USE_ATTRIBUTES_FOR_SAL 1
#include <sal.h> // @manual
#define FOLLY_PRINTF_FORMAT _Printf_format_string_
#define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/
#else
#define FOLLY_PRINTF_FORMAT /**/
#define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \
__attribute__((__format__(__printf__, format_param, dots_param)))
#endif
이것은 MSVC, Clang, Clang on Windows, GCC와 함께 작동합니다.
거기에 사용된 매크로는 Facebook Folly, https://github.com/facebook/folly/blob/3a3a6d4fb673443f04536f2d385b9545ba135d7e/folly/Portability.h#L54 에서 가져온 것입니다.
언급URL : https://stackoverflow.com/questions/2354784/attribute-formatprintf-1-2-for-msvc
'programing' 카테고리의 다른 글
Android 완전히 투명한 상태 표시줄? (0) | 2023.10.25 |
---|---|
SQL 값이 없을 때도 행 유지 (0) | 2023.10.25 |
SQL Server 2008에서 테이블 설계를 변경할 수 없음 (0) | 2023.10.25 |
WordPress WP_Query - 상위 페이지만 쿼리 (0) | 2023.10.25 |
'log'에 대한 정의되지 않은 참조 (0) | 2023.10.25 |