C++ 在C+中处理字符数组+;

C++ 在C+中处理字符数组+;,c++,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(

我有一段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)
std::string pluginpath=“test”;
libvlc_exception_t exc;
std::向量args;
参数。推回(“-I”);
args.推回(“虚拟”);
args.push_back(“--ignore config”);
args.push_back(“--extrantf=logger”);
args.push_back(“--verbose=2”);
args.push_back(“--ipv4”);
args.push_back(“--plugin path=“+pluginpath”);
std::string组合字符串;
对于(size_t idx=0;idx此处发生错误(不在范围或任何内容的末尾)
但这会导致分割错误。所以我的代码中一定有错误,我似乎找不到。。有人能发现吗

解决了
感谢约瑟夫·格雷恩和杰森·奥伦多夫。我对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);
std::矢量字符;
对于(size_t idx=0;idx
问题是由于使用了c_str()并存储了指针


忘记我说的话。。。已经很晚了。。。请参阅注释:)

如果要将所有参数附加到单个字符串中,则将指向const char*字符串的指针传递给libvlc_new,就像它是char*数组一样


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

我认为约瑟夫·格雷恩是对的: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保留指针并在以后再次使用它,则这是正确的;我无法从文档中判断情况是否如此。

关于分割冲突 没有解决方案,因为可能会有更多问题

您只发送了1个字符串。(不确定
libvlc_new
是否允许该参数),因此第一个参数应设置为1,即
size=1
。我相信这将解决细分问题。但我怀疑
libvlc\u 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有一个很好的解决方案来解决这一切…

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

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

// 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);
//将c_str()指针存储在向量中
std::向量组合;
对于(size_t idx=0;idx
此处的备注也有效:如果
libvlc\u new
在内部存储传递的指针以供以后使用,则此操作将无效。

您是否尝试过:

libvlc_new(size, data, &exc);
而不是

libvlc_new(size, &data, &exc);

似乎您使用空字节使字符串的行为类似于字符数组,但随后您传递了指向char*“array”的指针,而不仅仅是数组;我想动态地生成参数,但用一种安全的C++方式。< /P> 我的解决方案是使用UNQuYJPTR新到C++ 11。例如:

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

在调试器中运行它,并告诉我们它在哪一行进行故障检测。它在目标代码中进行故障检测,而不使用调试符号。在我的代码中,这发生在libvlc_new调用期间。为什么要将&数据传递给libvlc_new函数?在原始代码中,第二个参数的类型为const char*,现在传递的是const char**。从第二个参数中删除“&”。它与char*数组有何不同?这两种情况下的内存布局是否相同?否,“const char*const vlc_args[]”是指针数组。单个字符串中没有任何指针。我不知道libvlc需要什么,但对于main()中的程序参数,您应该能够执行以下操作:argv[3]获取指向第四个参数的常量char*。在您的例子中,这将在堆栈上的某个位置(变量数据驻留的上方)生成一个通配符指针。这种情况不同于错误地使用stringstream(ss.str().c_str()),因为在我的string对象中是一个l值。指针由
combinedString.c_str()返回
在修改或销毁组合字符串之前是有效的。我记得读到过谷歌代码指南规定使用sizeof(args[0])而不是sizeof(char),因此在数据类型发生变化时(例如wchar)不需要更改(或忘记)。谢谢Jason,你的回答让我有了正确的想法。epatel:好眼力,我的意思是
sizeof(args[0])
vlc_argv = std::unique_ptr<char *[]>(new char *[2 + argc - next_arg]);
vlc_argv[0] = argv[0];
for (vlc_argc=1; vlc_argc <= argc - next_arg; vlc_argc++) {
    vlc_argv[vlc_argc] = argv[next_arg + vlc_argc - 1];
}
vlc_argv[vlc_argc] = 0;