8

我目前正在将一个包含数百个代码文件和依赖项的项目移植到几个第三方库到 Mac Os 上。我终于达到了程序编译没有警告或错误的地步,但它似乎没有执行我自己的 main 函数。

相反,它似乎执行了一些其他似乎属于第三方的主要功能。此函数将一些诊断数据写入控制台,然后退出:

(gdb) continue
Current language:  auto; currently c++
//
// This is an automatically generated file.
// Do not edit.
//

const unsigned short expTable[] =
{
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
...
    0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 0x3c00, 
};

Debugger stopped.
Program exited with status value:0.

我无法使用调试器找出这个 main 函数所在的位置,因为虽然堆栈跟踪似乎有效,但 gdb 没有向我显示每个堆栈条目的正确行号和文件名(有关详细信息,请参阅这个未解决的问题)。

搜索需要几分钟才能完成,但没有返回任何结果。

我的项目在其他库中使用 SDL,但我获得了 SDL_Main() 和潜在问题的奖励,并且在完美运行的 SDL 项目模板之上构建了我的项目。所以我很确定我自己的主要功能是有效的。

你知道可能出了什么问题吗?我目前对如何查找和删除流氓主要功能一无所知。

谢谢,

阿德里安

编辑:正如我刚刚发现的那样,我在使用字符串“这是自动生成的”搜索文件文件时犯了一个错误。我刚刚发现了几十个具有相同字符串的文件,它们都属于我正在使用的第三方库之一 FreeImage。因此,问题似乎与 FreeImage 有关,但我仍然不确定如何继续,因为我已将 Freeimage 编译为包含 MacOs makefile 的库并且仅包含该库。我会尝试重建一个更新版本的 FreeImage 并查看它是否解决了我的问题。

4

10 回答 10

8

它可能是在调用 main() 之前失败的静态对象的初始化程序吗?

于 2009-03-05T12:22:15.563 回答
3

你有几个主要的二进制文件吗?尝试使用nm它。(它不应该ld与重复链接,但进入动态库并在_main那里寻找)

nm a.out | grep -5 _main

_main这应该在二进制文件中找到之前和之后给出 5 行a.out

如果您有多个,请查看周围的符号以提示它们位于哪些部分...

下一步可以对使用的每个动态库执行相同的操作。要获取使用的动态库的列表,请使用 otool

otool -L a.out
于 2009-03-05T13:33:35.580 回答
2

我不确定如何找到另一个,但您可以明确指定自己的入口点并使另一个不使用。您可以使用 GNU 链接器ld -e 选项来设置您的入口点。

-e 条目

--entry=条目

使用 entry 作为开始执行程序的显式符号,而不是默认的入口点。如果没有名为 entry 的符号,链接器将尝试将 entry 解析为一个数字,并将其用作入口地址(该数字将以 10 为基数解释;您可以使用前导 0x 表示基数 16,或者以 8 为基数的前导 0)。

对于未来的读者,如果您在 Windows 中遇到此问题。等效的链接器选项是/ENTRY

于 2009-03-05T12:24:46.743 回答
1

您是否尝试通过运行您的可执行文件nm?或许能给你一些提示。我认为不可能将一个程序与多个名为 的全局可见函数链接起来main(),但不确定这是如何实现的。

于 2009-03-05T12:06:55.427 回答
1

查看您包含的头文件,看看是否没有重新映射main到其他内容的定义。这是确保首先调用库的主要功能以进行某些设置的老技巧。通常,它最终会通过引用重新定义的值来调用您的 main 函数。

于 2009-03-05T12:25:52.120 回答
1

快速破解:

readelf -s -w my_bin_file > temp.txt

打开 temp.txt,搜索 main(在一列中带有 FUNC) 向上直到找到第一个 FILE 列 - 这是带有链接 main 的文件。

编辑:这只适用于 GNU Unix 风格和朋友。OS X 使用 Mach-O 格式,而不是 ELF。

于 2009-03-05T12:30:13.093 回答
0

我知道在 C 中,您可以在 main 函数之前调用不同的入口点,这可能是一个想法。代码通常如下所示:

void __attribute__ ((constructor)) my_main(void);

也许您可以在代码中搜索类似的内容。

在 C 中,也有不同的方法来捕获主函数并在“真正的”主函数之后调用它。一些线程库为了“准备”环境、调度程序和类似的东西而进行了这种黑客攻击。

这并不是很有用,但这可以解释为什么你的 main 根本没有被调用。

希望这可以帮助!

于 2009-03-05T12:45:44.087 回答
0

另一个注意事项。

WxWidgets 也定义了自己的main

这里

与所有程序一样,必须有一个“主要”功能。在 wxWidgets 下 main 是使用这个宏实现的,它创建一个应用程序实例并启动程序。

IMPLEMENT_APP(MyApp)

于 2009-03-05T13:39:47.530 回答
0

看起来您可以将一个名为的文件b44ExpLogTable.cpp编译到您的二进制文件或某个第三方库中。看起来那个小程序是生成一个 exp() 表,但不知何故被导入到您的项目中

在FreeImage 资源中查看这个和这个

于 2009-03-06T11:04:07.690 回答
0

生成地图文件。大多数程序实际上并不是从 main 开始的。来自 GCC 的映射文件应该告诉您 __start 或 __executable_start 的地址,您应该能够闯入并逐步查看导致程序退出的原因。

于 2009-03-06T11:33:49.587 回答