如何人为地增加 C++ 可执行文件的大小

17

我想制作一个虚拟的Win32 EXE文件,比它原本的大小要大得多。正常情况下,一个样板Win32 EXE文件大小为80KB。我想制作一个5MB大小的EXE文件来测试其他实用程序。

第一个想法是添加资源,但事实证明,嵌入式资源与内存分配时的5MB代码不一样。我在考虑是否可以引用一个大型库并最终获得一个巨大的EXE文件?如果不行,也许可以编写几千个类似的方法,如AddNum1、AddNum2,等等。

任何简单的想法都非常欢迎。


6
你能告诉我们你希望解决什么问题吗? - Francesco
1
这个问题并没有明确它的目的,因此答案对他人帮助不大。 - frast
1
为问题增加更多内容: - Phil
1
我正在调用CreateProcess函数。在这样做时,我需要它分配比简单(空)win32项目更多的内存。在这种情况下,我希望CreateProcess加载目标win32可执行文件并为其分配5MB的内存。 - Phil
3
请使用“编辑”按钮来为您的帖子添加更多细节。 - Hello71
19个回答

18

那么是否可以简单地定义一个大的静态字符数组呢?

char const bigarray[5*1024*1024] = { 1 };

请参考我在本主题中提供的另一个答案,我建议静态链接到大型库。如果您只引用足够多的库代码,这肯定会引入真实的代码。

编辑:添加了非零初始化,因为仅包含零的数据由编译器/链接器以优化的方式处理。

编辑:添加了对我的其他答案的引用。

编辑:添加const限定符,使得许多编译器将bigarray放置在代码中。


1
如果你从来没使用过它,那么它不应该被加载到物理内存中。因此,除非你关心它对可用虚拟地址空间的影响,否则不必担心它。 - Tyler McHenry
1
@Phil:你说你只想让磁盘上的大小变大,而不是内存使用量,但在实际问题中,你说内存分配应该是5MiB。我有什么遗漏吗? - legends2k
@legends2k:抱歉,磁盘上的大小也很重要,我正在使用分配内存的Createprocess。我需要它分配与磁盘上文件大小相同的内存。 - Phil
3
@Klaim,静态POD对象在链接时分配,这意味着它们存在于可执行文件中。 - Peter G.
1
@Klaim,我不知道有任何例外。许多编译器也会将const static POD对象与代码一起放置在只读节中。我现在在我的代码示例中添加了const。 - Peter G.
显示剩余6条评论

9
char big[5*1024*1024] = {1};

你需要将其初始化为非0值,否则编译器/链接器可能会进行优化。


这将只初始化第一个元素,其余的将是零。 - SuperJames
2
没错,但就这个问题而言,它被初始化为什么并不重要。将第一个元素设置为非零值似乎足以防止编译器优化该变量。换句话说,当您将其设置为全零时,编译器只会说“这里应该有500万个零”。而这会强制它说“这里有一个一,后面跟着一个零,再后面是一个零……” - Ferruccio

9
如果您想增加文件大小,可以将所需大小的文本文件附加到exe文件的末尾。
当客户抱怨小exe文件时,我曾经这样做。他们没有意识到小exe与大exe同样专业。实际上,在某些语言中,有一个bloat()命令用于增加exe文件的大小,通常在BASIC编译器中使用。
编辑:找到了一段人们使用的旧代码链接:http://www.purebasic.fr/english/viewtopic.php?f=12&t=38994 示例:https://softwareengineering.stackexchange.com/questions/2051/what-is-the-craziest-stupidest-silliest-thing-a-client-boss-asked-you-to-do/2698#2698

3
什么?!客户抱怨EXE文件太小?我从来没有遇到过如此愚蠢的客户。 - ptomato
2
是的,信不信由你!这就像一个沉重的相机。它越重,它就越“好”!初始程序发布时膨胀,随着每个后续更新,由于进一步的优化,声称内存占用更小! ;) - Gary Willoughby
EXE 文件中难道没有一些校验和验证方法吗?如果你添加一个文件,这种方法就会失败? - Amnon
除非你已经编写了exe文件来检查自身。 - Gary Willoughby
重型相机有一个优点:它们不太容易出现相机抖动(牛顿的F=ma等等!)。但是对于大型可执行文件来说,情况并非如此 :-) - psmears

8

使用汇编语言将EXE文件填充为NOPs。


6
只需要在.exe文件的末尾添加二进制零吗?

11
为什么不加一些十六进制的零呢?那些零更大:P。 - davidtbernal

5

使用一个大的常量数据数组,例如明确的字符串:

char *dummy_data[] = {
    "blajkhsdlmf..(long script-generated random string)..",
    "kjsdfgkhsdfgsdgklj..(etc...)...jldsjglkhsdghlsdhgjkh",
};

与可变数据不同,常量数据通常与实际代码位于同一内存段中,尽管这可能取决于编译器或链接器。

编辑:我在Linux上测试了以下内容,它可以正常工作:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int i, j;

    puts("char *dummy_data[] = {");
    for (i = 0; i < 5000; i++) {
        fputs("    \"", stdout);
        for (j = 0; j < 1000; j++) putchar('a' + rand() % 26);
        puts("\",");
    }
    puts("};");
    return 0;
}

这段代码和它的输出都可以干净地编译。


我尝试了这样的代码,结果出现了C2026错误。看起来数组有16K的限制? - Phil
1
如果您的字符串长度为1K,则数组中只需要5K个元素,这使得数组大小为20K(它是指向常量字符串的指针数组)。 - Edgar Bonet
我会使用内联汇编在某个地方创建一个NOP滑块。这样做更加简洁、语义更正确,而且有点自文档化。更不用说它不太可能被编译器搞砸了。 - Michael J. Gray

5

您可以创建大型的静态数据数组。这将增加exe文件的大小,但不是真正的代码。


这似乎是控制方法最简单、最容易的方式,来完成像这样的任务。 - Andrew Barber
2
当我看到这个问题时,我也考虑过这个,但它不会被优化掉吗? - legends2k
@Phil 如果你可以将它们静态链接,那就好了。否则这只是一堆导出/引用。 - enriquein
原因是,在测试时可能需要进行优化,即使是为了匹配实际的非臃肿代码。此外,rc 应该可以工作,因为 OP 说它是 Win32。 - legends2k
资源将无法工作。不知何故,Win32的CreateProcess方法知道资源未分配在相同的内存空间中。 - Phil
显示剩余3条评论

3
我发现即使进行了优化,原始字符串在编译后的可执行文件中仍保持不变。因此,正确的方法是:
  • 前往http://lipsum.org/
  • 生成大量文本。
  • 在您的程序中添加一个cpp文件。
  • 添加一个静态常量字符串,其值为生成的文本。
  • 编译。
  • 检查大小。
如果您的编译器有原始字符串大小限制,则只需每个静态字符串添加一个段落。
增加的大小应该很容易猜到。

3

您可以尝试创建一种递归模板,以生成许多不同的实例。这可能会导致代码大小的大幅增加。


还有编译时间;模板是 C++ 编译速度非常缓慢的最主要原因之一。 - imgx64

2

使用Boost,并使用调试信息编译可执行文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接