Не могу понять, почему этот код вызывает SIGSEGV при отправке данных пакета

0

Я пишу какой-то сетевой код на Android, используя сокеты POSIX, но я получаю странный SIGSEGV (Signal 11, code 1), когда я звоню в sento. Я использовал трассировку Надгробной плиты, чтобы определить, какая она есть, но, честно говоря, я не вижу, что с ней не так.

Ссылки на i_Socket и i_Server были успешными до этого конкретного фрагмента. Я должен также упомянуть, что строки поступают из маршалированных строк из Mono/Unity.

// Set client informaion
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // We don't care IPv4 or IPv6
hints.ai_socktype = SOCK_DGRAM; // UDP Datagram packets

// Resolve server domain name
int res = getaddrinfo(server, TFTP_PORT, &hints, &i_ServerList);

// Check if we got a valid result
if (res != 0) {
    // Report error
    if (res == EAI_SYSTEM) 
        StreamingVideoPluginError("getaddrinfo");
    else {
        std::stringstream str;
        str << "error in getaddrinfo: " << gai_strerror(res);
    }
    return 1; // No such host
}

// Loop through all entries and bind to the first one we can
bool didBind = false;
for (auto i_Server = i_ServerList; i_Server != nullptr; i_Server = i_Server->ai_next) {
    // Try create the socket
    if ((i_Socket = socket(i_Server->ai_family, i_Server->ai_socktype, i_Server->ai_protocol)) == -1) {
        // Display error
        StreamingVideoPluginError("client: socket creation failure");
        i_Socket = -1; // Reassert invalid socket
        continue;
    }
    else {
        // Binded a socket
        didBind = true;
        break;
    }
}

// Check if we could bind to a server
if (!didBind) {
    StreamingVideoPluginError("Failed to bind to a server.");
    return 2;
}

// Set socket options
struct timeval tv;
memset(&tv, 0, sizeof (struct timeval));
tv.tv_sec = 5; // 5 second timeout
if (setsockopt(i_Socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv) == -1)
{
    std::stringstream str;
    str << "client: could not set timeout. errno =" << errno;
    StreamingVideoPluginError(str.str());
    return 3;
}


// Make the initial TFTP request
char tftp_buffer[512 + 4];
// Set the opcode to be read request
int packetLength = 0;
tftp_buffer[0] = 0;                   
tftp_buffer[1] = TFTP_RRQ;
packetLength = 2;


// Place filename
memcpy(&tftp_buffer[packetLength],tftpFileName, strlen(tftpFileName));
packetLength += strlen(tftpFileName);
tftp_buffer[packetLength] = 0; packetLength++;

// Set transfer type to be octet
memcpy(&tftp_buffer[packetLength], TRANSFER_TYPE, strlen(TRANSFER_TYPE));
packetLength += strlen(TRANSFER_TYPE);
tftp_buffer[packetLength] = 0; packetLength++;

std::stringstream str;
str << "Value of packetLength =" << packetLength;
StreamingVideoPluginLog(str.str());



// Send the TFTP request
if (sendto(i_Socket, tftp_buffer, packetLength, 0, i_Server->ai_addr, i_Server->ai_addrlen) == -1) {
    // Could not send TFTP request
    StreamingVideoPluginError("client: could not send tftp request.");

    return 4;
}

Вот вывод от NDK-Stack

signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 00000018
Stack frame #00  pc 0001e544  /data/app-lib/com.imersia-2/PLUGINNAME.so (ImersiaTftpDa
taSource::Init(char const*, char const*)+1292)
Stack frame #01  pc 0001d428  /data/app-lib/NOPENOPENOPE-2/PLUGINNAME.so (std::priv::_S
TLP_alloc_proxy<char*, char, std::allocator<char> >::~_STLP_alloc_proxy()+16)

addr2line обвиняет

C:/NVPACK/android-ndk-r10/sources/cxx-stl/stlport/stlport/stl/_alloc.h:472
  • 0
    просто любопытно, каково значение packetLength перед вызовом sendto() ?
  • 0
    Вам не нужны все memcpy()'s . Вы можете использовать sendmsg() чтобы сделать сборку-запись, или просто написать фрагменты непосредственно от того места, где они находятся по одному. Не перемещайте данные, если нет необходимости. Вы получаете этот SIGSEGV изнутри sendto() или при вычислении аргументов, например i_Server->ai_addr ? Обратите внимание: вы должны сравнивать результат sendto() со значением -1 и немедленно проверять / отображать errno или strerror[errno] или вызывать perror() .
Показать ещё 3 комментария
Теги:
networking
sockets

1 ответ

0
Лучший ответ

Выяснил этот вопрос. Я случайно перезаписывал i_Server внутри цикла for.

for (auto i_Server = i_ServerList; i_Server != nullptr; i_Server = i_Server->ai_next) {

должно быть

for (i_Server = i_ServerList; i_Server != nullptr; i_Server = i_Server->ai_next) {

Ещё вопросы

Сообщество Overcoder
Наверх
Меню