2

Before I get blasted on opening another question, this question is related to another question that I opened a few days ago:

C++ Program Always Crashes While doing a std::string assign

After investigating further based on some of the answers I came up with more questions and more information that may help debug the issue.

So here goes...

The Code in Question:

bool peopleSProtocol::SignalProtocolCreated(BaseProtocol *pProtocol,
        Variant customParameters) {

   LOG("peopleSProtocol::SignalProtocolCreated");

   SetOutboundConnectParameters(customParameters);

   // Tie up the peopleSProtocol Instance to the BaseOutboundStream Instance.
   BaseClientApplication *pApplication = ClientApplicationManager::FindAppByName("peoplestreamer");

   std::string lStreamName;
   printf("1b [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str()); // line 217

   SetApplication(pApplication); // line 218

   printf("1c [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str()); // line 219

   BaseRTAppProtocolHandler *pProtocolHandler = (BaseRTAppProtocolHandler *)pApplication->GetProtocolHandler(PT_OUTBOUNDRT);

   printf("1d [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());

   uint32_t protocolId = customParameters["customParameters"]["outboundRTProtocolId"];
   uint32_t streamId = customParameters["customParameters"]["streamId"];

   printf("1d [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());

   BaseOutboundStream *lpBaseOutboundStream = (BaseOutboundStream*)pProtocolHandler->FindByProtocolIdById(protocolId,streamId);

   printf("1e [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());

   RegisterOutboundStream(lpBaseOutboundStream);

   printf("2 [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());

   // Get the address of our peer (the RT peer, NOT the peopleS peer)...

   int32_t lRTClientFd = lpBaseOutboundStream->GetProtocol()->GetIOHandler()->GetFd();

   struct sockaddr_in lPeerAddressStruct;
   int lPeerLength = sizeof(lPeerAddressStruct);
   getpeername(lRTClientFd,(sockaddr*)&lPeerAddressStruct,(socklen_t*)&lPeerLength);

   string lPeerIpAddressString = inet_ntoa(lPeerAddressStruct.sin_addr);

   uint16_t lPeerPort = ntohs(lPeerAddressStruct.sin_port);

   printf("3 [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());

   // Get the name of the file in accordance with the RT spec...

   GetStreamName(STR(M_INVOKE_PARAM(customParameters,1)), lStreamName); // line 247  
   return SendPlayCommand(lStreamName,lPeerIpAddressString,lPeerPort);
}

bool peopleSProtocol::GetStreamName(const char* pRawPath, std::string &pStreamName)
{
   vector<string> parts = split(pRawPath,"/"); // line 260
   pStreamName = parts.back(); // line 261

   parts = split(pStreamName.c_str(),":");
   pStreamName = parts.back();
   return true;
}

#define ADD_VECTOR_END(v,i) (v).push_back((i))

vector<string> split(string str, string separator) {
    vector<string> result;

    string::size_type position = str.find(separator);
    uint32_t separatorLength = separator.length();

    while (position != str.npos) {
        string temp = str.substr(0, position);
        ADD_VECTOR_END(result, temp);
        str = str.substr(position + separatorLength);
        position = str.find(separator);
    }
    ADD_VECTOR_END(result, str);
    return result;
}

The GDB backtrace:

(gdb) b 217
Breakpoint 3, peopleSProtocol::SignalProtocolCreated (this=0x3c52020, pProtocol=<value optimized out>, customParameters=@0x413f9eb0) at peopleRTstreamer/src/peoplesprotocol.cpp:217
217    printf("1b [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());
(gdb) p lStreamName 
$1 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x3c52020 "\220R̪�*"}}
(gdb) c
[DEBUG] cpeopleTcpConnection - Connected to 127.0.0.1:37255
[DEBUG] cpeopleTcpConnection - Connected from server address : 127.0.0.1
[New Thread 1096964416 (LWP 10941)]
Breakpoint 4, peopleSProtocol::SignalProtocolCreated (this=0x3c52020, pProtocol=<value optimized out>, customParameters=@0x413f9eb0) at peopleRTstreamer/src/peoplesprotocol.cpp:218
218    SetApplication(pApplication);
(gdb) p lStreamName 
$2 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x2abbad098e78 ""}}
(gdb) c
Breakpoint 5, peopleSProtocol::SignalProtocolCreated (this=0x3c52020, pProtocol=<value optimized out>, customParameters=@0x413f9eb0) at peopleRTstreamer/src/peoplesprotocol.cpp:219
219    printf("1c [%d] [%s]", (int) lStreamName.size(), lStreamName.c_str());
(gdb) p lStreamName 
$3 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x2abbad098e78 ""}}
(gdb) c
[New Thread 1097099584 (LWP 11010)]
1b [0] []1c [0] []1d [0] []1d [0] [][DEBUG] peopleStreamingServer.RTServer - Opening connection from 127.0.0.1
[DEBUG] peopleStreamingServer.RTServer - Using server IP address 127.0.0.1
Breakpoint 6, peopleSProtocol::SignalProtocolCreated (this=0x3c52020, pProtocol=<value optimized out>, customParameters=@0x413f9eb0) at peopleRTstreamer/src/peoplesprotocol.cpp:247
247    GetStreamName(STR(M_INVOKE_PARAM(customParameters,1)), lStreamName);
(gdb) p lStreamName 
$4 = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x2abbad098e78 ""}}
(gdb) c
Breakpoint 7, peopleSProtocol::GetStreamName (this=0x3c52020, pRawPath=0x3c40808 "RT://127.0.0.1/mp4:popeye.mp4", pStreamName=@0x413f9e10) at peopleRTstreamer/src/peoplesprotocol.cpp:260
260    vector<string> parts = split(pRawPath,"/");
(gdb) p pStreamName 
$5 = (string &) @0x413f9e10: {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 
    _M_p = 0x2abbad098e78 ""}}
