2013-09-24 45 views
1

考慮我有一個動態的外部庫libExternal.dylib以下功能的外部庫函數:傳遞爲const char *從該需要一個char *

void print(char* str) 
{ 
    // Changes the first char to 'a' and prints the string 
    *str = 'a'; 
    printf("%s\n", str); 
} 

接下來,我有一個加載這個外部庫和調用可執行(檢查省略誤差)函數:

int main(int argc, const char * argv[]) 
{ 
    void* hLib = dlopen("libExternal.dylib", RTLD_LAZY | RTLD_LOCAL); 

    typedef void(*printFunc)(const char*); 
    printFunc func = (printFunc)dlsym(hLib, "print"); 

    std::string test = "hello"; 
    func(test.c_str()); 

    dlclose(hLib); 

    return 0; 
} 

正如你可以看到,在庫中定義的函數以一個char*作爲參數。當使用dlsym時,我使它得到了一個函數,它需要一個const char*。它的工作原理!

我的問題是,這怎麼可能?動態加載器忽略const類型?我真的無法在任何地方找到答案,所以請幫助我! :)

編輯: 我知道這個代碼是錯誤的,我只是想了解這是如何可能的。

+0

請注意「問題預覽」窗口,並使用正確的代碼格式(此次修復它)。 – Angew

回答

4

它可以工作,但並不意味着它是正確的。

它不會忽略const的類型,你鑄造外部函數,它接受常量類型的函數:

typedef void(*printFunc)(const char*); 
         ^^^^^^^^^^^ 

printFunc func = (printFunc)dlsym(hLib, "print"); 
       ^^^^^^^^^^^ 

,並嘗試使用正確的函數簽名,以避免未定義行爲因修改常量值。

+0

這是正確的,我鑄造它,但鑄造一個const char * char *是錯誤的。我不明白代碼如何運行而不會崩潰。 –

+3

@LuísMendes這是一個僥倖,它的工作。 'std :: string'的動態存儲實際上是一個非''contst'數組,所以它看起來工作正常。您正跨越動態庫邊界並使用不正確的函數類型;編譯器無法檢測到這個錯誤。 – Simple

+0

@Simple:'test'作爲'std :: string'是非const的,但'test.c_str()'的返回值是const。 – deepmax

1

傳遞const char *foo(char *str)是未定義行爲(UB)。

它可以工作,它可能不會。它肯定不會在防止寫入const內存的系統上工作。其他系統是寬鬆的,隨後的操作可能會/不會按預期工作。

C11草案6.7.3。 6

+0

@Giorgi是的 - 它仍然是UB。想想一個系統,其中'const'和non-'const'指針有一些屬性附加到它們的指針值。而且該系統無法將'const'轉換爲非''constst'指針。 – chux

+0

@Giorgi也許C11dr第6.3.2.3節8「...如果使用轉換的指針調用其類型與引用類型不兼容的函數,則行爲是未定義的。」 – chux

+0

@Giorgi如果可以的話,是傳遞non-'const'到'c​​onst。 – chux

相關問題