9

将 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 的工作方式相同?

4

5 回答 5

11

如果 C API 函数要求对内容进行只读访问,std::string则使用std::string::c_str()成员函数来传递字符串。这保证是一个空终止的字符串。

如果您打算将std::string用作out参数,C++03 不保证存储的字符串在内存中是连续的,但 C++11 可以。对于后者,operator[]只要您不修改终止 NULL 字符,就可以修改字符串。

于 2013-05-07T17:46:56.533 回答
6

所以,我知道这已经得到了回答,但我在 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);
}

在我看来,这似乎是最简单、最明智的解决方案。

于 2013-05-07T18:46:29.327 回答
1

是的,但您需要使用c_str方法传递它们以保证空终止。

于 2013-05-07T18:05:09.860 回答
0

不,不是,但通常是因为假定 C 字符串以零结尾,而您的指针char不是。(如果你使用string,你可以使用string::c_str(),那是 0 终止的。)

无论如何,C++11 确实要求 的元素vector在内存中是连续的。

于 2013-05-07T17:47:51.427 回答
0
cStyleAPI(&myArray[0], arraySize);

如果您cStyleAPI收到一个 char* 作为输入,那就是std::string::c_str()它的用途。

如果它接收到一个预先分配的 char* 用于输出,则没有. 在这种情况下,您应该使用 astd::vector<char>std::array<char>

于 2013-05-07T18:07:33.253 回答