(gdb) c
*** glibc detected *** /home/ml01/t-live/TEngine/StreamingServer/.libs/peoplestreamingserver: free(): invalid pointer: 0x00002abbad098e60 ***

======= Backtrace: =========
/lib64/libc.so.6[0x3560871634]
/lib64/libc.so.6(cfree+0x8c)[0x3560874c5c]
/home/ml01/t-HEAD/gcc/4.2.4/lib/../lib64/libstdc++.so.6(_ZNSs6assignERKSs+0x90)[0x2abbace3fd20]
/home/ml01/usr/local/lib/RTserver/libpeopleRTstreamer.so(_ZN12peopleSProtocol13GetStreamNameEPKcRSs+0x9a)[0x2aaaaaabd16a]
/home/ml01/usr/local/lib/RTserver/libpeopleRTstreamer.so(_ZN12peopleSProtocol21SignalProtocolCreatedEP12BaseProtocol7Variant+0x2e4)[0x2aaaaaabd894]
/home/ml01/usr/local/lib/RTserver/libpeopleRTstreamer.so(_ZN12TCPConnectorI12peopleSProtocolE7OnEventER11epoll_event+0x1a6)[0x2aaaaaabf046]
/home/ml01/t-HEAD/cRTserver/20091229/lib/libthelib.so(_ZN16IOHandlerManager5PulseEv+0x4a6)[0x2abbad425620]
/home/ml01/usr/local/lib/libpeopleRT.so.0(_ZN3people15cRTServerLoop19RTProtocolHandlerEv+0x55)[0x2abba2d2df45]
/home/ml01/usr/local/lib/libpeopleRT.so.0(_Z19HandleTrafficThreadPv+0x9)[0x2abba2d2e009]
/home/ml01/t-HEAD/glib/2.18.0/lib/libglib-2.0.so.0[0x2abbabc84394]
/lib64/libpthread.so.0[0x35614062f7]
/lib64/libc.so.6(clone+0x6d)[0x35608d1b6d]

(gdb) where
#0  0x0000003560830155 in raise () from /lib64/libc.so.6
#1  0x0000003560831bf0 in abort () from /lib64/libc.so.6
#2  0x000000356086a38b in __libc_message () from /lib64/libc.so.6
#3  0x0000003560871634 in _int_free () from /lib64/libc.so.6
#4  0x0000003560874c5c in free () from /lib64/libc.so.6
#5  0x00002abbace3fd20 in std::string::assign (this=0x413f9e10, __str=<value optimized out>) at /home/ml01/ThirdParty/sources/gcc-4.2.4/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/basic_string.h:238
#6  0x00002aaaaaabd16a in peopleSProtocol::GetStreamName (this=<value optimized out>, pRawPath=0x3c40808 "RT://127.0.0.1/mp4:popeye.mp4", pStreamName=@0x413f9e10)
    at /home/ml01/t-HEAD/gcc/4.2.4/lib/gcc/x86_64-pc-linux-gnu/4.2.4/../../../../include/c++/4.2.4/bits/basic_string.h:491
