【问题标题】:Arrays in c shared libraryc共享库中的数组
【发布时间】:2016-06-09 12:47:22
【问题描述】:

我想基本上在动态库的方法中处理结构数组,但是当我传递数组并打印它时(以与我的主程序完全相同的方式)它具有不同的值。

考虑这样的结构:

struct color {
    uint8_t b;
    uint8_t g;
    uint8_t r;
    uint8_t a;
}

打印出来的代码是这样的:

printf("pos: %p\n", array);
for (i = 0; i < size; i++) {
        printf("bgra: %08x\n", ((uint32_t *) array)[i]);
}

现在,我在测试程序中所做的是:

printf("Table:\n");
print(table, size);

输出看起来像这样(例外):

pos: 0x7fff5b359530
bgra: 00000000
bgra: ff0000ff
bgra: ff00ffff

但是当我在库中的一个函数中执行相同的代码时,这就是我得到的:

pos: 0x7fff5b359530
bgra: 00000008
bgra: 00000030
bgra: 5b3598e0

现在我想知道我做错了什么,因为我在我的代码中看不到错误。此外,这些值必须以某种方式相关,因为输出总是相同的(当然地址除外)。

header.h

#include <stdint.h>

#ifndef __HEADER_H_
#define __HEADER_H_

struct bmpt_color_bgra {
    uint8_t b;
    uint8_t g;
    uint8_t r;
    uint8_t a;
};

void print(struct bmpt_color_bgra *table, uint8_t size);
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size);
#endif

图书馆.c

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

#define EXPORT __attribute__((visibility("default")))

__attribute__((constructor))
static void initializer(void) {
    printf("[%s] initializer()\n", __FILE__);
}

__attribute__((destructor))
static void finalizer(void) {
    printf("[%s] finalizer()\n", __FILE__);
}

EXPORT
void print(struct bmpt_color_bgra *table, uint8_t size) {
    uint8_t i;

    printf("pos: %p\n", table);
    for (i = 0; i < size; i++) {
        printf("bgra: %08x\n", ((uint32_t *) table)[i]);
    }
}

EXPORT
uint8_t *gen(struct bmpt_color_bgra *table, uint8_t size) {
    printf("table in func:\n");
    print(table, size);
}

test.c

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

int main(int argc, char **argv) {
    struct bmpt_color_bgra arr[3];
    struct bmpt_color_bgra c;

    c.b = 0x0;
    c.g = 0x0;
    c.r = 0x0;
    c.a = 0x0;
    arr[0] = c;

    c.b = 0xff;
    c.a = 0xff;
    arr[1] = c;

    c.r = 0xff;
    arr[2] = c;

    //the first result (the correct one)
    print(arr, 3);

    //the second result
    gen(arr, 3);
}

【问题讨论】:

  • 您是否注意到数据bgra: 5b3598e0 与地址pos: 0x7fff5b359530 有一些相同的数字?
  • 将相关代码复制到一个简单的单模块源文件中(忽略构造函数等),它可以正常工作,即第二个函数从第一个函数给出与第一个函数相同的输出被直接调用。
  • test.c 包含一个标头 bmptool.h,它似乎是声明 struct bmpt_color_bgra 类型和函数 gen()print() 的唯一可能来源。您没有提供该标头,library.c 使用不同的标头。这打开了声明不匹配的可能性。
  • @WeatherVane 更快,但看到它on ideone.com

标签: c arrays shared-libraries


【解决方案1】:

这可能归结为结构内成员的内存对齐,以及结构本身的大小在您的程序和动态/共享库之间不同。您没有提及您正在使用哪个编译器,但是为您的程序和共享库使用不同的编译器或编译器选项可能会导致这种效果。

您可以通过准确指定结构的成员应如何对齐来保持模块之间的二进制兼容性。例如,在 GCC 中,您可以通过使用属性来强制结构在内存中的表示方式。

有关 GCC 对齐说明,请参阅 https://gcc.gnu.org/onlinedocs/gcc-3.3/gcc/Type-Attributes.html

struct bmpt_color_bgra {
    uint8_t b;
    uint8_t g;
    uint8_t r;
    uint8_t a;
} __attribute__ ((packed));

也可以查看Byte Alignment for integer (or other) types in a uint8_t array 了解类似问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-28
    • 2017-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 2012-04-24
    相关资源
    最近更新 更多