在main()之前,C/C++程序有什么方法可以崩溃吗?

Thi*_*Thi 63 c c++ crash function

程序在main()之前有什么方法可以崩溃吗?

R S*_*hko 36

使用gcc,您可以使用构造函数属性标记函数(这会导致函数在之前运行main).在以下函数中,premain将在之前调用main:

#include <stdio.h>

void premain() __attribute__ ((constructor));

void premain()
{
    fputs("premain\n", stdout);
}

int main()
{
    fputs("main\n", stdout);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以,如果有一个崩溃的错误,premain你将崩溃main.

  • 也许如果您的代码在共享库中,并且您不希望要求共享库的所有用户在其main()内部调用premain()(因为他们都会忘记这样做无论如何:)) (7认同)

And*_*bel 33

是的,至少在Windows下.如果程序使用DL​​L,则可以在main()启动之前加载它们.DllMain这些DLL 的功能将在之前执行main().如果他们遇到错误,他们可能会导致整个过程停止或崩溃.

  • 如何调试这样的问题? (3认同)

epa*_*tel 20

如果你有一个C++程序,它可以在输入main之前通过函数和构造函数初始化变量和对象.任何这些中的错误都可能导致程序崩溃.

  • 问题是关于C,而不是C++. (3认同)

pm1*_*100 18

肯定是在c ++; 具有结构的静态对象将在main之前被调用 - 它们可能会死亡

不确定c

这是样本

class X
{
public:
X()
{
  char *x = 0;
  *x = 1;
}
};

X x;
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将在主要之前崩溃

  • @Thi然后这样说,通过使用标签和问题标题和文字!但这是关于C的一个很好的问题,而且关于C++的问题不是很好,因为在这种情况下答案是微不足道的 - "是的". (8认同)
  • 问题是关于C,而不是C++. (5认同)

con*_*nio 18

简单的答案是:是的.

更具体地说,我们可以区分两个原因.我将它们称为依赖于实现且与实现无关的.

根本不依赖于您的环境的一种情况是C++中的静态对象,这里提到过.以下代码在此之前消失main():

#include <iostream>

class Useless {
public:
    Useless() { throw "You can't construct me!"; }

};

static Useless object;

int main() {
    std::cout << "This will never be printed" << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

更有趣的是与平台相关的原因.这里提到了一些.这里提到的一个是动态链接库的使用(Windows中的DLL,Linux中的SO等) - 如果你的操作系统的加载器之前加载它们main(),它们可能会导致你的应用程序之前死掉main().

这项事业的更一般的版本都在谈论的所有事情的二进制文件的入口点之前调用做你的入口点(main()).通常当你构建你的二进制文件时,有一个相当严重的代码块,当你的操作系统的加载器开始运行你的二进制文件时调用它们,当它完成时它会调用你的main().这段代码的一个常见问题是初始化C/C++标准库.此代码可能由于多种原因而失败(它尝试为一个系统资源分配的任何类型的系统资源不足).

main()在Windows上使用二进制文件执行代码的一个有趣方法是使用TLS回调(谷歌会告诉你更多关于它们的信息).这种技术通常在恶意软件中被发现作为一种基本的反调试技巧(这个技巧当时用来欺骗ollydbg,不知道它是否仍然存在).

关键是你的问题实际上等同于"有没有办法加载二进制文件会导致用户代码在代码进入之前执行main()?",答案是地狱,是的!


nat*_*ose 10

依赖于在main之前加载的共享对象(DLL)的任何程序都可能在main之前失败.

在Linux下,动态链接器库(ld - *.so)中的代码运行以在main之前提供任何库依赖项.如果无法找到任何所需的库,具有不允许您访问它们的权限,不是普通文件,或者没有一些符号表示链接您的程序的动态链接器认为它应该具有它链接了你的程序然后这可能会导致失败.

此外,每个库在链接时都会运行一些代码.这主要是因为库可能需要链接更多的库或者可能需要运行一些构造函数(即使在C程序中,库也可能有一些C++或其他使用constroctors的东西).此外,标准C程序已经创建了stdio FILEs stdin,stdout和stderr.在许多系统上,这些也可以关闭.这意味着它们也是free()ed,这意味着它们(和它们的缓冲区)是malloc()ed,它们可能会失败.它还表明他们可能已经对那些FILE结构所代表的文件描述符做了一些其他的事情,这可能会失败.

其他可能发生的事情可能是操作系统要设置环境变量和/或传递给程序的命令行参数.在调用main之前,main之前的代码可能不得不使用这些数据.

主要之前发生了很多事情.他们中的任何一个都可以以致命的方式失败.


Sim*_*lli 6

我不确定,但是如果你有一个像这样的全局变量:

static SomeClass object;

int main(){
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

'SomeClass'构造函数可能会在main执行之前使程序崩溃.

  • 很难在C中有一个类构造函数,问题被标记出来. (6认同)
  • 问题是关于C,而不是C++. (2认同)

Mat*_* M. 5

有很多种可能性.

首先,我们需要了解main执行之前实际发生了什么:

  • 加载动态库
  • 全局变量的初始化
  • 一些编译器,一些函数可以显式执行

现在,任何这种情况都可能在几个方面导致崩溃:

  • 通常的未定义行为(取消引用空指针,访问内存,你不应该...)
  • 抛出异常>因为没有catch,terminate被调用并且程序结束

这当然很烦人,可能很难调试,这就是为什么你应该尽可能地避免执行代码main,如果可以,或者在内部进行显式初始化,则更喜欢延迟初始化main.

当然,当它是一个DLL失败并且你无法修改它时,你就陷入了痛苦的世界.


Car*_*rum 1

当然,如果操作系统或运行时代码中存在错误。C++ 因这种行为而臭名昭著,但在 C 中仍然可能发生。