2011-02-16 13 views
2

今日使用されていない、初期化されていないメンバ変数によって引き起こされるが、私は(私はそれが使用された保護だと思う)カナリア点を返す++ Gをオーバーライドし、私のスタックが壊してしまっ明らかに楽しいバグがありました。奇妙なスタックスマッシュ・エラー -

私の問題のクラスは、このでした:

class ClientSendContext : public SendContext 
    { 
     public: 
      ClientSendContext(UdpClient& client); 
      void send(boost::asio::const_buffer buffer); 
     private: 
      boost::asio::ip::udp::endpoint endpoint; 
      UdpClient& client; 
    }; 

事は、クライアント変数は初期化リストで初期化されますが、したではないエンドポイント(それが唯一のエンドポイントに送信するので、それは、ClientSendContextで使用していません、問題ありません)。スマッシュスタックは3回毎に発生しました。テスト(またはそのようなもの)を実行しましたが、私はまったく同じことをしています(スレッドタイミングの問題でなければなりません)。

しかし、できるだけ早く私は、エンドポイントの変数を削除し、それが正常に動作します!どうすればいいの?それは決して使われなかったし、g ++はそれについて私に警告しなかった... Valgrindも静かだった。

(?高い担当者との誰かが私の質問を編集し、タグとしてのスタック・スマッシュまたはそのような何かを追加してくださいでした)

よし、より多くのコードを持つ更新は、ペーストビンに掲載:

http://pastebin.com/xiWx8xjV

すべてのメソッドが呼び出されるべき

。最も内側のsendメソッドは、テンプレート化されたクラスの一部です。 UdpServerがそれを使用するとき、同じsendメソッドがうまくいきます。私はちょうど今ちょうど困っています。

編集:コードは今ここに直接置く:

void doTest(bool& failed) 
{ 
    ReceiveHelper helper(failed); 

    boost::threadpool::pool pool(2); 
    int port = 55600; 
    boost::asio::io_service service; 
    udp::endpoint thisPoint = udp::endpoint(address::from_string("127.0.0.1"), 
      port); 
    udp::endpoint receivePoint; 
    udp::socket socket(service, thisPoint); 
    socket.async_receive_from(boost::asio::buffer(helper.buffer), receivePoint, boost::bind(&ReceiveHelper::handleReceive, 
      &helper, boost::asio::placeholders::error, 
      boost::asio::placeholders::bytes_transferred)); 
    pool.schedule(boost::bind(&boost::asio::io_service::run, &service)); 
    voip::network::client::UdpClient client; 
    client.connect(thisPoint); 
    client.send(1, "Hello!"); 
    boost::this_thread::sleep(boost::posix_time::milliseconds(1)); 
    service.stop(); 
} 

class ReceiveHelper { 
private: 
    bool& failed; 

    public: 
     ReceiveHelper(bool & failed) : failed(failed), buffer() 
     { 

     } 
     boost::array<uint8_t, BUF_SIZE> buffer; 
     void handleReceive(const boost::system::error_code & error, size_t numBytes) 
     { 
      if(numBytes != 8) 
       return; 
      if(std::string((char*)buffer.c_array(), 6) != "Hello!") 
       return; 
      failed = false; 
     } 
}; 

void UdpClient::send(uint8_t handler, std::string message) 
{ <-------------------------------------------------------------------------------------- Canary at this point fails 
    ClientSendContext context(*this); 
    ClientConnection::send(context, handler, message); 
} <-------------------------------------------------------------------------------------- Canary at this point fails 

    void send(SendContext & sendContext, uint8_t handler, std::string & message) 
    { 
     uint8_t *array = new uint8_t[message.size() + 2]; 
     memcpy(array, message.c_str(), message.size()); 
     boost::asio::mutable_buffer buffer(array, message.size() + 2); 
     prepareMessage(handler, buffer); 
     sendContext.send(buffer); 
     delete[] array; 
    } 

    size_t prepareMessage(uint8_t handler, boost::asio::mutable_buffer message) 
    { 
     size_t messageLength = boost::asio::buffer_size(message); 
     uint8_t* data = boost::asio::buffer_cast<uint8_t*>(message); 
     data[messageLength - 1] = network::handler; 
     data[messageLength - 2] = handler; 
     return messageLength; 
    } 

、エラーメッセージ:

