在C ++中处理char数组

时间:2009-12-09 23:09:19

标签: c++

我有这个C风格的初始化代码:

const char * const vlc_args[] =
{
    "-I", "dummy",
    "--ignore-config",
    "--extraintf=logger",
    "--verbose=2"
    "--plugin-path=/usr/lib/vlc"
};
//tricky calculation of the char space used
libvlc_new(sizeof(vlc_args)/sizeof(vlc_args[0]), vlc_args, &exc);

由于我需要动态--plugin-path参数,我不能再使用静态数组了。所以我提出了一个C ++替代方案:

std::string pluginpath = "test";
libvlc_exception_t exc;

std::vector<std::string> args;
args.push_back("-I");
args.push_back("dummy");
args.push_back("--ignore-config");
args.push_back("--extraintf=logger");
args.push_back("--verbose=2");
args.push_back("--ipv4");
args.push_back("--plugin-path=" + pluginpath);

std::string combinedString;
for (size_t idx = 0; idx < args.size(); ++idx)
{
    combinedString.append(args[idx]);
    combinedString.resize(combinedString.size() + 1);
    combinedString[combinedString.size() - 1] = 0;
}
combinedString.resize(combinedString.size() + 1);
combinedString[combinedString.size() - 1] = 0;

size_t size = combinedString.size();
const char * data = combinedString.c_str();
libvlc_new(size, &data, &exc); // => error occurs here (not at end of scope or anything)

但是这会导致分段错误。所以我的代码中一定有错误,我似乎无法找到。有人能发现它吗?

解决!
感谢Joseph Grahn和Jason Orendorff。我对C风格数组内存布局的想法是错误的。我认为所有数据都被组织成一个大的顺序块。实际上,它是指向每个单独字符串的第一个字符的指针列表。

此代码有效:

std::vector<const char*> charArgs;
for (size_t idx = 0; idx < args.size(); ++idx)
{
    charArgs.push_back(&(args[idx][0]));
}
mVLCInstance = libvlc_new(charArgs.size(),
                          &charArgs[0],
                          &mVLCException);

7 个答案:

答案 0 :(得分:4)

您将所有参数附加到单个字符串中,然后将指向const char *字符串的指针传递给libvlc_new,就好像它是一个char *数组。

(我不确定这是不是问题,但似乎有点奇怪。)

答案 1 :(得分:4)

我认为Josef Grahn是对的:API需要一个实际的指针数组。

如果您不需要以编程方式添加参数,则可以返回使用数组:

std::string pluginpath = "test";
std::string pluginpath_arg = "--plugin-path=" + pluginpath;
const char *args[] = {
    "-I", dummy, "--ignore-config", ..., pluginpath_arg.c_str()
    };

libvlc_exception_t exc;
libvlc_new(sizeof(args) / sizeof(args[0]), args, &exc);

编辑:在这里使用c_str()可能 也有问题。如果VLC保留指针并稍后再次使用它,则为真;我不知道文档是否属于这种情况。

答案 2 :(得分:1)

关于分段违规

没有解决方案,因为可能会有更多问题

您只发送1个字符串。(不确定libvlc_new是否允许)所以第一个参数应设置为1,即size = 1。我相信这将解决分割问题。但我怀疑libvlc_new只能用一行多个参数调用。

在原始代码sizeof(vlc_args)/sizeof(vlc_args[0])中,参数的数量将作为向量中的条目。在你的例子中等于6。

您的代码

size_t size = combinedString.size(); // a long string, size >> 1
const char * data = combinedString.c_str(); // data is a pointer to the string

libvlc_new(size, &data, &exc);

// size should be 1 because data is like an array with only one string. 
// &data is the adress to the "array" so to speak. If size > 1 the function
// will try to read pass the only string available in this "array"

我认为Jason Orendorff有一个很好的解决方案来解决这个问题......

答案 3 :(得分:1)

库调用需要一个指向const char*数组的指针(这是几个指针),但是你传递一个指针。将更多字符附加到该字符串的末尾并不重要。

要动态构建所需指针的数组,您可以使用另一个vector

// store c_str() pointers in vector
std::vector<const char*> combined;
for (size_t idx = 0; idx < args.size(); ++idx) {
    combined.push_back(args[idx].c_str());
}

// pass pointer to begin of array (it is guaranteed that the contents of a vector
// are stored in a continuous memory area)
libvlc_new(combined.size(), &(combined[0]), &exc);

Jason Orendorff的注释在这里也是有效的:如果libvlc_new将传递的指针存储在内部供以后使用,这将不起作用。

答案 4 :(得分:1)

你试过了吗?

libvlc_new(size, data, &exc);

而不是

libvlc_new(size, &data, &exc);

似乎你使用空字节使字符串像一个字符数组一样,但是你将指针传递给char *“array”而不仅仅是数组。

答案 5 :(得分:0)

我有同样的问题;我想动态生成参数,但是以安全的c ++方式。

我遇到的解决方案是使用unique_ptr&lt; []&gt; C ++ 11新手。例如:

unique_ptr<char *[]> vlc_argv;
int vlc_argc;
...
auto vlc(libvlc_new(vlc_argc, vlc_argv.get()));

这给了我一个很好的RAII对象来保存我的参数,因为我仍然可以传递给libvlc_new()。由于参数是argv中的原始指针,由操作系统管理,我们可以直接在vlc_argv中使用它们。

作为另一个例子,假设我处理argv中的前几个args(在&#34; ...&#34;上面的某个区域),并想要传递来自{{1}的所有内容}到libvlc_new():

next_arg

答案 6 :(得分:-1)

问题是由于使用c_str()并存储指针。

请参阅stringstream, string, and char* conversion confusion

编辑忘了我说的......已经晚了...看到评论:)