c - 函数调用的时候,参数发生漂移是怎么回事?(第一个参数丢了,第二个参数变成了第一个参数的值)

查看:168
本文介绍了c - 函数调用的时候,参数发生漂移是怎么回事?(第一个参数丢了,第二个参数变成了第一个参数的值)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

我在 StackOverflow 上面的同问题:C function parameter mysteriously drifted?

以下是中文问题:


本人目前在做一个基于 Samba 3.6.25 的小工具,参照 smbclient 程序的函数调用方式,自己设计一个 SMB/CIFS 发现/目录列表工具。

有一个被调用的库函数,在某个静态库 .a 中。我调用的时候,发现参数神奇地漂移了,第一个参数莫名丢失,而后面的参数则补到了前面去……

我要调用的函数是 cli_pipe.c 里的 cli_rpc_pipe_open_noauth_transport(),调用方法是这样的:

NTSTATUS cli_rpc_pipe_open_noauth_transport(struct cli_state *cli,
                        enum dcerpc_transport_t transport,
                        const struct ndr_syntax_id *interface,
                        struct rpc_pipe_client **presult)
{

    struct rpc_pipe_client *result;
    struct pipe_auth_data *auth;
    NTSTATUS status;

    status = cli_rpc_pipe_open(cli, transport, interface, &result);
    _DEBUG("cli = %p", cli);
    _DEBUG("transport = %p", transport);
    _DEBUG("interface = %p", interface);
    _DEBUG("presult = %p", presult);
    _DEBUG("cli->desthost = %p", cli->desthost);
    _DEBUG("cli->desthost = \"%s\"", cli->desthost);
    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }
    ......

我是这么调用的:

NTSTATUS _pipe_open_noauth(struct cli_state *cli, const struct ndr_syntax_id *intf, struct rpc_pipe_client **presult)
{
    SMBD_DEBUG("cli = %p", cli);
    SMBD_DEBUG("intf = %p", intf);
    SMBD_DEBUG("presult = %p", presult);
    SMBD_DEBUG("cli->desthost = %p", cli->desthost);
    SMBD_DEBUG("cli->desthost = \"%s\"", cli->desthost);
    return cli_rpc_pipe_open_noauth_transport(cli, 1, intf, presult);
}

但是我得到的输出信息是这样的:

--- SMBD (util_smbclient.c, 117): cli = 0xdb2b20
--- SMBD (util_smbclient.c, 118): intf = 0xda31c0
--- SMBD (util_smbclient.c, 119): presult = 0x7fe9fdc8
--- SMBD (util_smbclient.c, 120): cli->desthost = 0xdd3a50
--- SMBD (util_smbclient.c, 121): cli->desthost = "192.168.1.125"
=== Samba (rpc_client/cli_pipe.c, 2873): cli = 0x1
=== Samba (rpc_client/cli_pipe.c, 2874): transport = 0xda31c0
=== Samba (rpc_client/cli_pipe.c, 2875): interface = 0x7fe9fdc8
=== Samba (rpc_client/cli_pipe.c, 2876): presult = 0xdaf3d0

很显然,我的第一个参数a消失了,而第二个参数b在被调用的函数里顶替了a的位置;后面的参数也按顺序顶替上去了……

请问各位,这是怎么回事啊?是不是链接器哪里出问题了吗?


附加信息1:

我使用的工具链是:mipsel-linux-uclibc-cc/ld/ar,并且我尝试了对生成目标做 objdump:

自己的程序:

可以发现参数是按顺序 a0, a1, a2, a3 传入的:

  409bf0:   8fdc0010    lw  gp,16(s8)
  409bf4:   8fc40020    lw  a0,32(s8)
  409bf8:   24050001    li  a1,1            # store 1 in a1
  409bfc:   8fc60024    lw  a2,36(s8)
  409c00:   8fc70028    lw  a3,40(s8)
  409c04:   8f99ab74    lw  t9,-21644(gp)
  409c08:   00000000    nop
  409c0c:   0320f809    jalr    t9
  409c10:   00000000    nop
  409c14:   8fdc0010    lw  gp,16(s8)
  409c18:   03c0e821    move    sp,s8
  409c1c:   8fbf001c    lw  ra,28(sp)
  409c20:   8fbe0018    lw  s8,24(sp)
  409c24:   03e00008    jr  ra
  409c28:   27bd0020    addiu   sp,sp,32

