【问题标题】:modified after being freed - returning a C array of `c_str` (const char*) within a struct被释放后修改 - 在结构中返回一个 C 数组 `c_str` (const char*)
【发布时间】:2021-07-27 09:49:42
【问题描述】:

如何从std::vector(在struct 中)获取一个c_str 数组供C 用户使用?

尝试:

#include <vector>
#include <algorithm>

typedef struct { size_t size; const char** arr; } CStrStrArray;

CStrStrArray f() {
    const std::vector<const char*> cStrVec {"foo", "bar"}; 
    /* pretend ^this is huge^ with size + contents not known ahead of time */

    const char **cStrArr = (const char**)malloc(cStrVec.size());
    std::copy(cStrVec.begin(), cStrVec.end(), cStrArr);
    /* also tried `cStrVec.data();` */
    return {cStrVec.size(), cStrArr};
}

/* pretend this is 'main.c' and the above is in an `extern C` elsewhere */
int main(void) {
    CStrStrArray c_str_arr = f();
    free(c_str_arr.arr);
    c_str_arr.size = 0;
    return EXIT_SUCCESS;
}

错误:

malloc: Incorrect checksum for freed object 0x7ff996d3d790: probably modified after being freed.
Corrupt value: 0x7ff996d08280
executable(17572,0x11c6d5e00) malloc: *** set a breakpoint in malloc_error_break to debug

【问题讨论】:

  • 嗨@AT - 你不是在复制内容,你是在复制指针 - 当方法完成时内容范围完成..尝试将“foo”作为方法之外的静态常量和看看有什么不同。
  • @MrR 这是指向字符串文字的指针,所以可以复制指针

标签: c++ arrays c malloc c-strings


【解决方案1】:

您的代码没有分配足够的内存。您只为 2 个字节分配内存,但您需要为 2 个字符指针分配内存。所以改变它:

malloc(cStrVec.size()) --> malloc(cStrVec.size() * sizeof *cStrArr)
                                  \------------/   \--------------/
                                   Number of        size of a single
                                   char pointers    char pointer
                                   in the vector

                                  \-------------------------------/
                                          Memory needed

【讨论】:

  • 应该是cStrVec.size() * sizeof(char *),你分配的太匹配了
  • @Slava cStrVec.size() * sizeof(char *)cStrVec.size() * sizeof *cStrArr 相同。然而,最后一个是“更好的 C 编码风格”——有几个原因。同样:int d; assert(sizeof d == sizeof(int)); 很好
  • 让我意识到这一点的是,我可以在变量“制造”之前引用它,就像这样没有意义 char c = c + 5;但我猜sizeof 很特别?
  • 是的,你是对的,我认为cStrArr 是指向CStrStrArray 的指针
  • @AT 是的,sizeof 很特别。
【解决方案2】:

如果您需要将std::vector&lt;std::string&gt;&gt; 转换为CStrStrArray,则不需要中间步骤并创建额外的std::vector&lt;const char *&gt;

CStrStrArray f( const std::vector<std::string> &v ) {
    CStrStrArray r{ v.size(), 
         reinterpret_cast<const char **>( malloc( sizeof( char * ) * v.size() ) };
    for( size_t i = 0; i < v.size(); ++i )
        r.arr[i] = strdup( v[i].c_str() );
    return r;
}

【讨论】:

  • 是的,但我做不到static,因为我不知道它的大小……
  • 即使它是静态的,你也不必提前知道它的大小,你的意思是它会随着调用而改变吗?
  • @Slava - 是的,它在远程服务器上调用 HTTPS API,然后我将响应过滤为字符串向量,然后将该字符串向量转换为 c_str 数组
  • @AT 字符串向量作为?
  • 好吧,我有一个很大的结构向量,然后我将其转换为 std::string(或 const char*)的向量,然后将其转换为 c_str 数组(const char**)。
猜你喜欢
  • 2021-11-17
  • 2021-11-23
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 2013-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多