kdgwill
kdgwill

Reputation: 2199

Does string change const char * when used as parameter

Curious as to the reason the constructor string (const char* s), sometimes alters the characters in const char *. I have a simple method that checks if a flag is set alters the string in some way searches a tree and return a value. It seems to work fine if I only use strings; however for some odd reason when I use const char * received from another function as a parameter into the function the const char * I recieve back is sometimes returned incomplete. Which is the cause for subtle errors I was unable to locate until recently. It seems to work if inside the method I create another string and append the string parameter to the new string but this seems like the wrong way to resolve this issue. I believe it could be a misunderstanding of the proper use of the constructor, Does anyone have any insight into this subtle issue?

As a simple example the terminal returns the below result, Note the symbol for an incomplete character did not copy correctly and instead is blank.

enter image description here

EDIT:
@T.C.
I in no way blame the string class T.C., I'm well aware that it is my error and I am attempting to understand the issue. It is most probably a misinterpretation on the use of the constructors in the std::string class. A bit of back story I am using C/C++ and java together for practice. I created a class that seemed to pass minimal testing in C++ and created a wrapper so that I can use it in C. When I pass a string as a parameter instead of const char * it works without a problem; however to the best of my understanding std::string should copy the characters though this I am not sure. I'm aware that a people will tell me to only use C++ and not to mix the two like in the answers to other questions when individuals mix the two but any direction would be appreciated.

I wanted to make the question short originally but posted before adding the code. Attached is a snippet of its use and a proper picture of the missing character symbol I could not find earlier.

LZW.c (C Class)

...
const char * tex = Trie_Int_longestPrefix(trie,input); //Find max prefix match tex
printf("%25s\t",tex);
//FOR SOME REASON TEX CHANGES AFTER THIS CALL
arr[size++] = Trie_Int_get(trie,tex);   //Add encoding 
printf("%25s\n",tex);
int t = strlen(tex);
...

ctrie.cpp (C-Wrapper Class)

...
//Return Value
int Trie_Int_get(Trie_Int * t,const char * key){return ((Trie<int> *)t)->get(key); }
...
//Find and return longest prefix of s in TST
const char * Trie_Int_longestPrefix(Trie_Int * t,const char * s){return  ((Trie<int> *)t)->longestPrefix(s).c_str();}
...

Trie.ii (C++ Class)

...
template<typename value>
value Trie<value>::get(std::string key,const bool & ignoreCase) const {
    if(key.empty()){throw std::invalid_argument("key must have length >= 1");}
    if(ignoreCase)__toLowerCase(key);
    TrieNode* x = get(root,key,0,ignoreCase);
    return x!=nullptr? x->val : defVal;
}
template<typename value>
std::string Trie<value>::longestPrefix(std::string key,const bool & ignoreCase) const{
...Kind of Long
}
...

Upvotes: 1

Views: 459

Answers (1)

aschepler
aschepler

Reputation: 72271

template<typename value>
std::string Trie<value>::longestPrefix(
    std::string key,const bool & ignoreCase) const;

//Find and return longest prefix of s in TST
const char * Trie_Int_longestPrefix(Trie_Int * t,const char * s)
{return  ((Trie<int> *)t)->longestPrefix(s).c_str();}

When a function returns a class type (directly, not a reference to type), calling that function creates a temporary class object which lives until the end of the full-expression that calls it. (The most common kind of "full-expression" is, like in this case, a statement.)

std::string::c_str() returns a C string pointer which is guaranteed to be valid until any non-const member of the string is called, including the destructor.

So that Trie_Int_longestPrefix function returns a pointer which is already invalid, and any use of it counts as undefined behavior.

In your test run, the memory the invalid pointer pointed at just happened to still contain some "expected" data the first time you print it. But by the second time, some other code has apparently reused that region of memory for something else.

Upvotes: 4

Related Questions