2

OpenGL で使用するために、GLSL 頂点/フラグメント シェーダー ソースを const char* 配列に読み込もうとしています。私がそれを行うために使用している機能は

const char* loadSource(const char* path)
{
   string line;
   stringstream output;
   ifstream source(path);

   if(source.is_open())
   {
       while(source.good())
       { 
           getline(source, line);
           output << line << endl;
       }
       source.close();
   }

   return output.str().c_str();
}

ソース入力は、最初の呼び出しで正常に機能します。ただし、2 番目のソースを呼び出すと、最初のソースが「破損」します (両方の呼び出しが 1 つの関数のスコープ内にあります)。

const char* vs_source = loadSource("vertex.vert");  // vs_source loads fine
const char* fs_source = loadSource("fragment.frag"); // fs_source loads fine. vs_source is terminated sooner than after previous call.

注: vs_source を *.cpp ファイルに直接コーディングして、両方のシェーダーをコンパイルしようとしました。これは、loadSource 関数でばかげたことをしているに違いないという事実を示しています。

質問:テキスト入力のこのような奇妙な動作の原因は何ですか?

4

3 に答える 3

3

関数から結果を返すとき、ぶら下がり参照を作成します。

return output.str().c_str();

式の最後でstd::string、ストリームから取得された一時が破棄され、返されたメモリが無効になります。配列へのアクセスは未定義の動作になります。

ところで、この入力へのアプローチは間違っています:

while(source.good())
{ 
    getline(source, line);
    output << line << endl;
}

読み取り後は、読み取りが成功したことを常に確認する必要があります。

while (std::getline(source, line)) {
    output << line << '\n';
}

また、使用しないでくださいstd::endl。本当にストリームをフラッシュするつもりなら、std::flush. 最後に、同じ効果をはるかに簡単に、おそらくより速く得ることができます。

out << source.rdbuf();

... そしてもちろん、(extra ではなく)outとして宣言する必要があります。std::ostringstreamo

于 2013-08-25T01:37:33.660 に答える
1

テキスト入力のこのような奇妙な動作の原因は何ですか?

return output.str().c_str();

loadSource関数の戻り値outputがスコープ外になると、ローカル変数を指すポインターが返されvs_source/fs_sourceます。vs_source/fs_source未定義の動作をするためのアクセス。

問題を解決するには、代わりに std::string を返すことができます。

std::string loadSource(const char* path)
{
    //...
    return output.str();
}

std::string vs_source = loadSource("vertex.vert");  // vs_source loads fine
std::string fs_source = loadSource("fragment.frag"); 
于 2013-08-25T01:37:29.703 に答える
1

なぜ誰もがこのようにファイルを 1 行ずつ読み取ることに固執するのでしょうか? ファイル全体を一度にロードするだけです。それは本当に簡単です:

std::string LoadFile(const std::string &filename)
{
    std::ifstream file (filename.c_str());
    if (file) {
        std::ostringstream os;
        os << file.rdbuf();
        return os.str();
    }
    else {
        // error
    }
}
于 2013-08-25T02:00:02.333 に答える