将 std::vector 传递给期望输出数组的 C API 是明确定义的 C++,因为 std::vector 是连续的:
std::vector<char> myArray(arraySize);
cStyleAPI(&myArray[0], arraySize);
以相同的方式将 std::string 传递给 C API 是否安全?标准 C++03 中是否有任何保证 std::string 是连续的并且在这种情况下与 std::vector 的工作方式相同?
如果 C API 函数要求对内容进行只读访问,std::string
则使用std::string::c_str()
成员函数来传递字符串。这保证是一个空终止的字符串。
如果您打算将std::string
用作out参数,C++03 不保证存储的字符串在内存中是连续的,但 C++11 可以。对于后者,operator[]
只要您不修改终止 NULL 字符,就可以修改字符串。
所以,我知道这已经得到了回答,但我在 Praetorian 的回答中看到了你的评论:
这是一个 OpenGL 驱动程序错误,导致最大长度字符串的返回值被破坏。请参阅 https://forums.geforce.com/default/topic/531732/glgetactiveattrib-invalid/。glGetActiveAttrib 不会尝试写入分配为 0 大小的 new[] 调用返回的指针,但字符串不是以空值结尾的。然后,稍后在代码中,非空终止的字符串被复制到 std::string 中进行存储,这会导致读取缓冲区溢出。我也很困惑,只是在这里查看 std::string 是否会使事情更容易理解。
嗯......请原谅我,但如果这是您的问题,那么所有这些解决方案似乎都过于复杂。如果问题归结为您获得 0 作为所需的缓冲区大小(这意味着您最终将得到一个不是 NULL 终止的字符串,因为 NULL 终止符没有空间),那么只需确保始终存在 NULL 终止符:
int arraySize;
/* assume arraySize is set to the length we need */
...
/* overallocate by 1 to add an explicit NULL terminator. Just in case. */
char *ptr = malloc(arraySize + 1);
if(ptr != NULL)
{
/* zero out the chunk of memory we got */
memset(ptr, 0, arraySize + 1);
/* call OpenGL function */
cStyleAPI(ptr, arraySize);
/* behold, even if arraySize is 0 because of OpenGL, ptr is still NULL-terminated */
assert(ptr[arraySize] == 0);
/* use it */
...
/* lose it */
free(ptr);
}
在我看来,这似乎是最简单、最明智的解决方案。
是的,但您需要使用c_str方法传递它们以保证空终止。
不,不是,但通常是因为假定 C 字符串以零结尾,而您的指针char
不是。(如果你使用string
,你可以使用string::c_str()
,那是 0 终止的。)
无论如何,C++11 确实要求 的元素vector
在内存中是连续的。
cStyleAPI(&myArray[0], arraySize);
如果您cStyleAPI
收到一个 char* 作为输入,那就是std::string::c_str()
它的用途。
如果它接收到一个预先分配的 char* 用于输出,则没有. 在这种情况下,您应该使用 astd::vector<char>
或std::array<char>
。