2012-08-13 194 views
0

我試圖編譯的MinGW下,並在源文件seterror.c SASL聲明瞭兩個功能如下:gcc是否可以不編譯代碼?


#include <config.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <limits.h> 
#ifdef HAVE_SYSLOG 
#include <syslog.h> 
#endif 
#include <stdarg.h> 
#include <ctype.h> 

#include <sasl.h> 
#include <saslutil.h> 
#include <saslplug.h> 
#include "saslint.h" 

#ifdef WIN32 
/* need to handle the fact that errno has been defined as a function 
    in a dll, not an extern int */ 
# ifdef errno 
# undef errno 
# endif /* errno */ 
#endif /* WIN32 */ 
#ifdef HAVE_UNISTD_H 
#include <unistd.h> 
#endif 

static int _sasl_seterror_usererr(int saslerr) 
{ 
    /* Hide the difference in a username failure and a password failure */ 
    if (saslerr == SASL_NOUSER) 
    return SASL_BADAUTH; 

    /* otherwise return the error given; no transform necessary */ 
    return saslerr; 
} 

void sasl_seterror(sasl_conn_t *conn, 
      unsigned flags, 
      const char *fmt, ...) 
{ 
    size_t outlen=0; /* current length of output buffer */ 
    size_t pos = 0; /* current position in format string */ 
    size_t formatlen; 
    int result; 
    sasl_log_t *log_cb = NULL; 
    void *log_ctx; 
    int ival; 
    char *cval; 
    va_list ap; /* varargs thing */ 
    char **error_buf; 
    size_t *error_buf_len; 

    if(!conn) { 
#ifndef SASL_OSX_CFMGLUE 
     if(!(flags & SASL_NOLOG)) { 
     /* See if we have a logging callback... */ 
     result = _sasl_getcallback(NULL, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx); 
     if (result == SASL_OK && ! log_cb) 
      result = SASL_FAIL; 
     if (result != SASL_OK) 
      return; 

     log_cb(log_ctx, SASL_LOG_FAIL, 
     "No sasl_conn_t passed to sasl_seterror"); 
     } 
#endif /* SASL_OSX_CFMGLUE */ 
     return; 
    } else if(!fmt) return;  

/* we need to use a back end function to get the buffer because the 
    cfm glue can't be rooting around in the internal structs */ 
    _sasl_get_errorbuf(conn, &error_buf, &error_buf_len); 

    formatlen = strlen(fmt); 

    va_start(ap, fmt); /* start varargs */ 

    while(pos<formatlen) 
    { 
    if (fmt[pos]!='%') /* regular character */ 
    { 
     result = _buf_alloc(error_buf, error_buf_len, outlen+1); 
     if (result != SASL_OK) 
    return; 
     (*error_buf)[outlen]=fmt[pos]; 
     outlen++; 
     pos++; 
    } else { /* formating thing */ 
     int done=0; 
     char frmt[10]; 
     int frmtpos=1; 
     char tempbuf[21]; 
     frmt[0]='%'; 
     pos++; 

     while (done==0) 
     { 
    switch(fmt[pos]) 
     { 
     case 's': /* need to handle this */ 
     cval = va_arg(ap, char *); /* get the next arg */ 
     result = _sasl_add_string(error_buf, error_buf_len, 
         &outlen, cval); 

     if (result != SASL_OK) /* add the string */ 
      return; 

     done=1; 
     break; 

     case '%': /* double % output the '%' character */ 
     result = _buf_alloc(error_buf, error_buf_len, outlen+1); 
     if (result != SASL_OK) 
      return; 
     (*error_buf)[outlen]='%'; 
     outlen++; 
     done=1; 
     break; 

     case 'm': /* insert the errno string */ 
     result = _sasl_add_string(error_buf, error_buf_len, 
         &outlen, 
         strerror(va_arg(ap, int))); 
     if (result != SASL_OK) 
      return; 
     done=1; 
     break; 

     case 'z': /* insert the sasl error string */ 
     result = _sasl_add_string(error_buf, error_buf_len, &outlen, 
      (char *)sasl_errstring(_sasl_seterror_usererr(
          va_arg(ap, int)),NULL,NULL)); 
     if (result != SASL_OK) 
      return; 
     done=1; 
     break; 

     case 'c': 
     frmt[frmtpos++]=fmt[pos]; 
     frmt[frmtpos]=0; 
     tempbuf[0] = (char) va_arg(ap, int); /* get the next arg */ 
     tempbuf[1]='\0'; 

     /* now add the character */ 
     result = _sasl_add_string(error_buf, error_buf_len, 
         &outlen, tempbuf); 
     if (result != SASL_OK) 
      return; 
     done=1; 
     break; 

     case 'd': 
     case 'i': 
     frmt[frmtpos++]=fmt[pos]; 
     frmt[frmtpos]=0; 
     ival = va_arg(ap, int); /* get the next arg */ 

     snprintf(tempbuf,20,frmt,ival); /* have snprintf do the work */ 
     /* now add the string */ 
     result = _sasl_add_string(error_buf, error_buf_len, 
         &outlen, tempbuf); 
     if (result != SASL_OK) 
      return; 
     done=1; 

     break; 
     default: 
     frmt[frmtpos++]=fmt[pos]; /* add to the formating */ 
     frmt[frmtpos]=0;   
     if (frmtpos>9) 
      done=1; 
     } 
    pos++; 
    if (pos>formatlen) 
     done=1; 
     } 

    } 
    } 

    (*error_buf)[outlen]='\0'; /* put 0 at end */ 

    va_end(ap); 

#ifndef SASL_OSX_CFMGLUE 
    if(!(flags & SASL_NOLOG)) { 
     /* See if we have a logging callback... */ 
     result = _sasl_getcallback(conn, SASL_CB_LOG, (sasl_callback_ft *)&log_cb, &log_ctx); 
     if (result == SASL_OK && ! log_cb) 
     result = SASL_FAIL; 
     if (result != SASL_OK) 
     return; 

     result = log_cb(log_ctx, SASL_LOG_FAIL, conn->error_buf); 
    } 
#endif /* SASL_OSX_CFMGLUE */ 
} 

