将std :: string传递给C风格API是否安全?
很好地定义了C ++将std :: vector传递给期望输出数组的C API,因为std :: vector是连续的:
std::vector 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 []调用返回的指针,但该字符串不会以null结尾。 然后,在代码的后面,将非空终止字符串复制到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 *用于输出, 则不 。 在这种情况下,您应该使用std::vector
或std::array
。