C에서 variable-length argument를 다시 파라미터로 넘길때

labien의 이미지

로그를 남기는 함수를 하나 만들고 있는데요...이 함수는 설정에 따라 파일이나
syslog, 네트웍으로 로그를 날려줍니다...

make_log라는 함수가 있다고 할때 이 함수는 variable-length argument를 받아 이전에 설정한 설정치에 따라 다른 target으로 로그를 쏘게 되는데요..
syslog일때는 그대로 메시지를 syslog함수를 호출하여 날려줍니다...근데 문제가 생겼습니다.-_-
아래의 예제 코드에서

void makelog(int priority, char* fmt,...)
{
    syslog(priority, fmt);
}

void main(void)
{

    openlog("syslogtest1", LOG_PID, LOG_LOCAL7);
    makelog(LOG_NOTICE, "this is a syslog test message %s%d\n", "test", 1234);
    
}

위와 같이 하면 %s와 %d자리에 쓰레기값이 나오거나 segment fault내면서 프로그램이 죽게됩니다.(당연할꺼같습니다.)

그럼 문제는 위과 같이 variable-length argument를 받는 함수에서 그 argument들을 그대로 다른 variable-length argument를 받는 함수로 넘길때 어떻게 해야하는지가 궁금합니다.

테스트로 (안될꺼알면서도..)

void makelog(int priority, char* fmt,...)
{
    va_list ap;
    va_start(ap, fmt);
    syslog(priority, fmt, ap);
    va_end(ap);
}

위와 같이 해봐도 안됩니다...어떻게 하면 될까요..흑흑...고수님들 부탁드리겠습니다!!!

cinsk의 이미지

#include <syslog.h>
#include <stdarg.h>

void
make_log(int priority, const char *fmt, ...)
{
  va_list argptr;
  va_start(argptr, fmt);
  vsyslog(priority, fmt, argptr);
  va_end(argptr);
}
labien의 이미지

헉...vsyslog가 있다니....
찾아보니 RedHat 6.2에는 vsyslog에 대해서는 맨페이지가 없네요...(7.2에는 있군요..)
어떻게 이런 함수가 있다는걸 아시는지....vsyslog가 있을꺼라고는 생각치도
못했네요...크흐~~..

감사합니다..꾸벅~~~

cinsk의 이미지

만약에 vsyslog를 못 쓸 경우라면, 다음과 같이 만들 수는 있습니다.

#include <syslog.h>
#include <stdarg.h>
#include <limits.h>

#ifndef LINE_MAX
#define LINE_MAX	4096
#endif

void
make_log(int priority, const char *fmt, ...)
{
  static char buf[LINE_MAX];
  va_list argptr;

  va_start(argptr, fmt);
  vsnprintf(buf, LINE_MAX, fmt, argptr);
  va_end(argptr);

  syslog(priority, "%s", buf);
}

그런데 이 방법을 쓰면, 메시지 길이가 LINE_MAX에 제한된다는 것이
단점입니다. 아 물론, LINE_MAX 대신 다른 상수를 쓰거나, 아니면
적당한 수치로 버퍼를 잡으면 되긴 합니다만,

man을 참고하니 리눅스의 경우 syslog는, 원래는 4096,
1.3.54부터는 8192, 2.1.113부터는 16384의 크기의 메시지를 지원하는것
같습니다.

적당한 크기로 사용하세요.
많이 찾아보지 않아서, (어딘가에 메시지 최대 길이를 정의한 매크로
상수가 있을 법한데) 잘 모르겠군요.

참 그리고, 위의 코드에서는 buf를 static으로 잡았기 때문에, 위 함수는
재진입(reentrance)할 수 없습니다. thread를 쓴다거나 할 때는 주의하시길.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.