【问题标题】:dynamic struct array resizing when passed by reference通过引用传递时动态结构数组调整大小
【发布时间】:2016-08-22 12:42:18
【问题描述】:

以下第一轮之后,我不明白导致段错误的原因:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct query_param {
  char *key;
  char *val;
};

void extract_params(struct query_param **query_params, char *query_string,
                    size_t *query_params_len) {
  char *token, *key;

  while (query_string != NULL) {
    token = strsep(&query_string, "&");
    key = strsep(&token, "=");

    *query_params = realloc(*query_params, (*query_params_len + 1) *
                                               sizeof(struct query_param));


    query_params[*query_params_len]->key = malloc(strlen(key));
    query_params[*query_params_len]->val = malloc(strlen(token));

    memcpy(query_params[*query_params_len]->key, key, strlen(key));
    memcpy(query_params[*query_params_len]->val, token, strlen(token));

    (*query_params_len)++;
  }
}

int main(int argc, char **argv) {
  char *query_string = "foo=bar&baz=boo&zip=zap";
  size_t query_params_len = 0;
  struct query_param *query_params = NULL;
  extract_params(&query_params, query_string, &query_params_len);
  return 0;
}

将第一个键值对添加到结构中可以正常工作,但 第二个 malloc 会导致 麻烦

valgrind 信息:

==15319== Memcheck, a memory error detector
==15319== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==15319== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==15319== Command: ./a.out
==15319== 
==15319== 
==15319== Process terminating with default action of signal 11 (SIGSEGV)
==15319==  Bad permissions for mapped region at address 0x4008DF
==15319==    at 0x4EC1A0B: strsep (in /lib64/libc-2.23.so)
==15319==    by 0x4006C0: extract_params (foo.c:15)
==15319==    by 0x400848: main (foo.c:36)
==15319== 
==15319== HEAP SUMMARY:
==15319==     in use at exit: 0 bytes in 0 blocks
==15319==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==15319== 
==15319== All heap blocks were freed -- no leaks are possible
==15319== 
==15319== For counts of detected and suppressed errors, rerun with: -v
==15319== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

在运行 valgrind 之后,仍然无法解决这个问题。特别是堆摘要对我来说没有任何意义。 malloc 运行 3 次后怎么会分配 0 个字节?

干杯!

【问题讨论】:

  • 没有错误检查,没有minimal reproducible example,没有细节。见How to Ask!
  • 你可以自己调试它,用gcc -g(并且没有-O...标志)编译它,然后通过valgrind运行它。如果您不理解valgrind 的输出,请将其复制粘贴到问题中。
  • 感谢您迄今为止的意见。运行 valgrind 之后,我比以前更困惑:D
  • C 没有传递引用。它支持按值传递指针,但这不是一回事。
  • 考虑使用strdup() 代替strlen() + malloc() + memcpy()。前者更短、更清晰、等价。

标签: c arrays struct segmentation-fault dynamically-generated


【解决方案1】:
 query_params[*query_params_len]->blah

query_params 不是指针数组,也不是指向指针数组的第一个元素的指针。它是一个指向结构数组的第一个元素的指针。你想要这个

 (*query_params)[*query_params_len].blah

【讨论】:

    【解决方案2】:

    除了@n.m 中指出的问题之外,还有几个问题。答案(query_params“指向结构数组的第一个元素的指针。”)。

    线

    char *query_string = "foo=bar&baz=boo&zip=zap";
    

    query_string 声明为指向常量字符串字面量的指针,但稍后程序必须修改由于使用strsep() 而指向的内存。您应该将数组声明为 const 字符串的副本:

    char query_string[] = "foo=bar&baz=boo&zip=zap";
    

    另外,当您尝试复制令牌时,您应该遵循@John Bollinger 的建议并使用strdup() 或至少考虑'\0' 终止符。

    此外,您应该检查所有使用的库函数的返回值,并在最后释放分配的内存。

    【讨论】:

    • 非常感谢您的所有建议,我会很乐意考虑它们,但@n.m。仍然回答了我首先要问的问题。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多