有周圍沒有任何的#define可言。當我編譯時:gcc -DHAVE_CONFIG_H -I. -I.. -I../include -I../lib -I../sasldb -I../include -Wall -W -g -O2 -c seterror.c nm產生:

$ nm seterror.o 
00000000 b .bss 
00000000 d .data 
00000000 N .debug_abbrev 
00000000 N .debug_aranges 
00000000 N .debug_info 
00000000 N .debug_line 
00000000 N .debug_loc 
00000000 N .debug_ranges 
00000000 N .debug_str 
00000000 r .eh_frame 
00000000 r .rdata 
00000000 t .text 
     U __buf_alloc 
     U __imp__sasl_errstring 
     U __sasl_add_string 
     U __sasl_get_errorbuf 
     U __sasl_getcallback 
00000000 T _sasl_seterror 
     U _snprintf 
     U _strerror 

爲什麼沒有地址?如果我運行nm庫我得到:

$ nm .libs/libsasl2.a | grep sasl_seterror 
     U __imp__sasl_seterror 
     U __imp__sasl_seterror 
     U __imp__sasl_seterror 
     U __imp__sasl_seterror 
     U __imp__sasl_seterror 
     U __imp__sasl_seterror 
     U __imp__sasl_seterror 
00000000 T _sasl_seterror 

仍然沒有地址,爲什麼?最後,當我嘗試鏈接庫時,我收到錯誤說undefined reference to '__imp__sasl_seterror'

任何人都可以幫助解釋這裏發生了什麼?

+0

第一個是靜態的,因此對象是局部的,它們都只是原型。那裏的功能團體呢? – 2012-08-13 17:38:32

+0

您在命令行中定義了'-DHAVE_CONFIG_H',這看起來很奇怪。通常這些用於包括守衛,但你似乎沒有包含任何頭部? – 2012-08-13 17:50:55

+0

@JensGustedt我沒有包括整個文件,應該嗎?這有什麼不同嗎? – chacham15 2012-08-13 18:02:01

回答

0

有鏈接爲標題行如下:

LIBSASL_API void sasl_seterror(sasl_conn_t *conn, unsigned flags, 
        const char *fmt, ...); 

LIBSASL_API被定義爲:


#ifdef WIN32 
# ifdef LIBSASL_EXPORTS 
# define LIBSASL_API __declspec(dllexport) 
# else /* LIBSASL_EXPORTS */ 
# define LIBSASL_API __declspec(dllimport) 
# endif /* LIBSASL_EXPORTS */ 
#else /* WIN32 */ 
# define LIBSASL_API extern 
#endif /* WIN32 */ 

因此,函數被編譯,就好像它是將要動態地鏈接。

但是,nm仍然對sasl_seterror產生00000000 T,但鏈接器不再抱怨該函數。

2
static int _sasl_seterror_usererr(int saslerr); 

void sasl_seterror(sasl_conn_t *conn, 
      unsigned flags, 
      const char *fmt, ...); 

這兩個函數都沒有定義函數,它們只聲明它。他們承諾您將提供該功能,但不要自行提供。因此,當您違反諾言時,您會收到鏈接錯誤。

您需要實際定義函數以獲取地址並鏈接到它。

+0

即時對不起,它的定義,我只是不想粘貼整個定義。 – chacham15 2012-08-13 17:41:49

+0

定義在哪裏?它們是否在同一個源文件中?或者他們在不同的源文件或庫中? – 2012-08-13 18:13:21

+0

@JohnBode同一個文件,我上面更新了包含文件。 – chacham15 2012-08-13 18:22:39

相關問題