【问题标题】:memcpy mixing up contents of struct?memcpy 混淆了结构的内容?
【发布时间】:2017-05-04 16:09:47
【问题描述】:

我一直在编写 R2K 对象模块,但在将符号表条目写入文件时遇到了麻烦。我一直在尝试使用 memcpy 将存储在 sym_table 中的符号表的条目放入一个名为 bytes_sym 的单字节整数数组中,然后将其写入文件中。它复制了正确的大小,但由于某种原因混淆了字节的位置。这是我的代码:

/*
** symbol table entry
*/    
typedef
struct syment {
    uint32_t flags;      /* flag word */
    uint32_t value;      /* value associated with this symbol */
    uint32_t sym;        /* symbol name's index into string table */
}
    syment_t;

// header->data[8] is the number of symbol table entries
int sym_length = header->data[8] * sizeof(syment_t);

uint8_t bytes_sym[sym_length];

for(int i = 0; i < header->data[8]; i++){
    memcpy(&bytes_sym[i * sizeof(syment_t)], &sym_table[i], sizeof(syment_t));
}
fwrite(bytes_sym, sym_length, 1, file);

// prints the newly copied symbol table section one byte at a time
// I know it's gross to look at, but it's only for testing :p
printf("New Symtab:\n");
for(int i = 0; i < sym_length; i++){
    printf("0x%x ", bytes_sym[i]);
}
printf("\n");

在写入之前,字节值是:

0x0 0x0 0x0 0xb1 0x0 0x40 0x0 0x2c 0x0 0x0 0x0 0x0
0x0 0x0 0x0 0xa3 0x10 0x0 0x0 0x20 0x0 0x0 0x0 0x5
0x0 0x0 0x40 0xb1 0x0 0x40 0x0 0x38 0x0 0x0 0x0 0xb
0x0 0x0 0x0 0xa1 0x0 0x40 0x0 0x14 0x0 0x0 0x0 0x10
0x0 0x0 0x40 0xb1 0x0 0x40 0x0 0x0 0x0 0x0 0x0 0x15
0x0 0x0 0x0 0x67 0x0 0x0 0x0 0x11 0x0 0x0 0x0 0x1f
0x0 0x0 0x0 0xa2 0x10 0x0 0x0 0x0 0x0 0x0 0x0 0x19
0x0 0x0 0x40 0xb1 0x0 0x40 0x0 0x64 0x0 0x0 0x0 0x29

写完后,它们是(不正确,应该不一样):

0xb1 0x0 0x0 0x0 0x2c 0x0 0x40 0x0 0x0 0x0 0x0 0x0 
0xa3 0x0 0x0 0x0 0x20 0x0 0x0 0x10 0x5 0x0 0x0 0x0 
0xb1 0x40 0x0 0x0 0x38 0x0 0x40 0x0 0xb 0x0 0x0 0x0 
0xa1 0x0 0x0 0x0 0x14 0x0 0x40 0x0 0x10 0x0 0x0 0x0 
0xb1 0x40 0x0 0x0 0x0 0x0 0x40 0x0 0x15 0x0 0x0 0x0 
0x67 0x0 0x0 0x0 0x11 0x0 0x0 0x0 0x1f 0x0 0x0 0x0 
0xa2 0x0 0x0 0x0 0x0 0x0 0x0 0x10 0x19 0x0 0x0 0x0 
0xb1 0x40 0x0 0x0 0x64 0x0 0x40 0x0 0x29 0x0 0x0 0x0

我无法理解是什么原因造成的,因此我们将不胜感激!

【问题讨论】:

  • 欢迎来到 Stack Overflow。请尽快阅读AboutHow to Ask 页面。数据结构是什么样的?我们需要知道这一点。另请阅读有关如何创建 MCVE (minimal reproducible example) 的信息。
  • 所以你也想看看代码写入和读取数据吗?同时将0x%x 设为0x%02x
  • 看起来像是一个大端与小端的问题。我们需要更多信息,尤其是minimal reproducible example 会有所帮助,但memcpy 绝对不会混淆任何东西。问题出在其他地方。
  • 我的理解是正确复制了值。正是您阅读它们以打印的方式是导致问题的原因。你能在 memcopy 之前显示打印代码吗?还有哪一个是正确的?
  • 您实际上需要提供minimal reproducible example 才能确定查看,但似乎更有可能是您没有一致地打印数据。跨度>

标签: c file io memcpy


【解决方案1】:

好吧,你们完全撒谎memcpy 没有弄乱我的数据。在做了一些研究之后,我发现这是一个字节序的东西,它颠倒了我的 32 位对象模块的符号表部分中每个 4 字节块中的字节顺序。所以我写了一个小函数来修复它:

///    Flips the bytes in each 4 byte block after the endian flip caused by memcpy
///    @param - the array of bytes
///    @param - the length of the array in bytes
///
void flip_bytes(uint8_t byte_array[], int length){

    uint8_t tmp;
    for(int i = 0; i < length; i++){
            if((i+1) % 4 == 0){

                    // switch the first and last bytes
                    tmp = byte_array[i];
                    byte_array[i] = byte_array[i-3];
                    byte_array[i-3] = tmp;
                    // switch the middle 2 bytes
                    tmp = byte_array[i-1];
                    byte_array[i-1] = byte_array[i-2];
                    byte_array[i-2] = tmp;
            }
    }
}

【讨论】:

  • 就其本身而言,正确使用,memcpy() 不会搞砸任何事情。您没有提供足够的信息让任何人首先知道您的问题是什么;您没有在此“答案”中提供足够的信息来演示您在何处以及如何使用此功能;你关于“完全撒谎”的说法不合时宜。您可能有调用未定义行为的代码。很难确定,因为您没有提供minimal reproducible example,但不稳定的行为是由不稳定的编码引起的。如果使用得当(例如,内存的源和目标区域可能不重叠),memcpy() 可以工作。
  • 否决这个答案,因为它具有误导性。建议memcpy 是字节序感知的并且以不同的顺序将字节写入源是完全不正确的。您可能遇到的是源数据本身使用与您期望的不同的字节序。这是数据格式问题,与memcpy无关。
  • 您不应对此反馈持负面态度。如果答案包含错误信息,那么它可能会伤害未来的读者,应该指出。
猜你喜欢
  • 1970-01-01
  • 2017-04-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-20
相关资源
最近更新 更多