c++ - "no main"C++ 中用于链接或执行的函数

标签 c++ linux macos compilation

我正在尝试编译一个可以集成到另一个代码中或直接执行(链接后)的函数(不称为 main)。

我在我的 Mac 上尝试了一下,效果很好。 我最终在Linux(CentOS和ubuntu)上测试了它。然而,正如预期的那样,该任务在 Linux 上看起来更困难。

源码如下(只是为了说明问题)

测试.cpp:

#include <cstdio>

#ifdef __cplusplus 
extern "C" {
#endif
    int test(int argc, char const *argv[]);
#ifdef __cplusplus
}
#endif

int test(int argc, char const *argv[]) {
    fprintf(stderr, "%s\n", "test");
    return 0;
}

MacOS 上的编译行

g++ -c test.cpp -o test.o && g++ test.o -o test -e _test

在 Linux 上

g++ -c test.cpp -o test.o && g++ test.o -o test -e test

我在我的 MacOS 上尝试使用 clang、g++ 和 Intel 编译器,这 3 个编译器都工作正常。

我在 Linux 上尝试使用 g++ 和 Intel 编译器,总是出现同样的错误。

usr/lib/gcc/x86_64-linux-gnu/5/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

任何关于我做错或遗漏的建议、解释或解决方案都会非常有帮助。 谢谢

编辑:

目前,我有一个“定义”来创建一个 main,但如果我们有很多函数,我们有义务每次进行两次编译(一次用于函数版本,一次用于执行),最终使代码变得更重。

就像本主题中讨论的那样 is there a GCC compiler/linker option to change the name of main?

为了不做 XY,我继承了一堆我想要收集的小程序,这样它更容易使用(用于远程执行......)。然而,如果需要的话,每个函数都需要能够独立执行,以便进行调试……我在使用“execv”和将每个 main 转换为函数之间犹豫不决。我可能会做出错误的选择。

编辑: 最终的目标是能够拥有独立的节目。但我们也可以从外部软件调用。

解决方案: 解决方案看起来是通过 dlopen 调用 main

最佳答案

你不能这样做(即使它看起来可以在 MacOSX 上运行,它也是特定于实现的 undefined behavior )。

Linux crt0正在做比你想象的更复杂的事情。

C 标准(例如 C11 的 n1570)需要用于托管实现的 main 函数 (§5.1.2.2.1):

The function called at program startup is named main. The implementation declares no prototype for this function.

C++ 标准也是 requires a main并且强烈要求在 main 运行之前和之后返回一些处理(例如静态数据的构造)(各种 crt0 技巧正在 Linux 上实现该功能)。

如果您想了解血淋淋的细节(而且它们并不容易!),请研究ABI以及 crt0 实现的(免费软件)源代码。

I am trying to compile a function (not called main) that can be integrated in another code

顺便说一句,要动态使用另一个程序中的某些代码(例如 plug-ins ),请考虑使用 dynamic linker 。我建议使用符合 POSIX 标准的 dlopen(3)dlsym(3)position-independent code共享库。它适用于大多数 Unix 版本(包括 MacOSX & Linux & Solaris & AIX)。对于 C++ 代码,请注意 name mangling所以至少阅读C++ dlopen mini howto .

另请阅读 Program Library HowTo .

Problems with libraries, they cannot be executed, no ?

我不明白这是什么意思。您当然可以加载一个插件,然后从主程序 dlopen 运行它内部的代码。

(在 Linux 上,一些库(例如 libc.so)甚至是专门构建的,也可作为可执行文件使用;我不建议您自己的代码采用这种做法)

您可能需要几天时间才能阅读 Drepper 的 How To Write Shared Libraries (但这是高级的东西)。

<小时/>

如果您想在运行时添加一些代码,另请阅读 this answerthat one .

The final goal is to be able to have independent program. But that we can call from an external software too

你不能这样做(而且没有意义)。但是,您可以使用 processes 与其他正在运行的程序(即 inter-process communication )进行通信。如pipe(7) -s 和许多其他。阅读 Advanced Linux Programming首先和编码之前。另请阅读Operating Systems : Three Easy Pieces

The solution looks to be, to a call to the main through a dlopen

C++ 标准禁止通过 dlopendlsym 调用 main 函数(该标准不允许使用指向 main 的指针)。 main 函数具有非常具体的地位和作用(并且是专门编译的;编译器知道 main)。

(也许调用由 dlsym 获得的 main 似乎可以在某些 Linux 系统上工作,但这肯定是未定义的行为,因此您不应该这样做)

关于c++ - "no main"C++ 中用于链接或执行的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45440506/

相关文章:

c++ - 将列出哪些设备

c++ - VS 中的 malloc 异常

java - 在 linux 中发出 kill 命令时优雅地停止嵌入式 jetty 服务器

java - 读取新终端窗口的控制台输出

c++ - Marshall char** to string 从托管代码调用非托管代码的问题

c++ - 在动态分配的内存中在字符串后存储 int 时出错

python - 实时获取 shell 输出并将所有输出存储在变量中

c++ - 调用execvp()后主窗口关闭

macos - 如何使用透明背景对视频进行编码

swift - CFArray takeRetainedValue() 删除导致崩溃