*** stack smashing detected ***: ./testclient terminated 
======= Backtrace: ========= 
/lib/libc.so.6(__fortify_fail+0x37)[0x58e9537] 
/lib/libc.so.6(__fortify_fail+0x0)[0x58e9500] 
./testclient(_ZN4voip7network6client9UdpClient4sendEhSs+0x85)[0x46b449] 
./testclient(_ZN4voip4test6client18SuiteTestUdpClient6doTestERb+0x2dd)[0x44c7c1] 
./testclient(_ZNK4voip4test6client18SuiteTestUdpClient17TestClientCanSend7RunImplEv+0x2f)[0x44c957] 
./testclient(_ZN8UnitTest11ExecuteTestINS_4TestEEEvRT_RKNS_11TestDetailsE+0x9a)[0x469551] 
./testclient(_ZN8UnitTest4Test3RunEv+0x23)[0x46920f] 
./testclient(_ZNK8UnitTest10TestRunner7RunTestEPNS_11TestResultsEPNS_4TestEi+0x7c)[0x469b74] 
./testclient(_ZNK8UnitTest10TestRunner10RunTestsIfINS_4TrueEEEiRKNS_8TestListEPKcRKT_i+0x8f)[0x469ddb] 
./testclient(_ZN8UnitTest11RunAllTestsEv+0x53)[0x4697b7] 
./testclient(main+0x9)[0x44ca62] 
/lib/libc.so.6(__libc_start_main+0xfe)[0x5808d8e] 
./testclient[0x44c429] 
======= Memory map: ======== 
00400000-00494000 r-xp 00000000 08:05 150971        /home/max/Documents/c++proj/voip/build/testclient 
00693000-00694000 r--p 00093000 08:05 150971        /home/max/Documents/c++proj/voip/build/testclient 
00694000-00695000 rw-p 00094000 08:05 150971        /home/max/Documents/c++proj/voip/build/testclient 
00695000-00696000 rw-p 00000000 00:00 0 
04000000-04020000 r-xp 00000000 08:05 560792        /lib/ld-2.12.1.so 
04020000-04022000 rw-p 00000000 00:00 0 
0403f000-04045000 rw-p 00000000 00:00 0 
04220000-04221000 r--p 00020000 08:05 560792        /lib/ld-2.12.1.so 
04221000-04222000 rw-p 00021000 08:05 560792        /lib/ld-2.12.1.so 
04222000-04223000 rw-p 00000000 00:00 0 
04223000-04224000 rwxp 00000000 00:00 0 
04a23000-04a24000 r-xp 00000000 08:05 145700        /usr/lib/valgrind/vgpreload_core-amd64-linux.so 
04a24000-04c23000 ---p 00001000 08:05 145700        /usr/lib/valgrind/vgpreload_core-amd64-linux.so 
04c23000-04c24000 r--p 00000000 08:05 145700        /usr/lib/valgrind/vgpreload_core-amd64-linux.so 
04c24000-04c25000 rw-p 00001000 08:05 145700        /usr/lib/valgrind/vgpreload_core-amd64-linux.so 
04c25000-04c2d000 r-xp 00000000 08:05 145715        /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 
04c2d000-04e2c000 ---p 00008000 08:05 145715        /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 
04e2c000-04e2d000 r--p 00007000 08:05 145715        /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 
04e2d000-04e2e000 rw-p 00008000 08:05 145715        /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so 
04e2e000-04e46000 r-xp 00000000 08:05 557639        /lib/libpthread-2.12.1.so 
04e46000-05045000 ---p 00018000 08:05 557639        /lib/libpthread-2.12.1.so 
05045000-05046000 r--p 00017000 08:05 557639        /lib/libpthread-2.12.1.so 
05046000-05047000 rw-p 00018000 08:05 557639        /lib/libpthread-2.12.1.so 
05047000-0504b000 rw-p 00000000 00:00 0 
0504b000-05133000 r-xp 00000000 08:05 656172        /usr/lib/libstdc++.so.6.0.14 
05133000-05332000 ---p 000e8000 08:05 656172        /usr/lib/libstdc++.so.6.0.14 
05332000-0533a000 r--p 000e7000 08:05 656172        /usr/lib/libstdc++.so.6.0.14 
0533a000-0533c000 rw-p 000ef000 08:05 656172        /usr/lib/libstdc++.so.6.0.14 
0533c000-05351000 rw-p 00000000 00:00 0 
05351000-053d3000 r-xp 00000000 08:05 560787        /lib/libm-2.12.1.so 
053d3000-055d2000 ---p 00082000 08:05 560787        /lib/libm-2.12.1.so 
055d2000-055d3000 r--p 00081000 08:05 560787        /lib/libm-2.12.1.so 
055d3000-055d4000 rw-p 00082000 08:05 560787        /lib/libm-2.12.1.so 
055d4000-055e9000 r-xp 00000000 08:05 521495        /lib/libgcc_s.so.1 
055e9000-057e8000 ---p 00015000 08:05 521495        /lib/libgcc_s.so.1 
057e8000-057e9000 r--p 00014000 08:05 521495        /lib/libgcc_s.so.1 
057e9000-057ea000 rw-p 00015000 08:05 521495        /lib/libgcc_s.so.1 
057ea000-05964000 r-xp 00000000 08:05 557476        /lib/libc-2.12.1.so 
05964000-05b63000 ---p 0017a000 08:05 557476        /lib/libc-2.12.1.so 
05b63000-05b67000 r--p 00179000 08:05 557476        /lib/libc-2.12.1.so 
05b67000-05b68000 rw-p 0017d000 08:05 557476        /lib/libc-2.12.1.so 
05b68000-05b6d000 rw-p 00000000 00:00 0 
05b6d000-05f6d000 rwxp 00000000 00:00 0 
05f6d000-05f6e000 ---p 00000000 00:00 0 
05f6e000-0676e000 rw-p 00000000 00:00 0 
0676e000-0676f000 ---p 00000000 00:00 0 
0676f000-06f6f000 rw-p 00000000 00:00 0 
06f6f000-06f70000 ---p 00000000 00:00 0 
06f70000-07770000 rw-p 00000000 00:00 0 
07770000-07771000 ---p 00000000 00:00 0 
07771000-07f71000 rw-p 00000000 00:00 0 
38000000-381fc000 r-xp 00200000 08:05 145710        /usr/lib/valgrind/memcheck-amd64-linux 
383fb000-383fe000 rw-p 003fb000 08:05 145710        /usr/lib/valgrind/memcheck-amd64-linux 
383fe000-3927e000 rw-p 00000000 00:00 0 
402001000-403272000 rwxp 00000000 00:00 0 
403272000-403274000 ---p 00000000 00:00 0 
403274000-403374000 rwxp 00000000 00:00 0 
403374000-403376000 ---p 00000000 00:00 0 
403376000-40583e000 rwxp 00000000 00:00 0 
40583e000-405840000 ---p 00000000 00:00 0 
405840000-405940000 rwxp 00000000 00:00 0 
405940000-405942000 ---p 00000000 00:00 0 
405942000-405946000 rwxp 00000000 00:00 0 
405946000-405948000 ---p 00000000 00:00 0 
405948000-405a48000 rwxp 00000000 00:00 0 
405a48000-405a4a000 ---p 00000000 00:00 0 
405a4a000-405a4e000 rwxp 00000000 00:00 0 
405a4e000-405a50000 ---p 00000000 00:00 0 
405a50000-405b50000 rwxp 00000000 00:00 0 
405b50000-405b52000 ---p 00000000 00:00 0 
405b52000-405b5a000 rwxp 00000000 00:00 0 
405b5a000-405b5c000 ---p 00000000 00:00 0 
405b5c000-405c5c000 rwxp 00000000 00:00 0 
405c5c000-405c5e000 ---p 00000000 00:00 0 
405c5e000-405c62000 rwxp 00000000 00:00 0 
7feffd000-7ff001000 rwxp 00000000 00:00 0 
7fffb9f36000-7fffb9f57000 rw-p 00000000 00:00 0       [stack] 
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 
+4

