2011-10-31 12 views
1

私のプロジェクトでは同じ状況に遭遇しました。
次のコードも同様に再現されました。
visual studio 2008 sp1 std :: string :: c_str()エラー

#include <iostream> 
#include <vector> 
using namespace std; 


class METHOD 
{ 
public: 
vector<METHOD*> m_arg; 
string name; 
string getName() 
{ 
    return name; 
} 
METHOD() 
{ 

} 
METHOD(string n) 
{ 
    name = n; 
} 
}; 

class PF : public METHOD 
{ 
public: 
PF(){}; 
}; 

void main() 
{ 


PF p; 
p.m_arg.push_back(new METHOD(string("a"))); 
p.m_arg.push_back(new METHOD(string("b"))); 
p.m_arg.push_back(new METHOD(string("c"))); 

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i) 
{ 
    const char* ccs = p.m_arg[i]->getName().c_str(); //PROBLEM POINT 

    size_t ss = strlen(ccs); 
} 

} 

問題がある//問題のPOINT
c_strのリターンアドレス()のconstのchar * CCSに割り当てることはできません。デバッガで
c_str()のリターンのCSS割り当てられたメモリアドレスが、CSSの値は 『』、それは同様に動作 『

』が、次のコードのように働いています期待される。このコードの後

string str("ok"); 
const char* ckk = str.c_str(); 

CKKstr.c_str() returnning ADDRES、及びCKK後デバッガでの値は

同じ問題が発生している "OK" でありますstd :: wstring、wchar_t、unicodeにあります。

この問題はなぜ発生しましたか?
誰が知っていますか?助けてください〜

追加: 私は問題を同じように解決します。この解決法もOKです。

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i) 
{ 
    string& strr = p.m_arg[i]->getName(); 
    const char* ccs = strr.c_str(); 
    size_t ss = strlen(ccs); 
} 

ので、私は、ループが閉じ}までのgetName()の戻り値は、ライブだと思います。
しかし興味深いことに、次は

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i) 
{ 
    string* strr = &p.m_arg[i]->getName(); 
    const char* ccs = strr->c_str(); 
    size_t ss = strlen(ccs); 
} 

CSSは「ダングリング」ともSTRRされ動作しないですが、「」私はボーッと混乱してきました
です!あなたのgetName()機能で

答えて

4

string getName() 
{ 
    return name; 
} 

返される文字列は、元のコピーです。

const char* ccs = p.m_arg[i]->getName().c_str(); 

式が終了すると、その中間は破棄されます。したがって、c_str()によって返されたポインタを無効にします。 その結果、ccsはダングリングポインタになります。

この作品理由:strは中間ではないので

string str("ok"); 
const char* ckk = str.c_str(); 

です。、それを動作させるこれにあなたのループを変更するには

for(int i = 0 ; i < (int)p.m_arg.size() ; ++i) 
{ 
    string str = p.m_arg[i]->getName() 
    const char* ccs = str.c_str(); 

    size_t ss = strlen(ccs); 
} 

EDIT:これが動作しない理由を

理由:

あなたの新しい質問に答えるために
string* strr = &p.m_arg[i]->getName(); 

は以前と同じです。 getName()は中間を返します。あなたはそれのアドレスを取ってstrrにそれを割り当てます。中間文はステートメントの後で破棄されるため、strrは、最初のケースのようにダングリングポインタになります。

+1

また、 'getName()'は 'std :: string const 'を返します(関数自体も' const'でなければなりません)。式が有効で、関連する文字列のコピーがありません。 – Mat

+0

さらに進んで、 'strlen'にインライン展開することもできます。しかし、 'ss'は決して使用されないので、ループは明らかに不完全です。 – Mysticial

+0

'strlen'もかなり疑わしいです。 'std :: string :: size()'はO(1)ではなくO(n)です。 – MSalters

関連する問題