2013-09-24 29 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

相关问题