#7  0x00002aaaaaabd894 in peopleSProtocol::SignalProtocolCreated (this=0x3c52020, pProtocol=<value optimized out>, customParameters=@0x413f9eb0) at peopleRTstreamer/src/peoplesprotocol.cpp:247
#8  0x00002aaaaaabf046 in TCPConnector<peopleSProtocol>::OnEvent (this=0x3c40aa0, event=<value optimized out>) at /home/ml01/t-HEAD/cRTserver/20091229/include/cRTserver/netio/epoll/tcpconnector.h:90
#9  0x00002abbad425620 in IOHandlerManager::Pulse () at /home/ml01/ThirdParty/sources/cRTserver/sources/thelib/src/netio/epoll/iohandlermanager.cpp:260
#10 0x00002abba2d2df45 in people::cRTServerLoop::RTProtocolHandler (this=0x3c4c180) at src/RTServerLoop.cpp:77
#11 0x00002abba2d2e009 in HandleTrafficThread (ipData=0x60bc) at src/RTServerLoop.cpp:39
#12 0x00002abbabc84394 in g_thread_create_proxy (data=0x3c4e060) at gthread.c:635
#13 0x00000035614062f7 in start_thread () from /lib64/libpthread.so.0
#14 0x00000035608d1b6d in clone () from /lib64/libc.so.6

So to explain the above, the crash is occuring on line 261 (see comments in code for line numbers) during the string assign. For some reason it tries to free invalid memory, but I'm not sure why? The address it tries to free is not the address of what I thought was the empty string assigned on line 217 (_M_p = 0x3c52020 gets set to _M_p = 0x2abbad098e78 i.e. the empty string) but some other address not too far off.

Any ideas what could be causing this issue? I was wondering if this could be an optimization issue since it does not occur in -O0 and I have ran the code through a battery of tests to try and find a whole slew of memory corruption issues that may cause this weird behavior and ....came up empty handed!

Another interesting note is that if I set std::string lStreamName = ""; instead of std::string lStreamName; the program no longer crashes??? Any Ideas what could cause this? Why would a simple initialization of this string eliminate the crash?

Thanks!

4

2 回答 2

2

如果不能保证 split 不会返回空向量,我会添加一个检查它是否为空。否则,将空向量的 back() 分配给字符串可能会导致您收到的行为。

bool GetStreamName(const char* pRawPath, std::string& pStreamName)
{
    std::vector<std::string> parts = split(pRawPath,'/'); // line 260
    if( parts.size() == 0 )
    {
        cout << "Cannot parse '" << pRawPaths << "'" << endl;
        return false;
    }
    pStreamName = parts.back(); // line 261

    parts = split(pStreamName.c_str(),':');
    pStreamName = parts.back();
    return true;
}
于 2010-02-23T13:32:53.920 回答
0

您应该尝试使用一个独立的示例来重现崩溃。使用您提供给我们的信息,我测试了以下代码。

请注意,我需要一个split函数。不知道你用了什么,我从这个问题中拿了一个。如果您使用boost::splitsplit自己编写的功能,请将其包含在您的问题中。

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

bool GetStreamName(const char* pRawPath, std::string& pStreamName)
{
    std::vector<std::string> parts = split(pRawPath,'/'); // line 260
    pStreamName = parts.back(); // line 261

    parts = split(pStreamName.c_str(),':');
    pStreamName = parts.back();
    return true;
}

int main()
{
    std::string streamName;
    GetStreamName("/some:weird/path/of:x/a:/stream:foo", streamName);
    std::cout << streamName << std::endl;
}

尝试运行此代码(使用 -O2,使用您能想到的任何 g++ 优化,使用 valgrind 等),看看它是否再次崩溃。

使用一个简单的、独立的示例,您可以确定崩溃的根源是您的代码中的错误还是其他任何错误(例如冲突的 C++ 库,就像您之前的问题中一样)。

于 2010-02-23T13:18:51.893 回答