增加二进制可执行文件的大小

10

摘要问题: 我有一些C代码。编译后,可执行文件大小为604 KB。 我希望它更大,比如说100 MB。

如何实现这一点?

我可以声明一个字符串来增加二进制文件的大小,但是否有更具可扩展性的解决方案呢?也就是说,我希望在不增加源代码N个字节的情况下将编译后的大小增加N个字节。

 char* filler = "filler"; // increases compiled size only by few bytes

应用场景: 我正在开发固件,并测试远程固件升级功能。我想看看当固件很大和重时它会表现如何。


5
"抽象问题" - 不行,你不能这么容易地逃避,我很好奇。你真正的问题是什么? :) - StoryTeller - Unslander Monica
类似 echo abcd >> myprogram.exe 这样的操作可行吗? - Stephan Lechner
我刚才浏览了https://en.wikipedia.org/wiki/Executable_and_Linkable_Format可执行文件(ABI)遵循该布局。正如您所看到的,各种大小和偏移字段散落在各个地方,因此,如果要附加一个死区段,您可能需要修改这些大小和偏移量。建议:使用bash脚本(甚至是makefile中的一些代码)在编译时生成一个.c文件并将其包含在项目中。您可以自动化指定const char数组的大小的过程,就像发出make命令时那样。 - lithiumhead
@el.pescado,我在问题中添加了解释。 - mjjaniec
@StoryTeller 读取“用例”。 - mjjaniec
显示剩余5条评论
3个回答

16

使用gcc编译时,会产生一个100MB的可执行文件:

#include <stdio.h>
#define SIZE 100000000

char dummy[SIZE] = {'a'};

int main(void){
    dummy[SIZE-1] = '\n';
    if(dummy[0] == 'a')printf("Hello, bloated world");
    return 0;
}

通过在main外定义数组,避免了堆栈溢出的问题。使用这个数组时,gcc不会将其优化掉。


1
请注意,至少需要一个非零的初始化器,否则您将无法获得大型可执行文件。 - dbush
很好。我尝试过它,但我没有使用数组,所以它被优化了。 - mjjaniec
@dbush 我注意到了。这就是为什么我换成了'a'。我最初尝试使用'\0',但惊讶的是可执行文件仍然很小。我真的不明白为什么会这样。 - John Coleman
所有值为零的变量通常会被分组在一起,并在调用main之前使用一个大的memset进行初始化,以保持可执行文件的大小不变。 - user694733
1
@JohnColeman:这是因为初始化为零的元素将被放置在BSS部分,而不会出现在可执行文件中,因为加载程序可以在运行时构造它们。 - Crowman

9

GCC 特定变体:

char dummy[100*1024*1024] __attribute__((used)) = { 77 };

应用'used'属性后,您就不需要再去操作它以防止被优化掉。但是,必须像John Coleman的解决方案中一样应用非全空的初始化器。

1
你需要创建一个全局数组,并明确初始化所有元素。这些元素应该是随机的,否则编译器很可能会在编译后的代码中优化初始化程序列表。
首先,你需要一个单独的程序来生成你的数组:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    int len = 100000000;
    int i;
    srand(getpid());
    printf("unsigned char buf[%d] = {\n", len);
    for (i=0;i<len;i++) {
        printf(" %hhu,", rand() & 0xff);
        if (i%16==15) printf("\n");
    }
    printf("};\n\n");
    return 0;
}

运行此命令并将输出重定向到文件:

./array_generator > array.c

然后你将得到一个类似于这样的array.c文件:
unsigned char buf[1000000] = { 
247, 223, 30, 51, 46, 247, 133, 136, 254, 225, 82, 135, 68, 176, 240, 7,
29, 245, 104, 203, 230, 83, 127, 189, 37, 5, 168, 105, 134, 9, 229, 125,
232, 3, 176, 23, 251, 53, 159, 249, 22, 241, 128, 90, 161, 112, 97, 191,
101, 202, 138, 75, 29, 10, 9, 66, 15, 177, 171, 149, 186, 145, 18, 163,
...
};

然后您将其包含在主要源代码中:

#include  "array.c"

不想过于挑剔,但问题确实要求“……不增加 N 字节的源代码。”这个方法可以用,但应该先测试一下 JohnColeman 的解决方案:许多嵌入式编译器在优化初始化列表方面并不那么出色。 - user694733
@user694733 这是一个很好的观点,如果所使用的编译器没有优化初始化列表,那么其他方法可能更好。如果不是这种情况,那么至少使用这种方法,您不需要手动创建一个大的源文件。 - dbush

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