【问题标题】:Change the address of a variable passed as a void* function parameter更改作为 void* 函数参数传递的变量的地址
【发布时间】:2020-08-13 23:47:10
【问题描述】:

我有一个回调函数void string_cb(char* data, size_t size, void* str),它使用原型void callback_decl (char* data, size_t size, void* ret_val),其中最后一个参数是返回值。因为我的回调需要为带有malloc() 的字符串分配内存,所以我需要将void* str 的地址更改为分配的内存块。是否可以在不更改回调原型的情况下为 str 分配新地址?

【问题讨论】:

  • 你能提供更多细节吗?我假设您正在将此回调传递给某个库?如果是,是什么库以及其中的什么功能?
  • 这取决于该参数中实际传递的内容。如果调用者传入char **,则可以返回新分配的内存。您必须提供更多上下文。
  • 提供callback_decl和string_cb的代码,只提供你用于callback的部分,还清理内存问题?很难理解你正在尝试做什么。
  • 这显然行不通。正如我所说,如果调用者传入一个双指针,那么您可以执行以下操作:char **ret = ret_ptr; *ret = malloc();。所以调用者和回调函数之间需要有一个理解。否则是不可能的。

标签: c


【解决方案1】:

是的,您可以...但不能通过您的string_cb 声明。如果你希望能够返回一个新分配的数组的地址,你需要一个char **作为最后一个参数:

void slbin_handler_nstring(char* data, size_t data_size, void* ret_ptr) {
    char** ptr = (char **) ret_ptr;
    *ptr = malloc(data_size);
    if (!(*ptr)) return;
    memcpy(*ptr, data, data_size);
}

如果应该这样调用:

char *ptr;
slbin_handler_nstring(data, data_size, &ptr) ;

【讨论】:

  • @SergerBallesta,是的,我试图在回调方法之后调用 puts(ptr),得到了段错误。
  • @iTs.SL4y3R:我在您发表评论后对其进行了测试,它确实出现了段错误,但这是由我的代码中的一些拼写错误引起的。我已经修复了它们,现在它可以按预期工作了。
【解决方案2】:

使用签名void callback_decl (char* data, size_t size, void* ret_val),调用者全权负责提供分配的内存。调用的回调不能在内部分配内存。

如果你想一想,这实际上是更喜欢的,因为调用者更清楚应该在哪里分配内存(堆或堆栈),并且可以完全控制字符串的整个生命周期。

通常这种模式与ret_val 的特殊值结合使用,表示提供的缓冲区太小,以便调用者可以再次发出回调,但缓冲区更大。

【讨论】:

    猜你喜欢
    • 2019-09-23
    • 2021-11-19
    • 2012-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 2016-04-28
    • 2018-04-09
    • 2018-09-08
    相关资源
    最近更新 更多