将char *作为参数传递给动态调用的函数会产生运行时错误

时间:2013-08-05 17:34:49

标签: c gcc runtime-error

我有一个名为testdynamic的函数,它使用dlopen和dlsym动态调用。现在,我创建了一个结构:

typedef struct BigStruct{
    char el[2000];
}BigStruct;

用于存储函数的参数。然后,我将空间分配给名为:

的变量
void *cur = (void*)malloc(totalSize);

其中,totalSize是参数的大小。我事先得到了这些信息。

之后我将所有参数复制到cur。

然后,我将它投射到BigStruct:

BigStruct *bg;
bg = (BigStruct*)cur;

然后像这样运行:

void* ch = (void*)testdynamic(*bg);

现在,在我打印参数的函数testdynamic中,我为所有数据类型获取了正确的值,例如char**int*,int等。

唯一不起作用的数据类型是char *。甚至在使用*bg调用函数之前,即使对于char *,bg-> el的内容也是正确的。但是,在调用之后,会发生错误。

可能是什么问题?

以下是testdynamic的代码

char* testdynamic(char* x, char* y){
    printf("%s %s\n", x, y);
    return "hello";
}

我想从我的代码中将参数传递给函数testdynamic 这个testdynamic可以是任何可以接受任何类型参数的函数 我在运行时获取有关该函数的信息。由于char *的大小为1,我将所有内容都转换为char *,然后将其传递给函数 此时,如果我在testdynamic中打印char*类型的任何内容,则会出现运行时错误。

6 个答案:

答案 0 :(得分:0)

您假设BigStruct看起来与2000个字符的数组完全相同。这取决于编译器,不太可能是真的。我想你真的想把cur指向的数据复制到el数组中,而不是把它全部写在BigStruct本身上,这将有一些你不知道的内部存储格式。

答案 1 :(得分:0)

总结一下我所理解的你在做什么:

  • 将cur作为char *处理并将参数列表复制到其中
  • 将cur作为BigStruct *进行投射,然后将其传递给testdynamic函数。

在我看来,这似乎是一种奇怪的方式,并且没有查看testdynamic函数,我猜这是导致错误的原因。我建议您更改BigStruct的定义:

typedef struct {
    char * el;
} BigStruct;

这样,您可以为char数组设置malloc空间,将参数列表复制到它,然后将BigStruct中的char *设置为指向相关的内存块,如下所示:

char * cur = malloc(totalSize);
// Copy parameters over into cur
BigStruct * bg = malloc(sizeof(BigStruct));
bg->el = cur;

然后再次调用testdynamic函数。试试这个,你还会遇到运行时错误吗?

编辑:看过testdynamic函数的内容后,我可以看到它的几个问题

char* testdynamic(char* x, char* y){
    printf("%s %s\n", x, y);
    return "hello";
}
  1. 该函数接受2个字符*但您似乎只在代码中传递1。如果你只为x?
  2. 给它一个参数,它应该打印什么?
  3. 假设您现在正在传递x和y的参数。你确定这两个字符串都是以null结尾的吗? printf通过打印字符来工作,直到找到'\ 0'字符。
  4. 你不能只是从这样的函数中返回一个字符串文字。该字符串文字属于该函数,一旦该函数返回,您无法保证持有该字符串的内存仍然可以安全地再次访问。如果要返回类似的字符串,首先应该为字符串设置malloc()空格,并将地址返回到已分配的内存块。

答案 2 :(得分:0)

如果totalSize > sizeof(BigStruct),您有问题,因为您没有将数据的完整副本传递给testdynamic(),可能会弄乱副本,因此未定义的行为

如果totalSize < sizeof(BigStruct),当您将* bg传递给testdynamic()时,您正在读取您不拥有的内存空间时遇到问题 - 因此未定义的行为

只需使用

,您就会更安全
bg = malloc(*bg);

此处还有其他可疑的程序问题,但需要更完整的发布。

答案 3 :(得分:0)

仅当尺寸为sizeof(BigStruct)

时才有效

你不能假设一个结构是其内容的大小,因为编译器可能会做出对齐的假设等。

如果你只想要 20,000个字符,那么就像其他人建议的那样在BigStruct内进行malloc。

答案 4 :(得分:0)

再读一遍......

您为一个需要2个参数的函数传入一个参数。

您是否在编译期间将-Wall用于警告视为错误?第二个参数未传入,即参数y为null。访问null会导致问题。

答案 5 :(得分:0)

要提供准确,无意见的评论,需要提供代码副本。因此,我已经收集了您的意见并生成了以下代码。这可能不是你想要做的。但是,应该以步骤或增量来处理编程问题。

也就是说,让一些简单的工作,然后使它更复杂,但仍然有效,并朝着你的最终版本努力。这是我们中的许多人的工作。没有人能够第一次正确地编写复杂的程序,特别是如果对语言不熟悉的话!

#include <stdio.h>
#include <stdlib.h>
char *testdynamic(char *x, char* y){

        printf("%s %s\n", x, y);
        return "hello";
    }

main()
{
    typedef struct BigStruct{
        char el[2000];
    } BigStruct;

    char      *ret_char_ptr;

    BigStruct *bg;

    char x[] = "abcd";
    char y[] = "23456";

    bg = malloc(sizeof(BigStruct));

    // invoke the testdynamic function
    ret_char_ptr = testdynamic(x, y);


    printf("%s\n", ret_char_ptr);

}

我在Eclipse / Microsoft C编译器上运行此代码并得到以下输出:

abcd 23456
hello

请注意。 BigStruct尚未在此代码中使用。不确定你的意图是什么,但C确实提供了一种方法来传递长度不同的参数列表和来自同一函数的几个不同调用的数据。