smbclient:

这是 Samba 自己的实现了。很奇怪,似乎a0 并没有用来传递参数

<cli_rpc_pipe_open_noauth>:
              …
  487840:   8fdc0018    lw  gp,24(s8)
  487844:   8fc2003c    lw  v0,60(s8)
  487848:   00000000    nop
  48784c:   afa20010    sw  v0,16(sp)
  487850:   02002021    move    a0,s0
  487854:   8fc50034    lw  a1,52(s8)
  487858:   24060001    li  a2,1    # Here, the number 1 was stored in a2 instead of a1!!!
  48785c:   8fc70038    lw  a3,56(s8)
  487860:   8f99aed0    lw  t9,-20784(gp)
  487864:   00000000    nop
  487868:   0320f809    jalr    t9  # cli_rpc_pipe_open_noauth_transport()
  48786c:   00000000    nop
  487870:   8fdc0018    lw  gp,24(s8)
  487874:   02001021    move    v0,s0
  487878:   03c0e821    move    sp,s8
  48787c:   8fbf0028    lw  ra,40(sp)
  487880:   8fbe0024    lw  s8,36(sp)
  487884:   8fb00020    lw  s0,32(sp)
  487888:   03e00008    jr  ra
  48788c:   27bd0030    addiu   sp,sp,48

被调用的函数本身:

似乎和前面 smbclient 的调用方式一样,a0 保存的并不是参数:

0053bdac <cli_rpc_pipe_open_noauth_transport>:
  53bdac:   3c1c0087    lui gp,0x87
  53bdb0:   279c3624    addiu   gp,gp,13860
  53bdb4:   0399e021    addu    gp,gp,t9
  53bdb8:   27bdffc0    addiu   sp,sp,-64
  53bdbc:   afbf0038    sw  ra,56(sp)
  53bdc0:   afbe0034    sw  s8,52(sp)
  53bdc4:   afb00030    sw  s0,48(sp)
  53bdc8:   03a0f021    move    s8,sp
  53bdcc:   afbc0018    sw  gp,24(sp)
  53bdd0:   afc40040    sw  a0,64(s8)
  53bdd4:   afc50044    sw  a1,68(s8)
  53bdd8:   afc60048    sw  a2,72(s8)
  53bddc:   afc7004c    sw  a3,76(s8)
  53bde0:   8f848080    lw  a0,-32640(gp)
  53bde4:   00000000    nop
  53bde8:   24844da0    addiu   a0,a0,19872
  53bdec:   24050b39    li  a1,2873
  53bdf0:   8fc60044    lw  a2,68(s8)
  53bdf4:   8f99cab0    lw  t9,-13648(gp)
  53bdf8:   00000000    nop
  53bdfc:   0320f809    jalr    t9              <—— invoke cli_rpc_pipe_open()
  53be00:   00000000    nop

注:我在 StackOverflow 上的同一个提问:C function parameter mysteriously drifted?

解决方案

自行解决了——准确地说原来遇到的问题的原因还是不明,我并没有针对性地解决,而是换了一种方式来完成我的目标。

之前出问题的情况是:先把 Samba 编译了,然后再自行编译一个应用程序去链接 Samba 的 .o 文件。
现在我改成:把自己的应用程序代码拷到 Samba 的工程里面,让 Samba 的 Makefile 直接编译我的应用程序,这样编译出来的程序就可以正常执行了。

这篇关于c - 函数调用的时候,参数发生漂移是怎么回事?(第一个参数丢了,第二个参数变成了第一个参数的值)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