简体   繁体   English

将值分配给数组需要memcpy

[英]Assign values to array requires memcpy

I've ran into a weird bug. 我遇到了一个奇怪的错误。

I'm writing code for a bootloader so I don't have many fancy libraries and all. 我正在为引导程序编写代码,所以我没有很多花哨的库。

The code itself is pretty simple, it's 代码本身很简单,就是这样

int array[32] = { 1, 2, 3, [...snip...], 31, 32 };

This code leads to an unresolved external problem regarding memcpy not being linked. 此代码导致有关memcpy未链接的未解决的外部问题。 However this code compiles and link fine 但是这段代码编译和链接很好

int array[12] = { 1, 2, 3, [...snip...], 11, 12 };

In fact, the error comes between 事实上,错误介于两者之间

int array[12] = { 0 };
and
int array[13] = { 0 };

The first one links fine, but the second cannot link. 第一个链接很好,但第二个不能链接。 I just don't get why at size 13, the compiler suddently decides to rely on memcpy for the thing. 我只是不明白为什么在13号,编译器突然决定依赖memcpy来做事情。 I tried with both -O0 and -O3. 我尝试了-O0和-O3。 My compiler is a windows executable called cl470, not really sure where that comes from. 我的编译器是一个名为cl470的Windows可执行文件,不确定它来自哪里。

Another weird thing is that this is problematic when I put it inside a function, but if I declare the array globally, then there is no problem. 另一个奇怪的事情是,当我把它放在一个函数中时,这是有问题的,但如果我全局声明数组,那么没有问题。

Your compiler is performing a time-space tradeoff . 您的编译器正在执行时空权衡

For the smaller array, the compiler is emitting individual instructions to initialise each array slot on the stack: 对于较小的数组,编译器会发出单独的指令来初始化堆栈上的每个数组插槽:

mov [ebp-4], 1
mov [ebp-8], 2
mov [ebp-12], 3
...

For the larger array, the compiler is placing the data in the program's read-only data segment and copying it onto the stack using memcpy : 对于较大的数组,编译器将数据放在程序的只读数据段中,并使用memcpy将其复制到堆栈中:

.rodata:
    _array_initialiser = { 1, 2, 3, ... }

push ebp-4
push _array_initialiser
push 32
call memcpy

This is why making the array file-scope or static will eliminate the memcpy ; 这就是为什么使数组文件范围或static将消除memcpy ; the array can be placed directly in the data segment and initialised at compile time. 数组可以直接放在数据段中,并在编译时初始化。

Using memcpy for larger arrays is more efficient because it reduces code size and so reduces instruction cache misses. 对大型数组使用memcpy更有效,因为它减少了代码大小,因此减少了指令缓存未命中。

Some things you could try are moving the array to file scope or making it static yourself; 您可以尝试的一些事情是将数组移动到文件范围或自己使其静态; if you need it reinitialised each time through the array you can copy it into a local array manually (although the compiler could also convert such a loop into a memcpy !) 如果你需要它每次通过数组重新初始化你可以手动将它复制到本地数组(虽然编译器也可以将这样的循环转换为memcpy !)

static const int array_data[] = { 1, 2, 3, ... };
int array[sizeof(array_data) / sizeof(array_data[0]))];
for (size_t i = 0; i < sizeof(array_data) / sizeof(array_data[0])); ++i)
    array[i] = array_data[i];

Another option would be to generate the array programmatically; 另一种选择是以编程方式生成数组; it looks like a simple for loop would work. 它看起来像一个简单的for循环可以工作。

Third option would be to write and link in your own memcpy ; 第三种选择是在你自己的memcpy编写和链接; it shouldn't require more than a few lines of code. 它不应该需要多行代码。

The following code copies data stored in your executable to stack. 以下代码将存储在可执行文件中的数据复制到堆栈。

int array[12] = { blah };

I guess the optimizer uses memcpy when the array size is greater than a certain number. 我想当数组大小大于某个数时,优化器使用memcpy。

You probably want to do this: 你可能想这样做:

static int array[12] = { blah };

By using the static keyword you prevent the compiler from generating code which copies static data to stack. 通过使用static关键字,可以防止编译器生成将静态数据复制到堆栈的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM