Is it safe to pass std::string to C style APIs?

后端 未结 5 680
南笙
南笙 2021-01-04 23:16

It is well defined C++ to pass std::vector to C APIs that expect an output array like so because std::vector is contiguous:

std::vector myArray(a         


        
相关标签:
5条回答
  • 2021-01-04 23:40

    So, I know this has been answered already, but I saw your comment in Praetorian's answer:

    It's an OpenGL driver bug that results in the return value for the maximum length string being broken. See https://forums.geforce.com/default/topic/531732/glgetactiveattrib-invalid/. glGetActiveAttrib won't try to write to the pointer returned by the new[] call with the 0 size allocation, but the string isn't null terminated. Then, later in the code, the non-null terminated string is copied into a std::string for storage, which results in a read buffer overflow. Very confusing to me too, and just checking here to see if std::string would make things easier to follow.

    Uhm... forgive me but if this is your problem then all these solutions seem to be overly complicated. If the problem boils down to the fact that you get a 0 as the buffer size that you need (which means that you will end up with a string that's not NULL-terminated, since there's no space for the NULL terminator) then simply make sure a NULL terminator is always present:

    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);
    }
    

    This seems, to me, to be the simplest, sanest solution.

    0 讨论(0)
  • 2021-01-04 23:41

    Yes, but you'll need to pass them using the c_str method to guarantee null-termination.

    0 讨论(0)
  • No, it isn't, but generally because C strings are assumed to be zero-terminated, which your pointer-to-char isn't. (If you use string, you can use string::c_str() instead, that's 0-terminated.)

    Anyways, C++11 does require the elements of vector to be contiguous in memory.

    0 讨论(0)
  • 2021-01-05 00:00
    cStyleAPI(&myArray[0], arraySize);
    

    If your cStyleAPI receives a char* for input, that is what std::string::c_str() is for.

    If it receives a pre-allocated char* for output, then no. In that case, you should use a std::vector<char> or std::array<char>.

    0 讨论(0)
  • 2021-01-05 00:07

    If the C API function requires read-only access to the contents of the std::string then use the std::string::c_str() member function to pass the string. This is guaranteed to be a null terminated string.

    If you intend to use the std::string as an out parameter, C++03 doesn't guarantee that the stored string is contiguous in memory, but C++11 does. With the latter it is OK to modify the string via operator[] as long as you don't modify the terminating NULL character.

    0 讨论(0)
提交回复
热议问题