How to get pointer to string's data in a vector of strings? [duplicate]

How to get pointer to string's data in a vector of strings? [duplicate]



This question already has an answer here:



I have a vector of strings as my primary data container. However, in order to interoperate with a C library, I need to be able to view these strings as character data pointers (i.e. const char*). This sounds simple enough, so I wrote a helper class like this:


const char*


class strvecAccessor
const std::vector<std::string>& names;

public:
strvecAccessor(const std::vector<std::string>& a) : names(a)
size_t size() const
return names.size();

const char* item(size_t i)
auto name = names[i];
return name.data();

;



This accessor class is short-lived. It serves as a wrapper around an existing vector of strings, which is guaranteed to not be modified or go out-of-scope during the lifespan of this class. An example of how this class can be used is the following:


void test(strvecAccessor& arr)
for (size_t i = 0; i < arr.size(); ++i)
printf("%sn", arr.item(i));




But there is a bug in this code, which manifests itself only when I compile it in --coverage -O0 mode, and only on Unix machine (I compile with CLang 6.0.0 in C++11 compatibility mode). The bug is that the printed strings contain garbage.


--coverage -O0



I believe what happens is that the name variable in item() method is not a reference, but a copy of the i-th element of the array. It goes out-of-scope at the end of the item() function, at which point the pointer that was returned becomes dangling. Most of the time it is not noticeable since the pointer is used immediately, but in coverage mode it gets filled up with other data right after the call.


name


item()


i


item()



The problem disappears if I replace auto name = names[i]; with const std::string& name = names[i];. But I don't really understand why, and whether this actually solves the problem or just buries it deeper. So my question is: why the copy is being made in the original code; and how to protect myself against these kinds of errors in the future?


auto name = names[i];


const std::string& name = names[i];



This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.





auto name = names[i]; creates a new local std::string and return name.data(); returns a pointer into a local variable ie a dangling pointer.
– Richard Critten
Aug 30 at 18:13



auto name = names[i];


std::string


return name.data();





I'm not sure I understand the question - given that the penultimate paragraph points out the problem very well. Do you have a specific source of confusion?
– Barry
Aug 30 at 18:16





@JesperJuhl does it not mean universal reference in this context?
– Slava
Aug 30 at 18:24





@Slava Yes. Except the term is forwarding reference please.
– Barry
Aug 30 at 18:25





@Slava Yes
– Barry
Aug 30 at 18:26




1 Answer
1


const char* item(size_t i)
auto name = names[i];
return name.data();



Here, name is a local variable to the function item(), and you're returning an address to data that is owned by that local variable. When it goes out of scope (the item() function completes) name will be destroyed.


name


item()


item()


name



Since you're guaranteeing the lifetime of the underlying vector, try this instead:


const char* item(size_t i)
return names[i].data();



This will be "safe", because vector::operator returns a reference to the stored data, and you don't make an extraneous copy into your name variable like in your original.


vector::operator


name





In meaning of C++ terminology name is not temporary, please do not confuse with your answer.
– Slava
Aug 30 at 18:18


name





name is an lvalue, not a temporary/rvalue.
– Jesper Juhl
Aug 30 at 18:25



name





Updated, thanks.
– Chad
Aug 30 at 19:53

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)