ほとんどのエンドポイント変数なしのこのクラスの大きさの変化は、他のコードでは、まだ既存のバグを隠します。このクラスのインスタンスを作成するコードのオーバーランを確認します。 – Erik

+0

@Erik Grumble ..1マイル離れているのが見えているはずです。もちろん、そうでなければなりません:pスタックオーバーランをチェックするツールはありますか? – Max

+0

メソッド内のコードによってスタックが壊れてしまいます。クラス宣言ではありません。あなたは間違ったコードを投稿しました。 –

答えて

1

このエラーがある(ほとんど常に)は、前記以外のアレイ/ベクトルに複数の要素を付加することによって引き起こされarray/vectorは持っていると宣言されています。したがって、コード内のすべてのcharおよびuint8配列に特に注意を払います。

ダンプが深く、それが最速のソリューションではありません使用して単なる人間とデバッグのために意味をなさない++ LinuxのCを理解して誰かのために意味をなすかもしれませんが。

私は古い学校のアプローチが好き:印刷フラグは、プログラムが例外なしに行く何点まで表示します。このように問題のアレイを非常に迅速に分離することができます。一例として

、私はこのコードで正確に同じ問題を抱えていた。

奇妙なことは、私のように宣言しBUFOUTに12個の文字を持っていた文字列を(割り当てられたときにエラーが発生しなかったということでした
std::string GetTimeStringFromDump(unsigned char *bufDumpIn, int startDate) { 
    unsigned char bufOut[6]; 
    for (int counter02=0;counter02<12;counter02++) { 
    bufOut[counter02] = bufDumpIn[counter02+startDate]; 
    } 
    std::string unixTimeOut = GetTimeStringNew(bufOut); 
    std::cout << "UnixTimeOUT: " << unixTimeOut << std::endl; 
    return unixTimeOut; 
} 

6要素)を有するのではなく、それにもかかわらず

return unixTimeOut; 

た後、私は

unsigned char bufOut[12]; 
に宣言を変更

となり、問題は解決しました。

+2

ちょっとトニー、答えてくれてありがとう。なぜ私は戻ってくるときにエラーが発生するのかを明らかにすることができると思う - 多くのコンパイラは、異なるポイントで既知のパディング値を追加する。リターンポイントで値がチェックされます。とにかく、私のエラーはスタック上の値を参照するコールバックによって引き起こされました。このコールバックは、(バグのために)遅れて起動し、スタックを破損させました。 :) – Max

+0

@Maxそうかもしれない。洞察力のおかげで、私は多くの人がこの種のエラーをデバッグしながら、これらの内部のより良い理解の恩恵を受けると確信しています。大きな質問は、upv​​oted取得! :) –