簡體   English   中英

C++ 套接字 - 客戶端給出分段錯誤 (linux)

[英]C++ Sockets - Client gives segmentation fault (linux)

我創建了一個服務器/客戶端連接。 服務器和客戶端都正確編譯,但是當我運行客戶端時,它給了我一個Segmentation Fault (core dumped)

我不知道我的內存分配做錯了什么。 該程序沒有懸空或任何東西。 我認為我的程序正在寫入內存的只讀部分,或者可能訪問不可用的內存。

如果有人能告訴我錯誤在哪里,我將不勝感激。

客戶端

#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdlib.h>
#include <unistd.h>
using namespace std;

int main() {
    char a;
    int client;
    int portNum = 1500;
    int bufsize = 1024;
    char* buffer = new char (bufsize);
    bool isExit = false;
    char* ip;
    strcpy(ip, "127.0.0.1");

struct sockaddr_in direc;

if ((client = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    cout << "Error creating socket..." << endl;
    exit(0);
}

cout << "Enter # to end call" << endl;
cout << "\t\t\t[s] to begin with" << endl;
cin >> a;

cout << "Socket created successfully..." << endl;
direc.sin_family = AF_INET;
direc.sin_port = htons(portNum);
inet_pton(AF_INET, ip, &direc.sin_addr);

if (connect(client,(struct sockaddr *)&direc, sizeof(direc)) == 0)
    cout << "Connection to the server " << inet_ntoa(direc.sin_addr) << endl;

cout << "Awaiting confirmation from the server..." << endl;
recv(client, buffer, bufsize, 0);

cout << "Response received: " << buffer;
cout << "\nRemember to put an asterisk at the end to send a message * \n Enter # to terminate the connection" << endl;

do {
    cout << "Enter a message: ";
    do {
        cin >> buffer;
        send(client, buffer, bufsize, 0);
        if (*buffer == '#') {
            send(client, buffer, bufsize, 0);
            *buffer = '*';
            isExit = true;
        }
    } while (*buffer != 42);

    cout << "Mensage received: ";
    do {
        recv(client, buffer, bufsize, 0);
        cout << buffer << " ";
        if (*buffer == '#') {
            *buffer = '*';
            isExit = true;
        }

    } while (*buffer != 42);
    cout << endl;

} while (!isExit);
cout << "Connection terminated. END PROGRAM\n\n";
close(client);
return 0;
}

我假設您不需要 server.cpp,因為它一切正常並等待傳入​​連接。

謝謝!

這段代碼有很多問題,但直接和致命的錯誤是:

int bufsize = 1024;
char* buffer = new char (bufsize);

分配 1 個字符並嘗試將bufsize的值存儲到其中。 bufsize太大,因此被截斷為 0。最終結果,緩沖區指向單個字符,而不是 1024 的數組,並且該單個值設置為 0。當您嘗試將bufsize字節讀入緩沖區時,您幾乎可以肯定超出該單個字符並且行為未定義 它很可能會破壞一些其他程序數據(並且可能會在以后引起問題)或寫入無效內存並立即崩潰。

我相信你的意思

int bufsize = 1024;
char* buffer = new char[bufsize];

反而,

char buffer[1024]; 

會做你想做的。 使用sizeof(buffer)代替bufsize 此外,以下通常更可取:

在文件的頂部,就在包含的下面:

#define BUFSIZE 1024

進而

char buffer[BUFSIZE]; 

現在您可以使用BUFSIZEsizeof(buffer) 兩者都在編譯期間解決,因此沒有性能成本。

2018 年附錄:

constexpr int BUFSIZE = 1024;

在現代 C++(C++11 或更高版本)中具有相同的效果,並且沒有#define宏替換的缺點。

這兩個選項的美妙之處在於內存是自我管理的。 char* buffer = new char[bufsize]; 需要在代碼中的某處使用delete[] buffer來放回內存。 而且您必須確保到達該delete[]以防止泄漏。 除非必須,否則不要使用指針和動態分配。

下一個,

char* ip;
strcpy(ip, "127.0.0.1");

分配一個未初始化的指針ip 最有可能的地址 if contains 由堆棧上的任何垃圾組成,並且不指向有效的char數組。 然后“127.0.0.1”被寫入ip所指向的任何內容。 與之前溢出緩沖區末尾的效果類似。

同樣,我們確切地知道ip將指向什么,因此修復很容易:

char * ip = "127.0.0.1";

我更喜歡

char ip[] = "127.0.0.1";

但我沒有理由這樣做。

2018 年附錄:我現在有這樣做的理由。 char * ip = "127.0.0.1"; 在現代 C++ 中是完全非法的。 字符串文字是常量數組,如果使用指針修改字符串文字,將它們分配給非常量指針會導致很多壞處。 在過去,我們只是忽略了這個問題,從來沒有寫過文字。 除非您稍后進行了一些抽象並花費了數天或數周的時間進行調試。 如果有可能發生變異,最好從源頭上解決問題並將文字復制到可變數組中。 如果可以的話,更好的是在整個代碼中保持const 正確

接下來,

recv(client, buffer, bufsize, 0);

有兩個問題:

它丟棄讀取的字節數和返回的錯誤代碼。 程序不知道它是否因為套接字錯誤而讀取任何內容,或者它是否獲得了整個消息、部分消息或更多消息。

這也說明了對 TCP 工作原理的誤解。 TCP 在良好的、定義的消息中不起作用。 寫入套接字的數據可能與其他消息打包到同一個出站數據包中。 它可能會被分成多個在不同時間到達的數據包。 這背后的邏輯超出了 StackOverflow 的范圍。 閱讀 TCP 和流數據。

可是等等! 還有更多!

cin >> buffer;

如果用戶輸入 1024 個或更多字符(不要忘記需要空終止符),即使將buffer固定為預期大小,也會溢出buffer 此外,您不知道輸入了多少字符而不自己計算它們。 痛苦而緩慢。 幸運的是有std::string

std::string outbuf;
cin >> outbuf;

一次解決這兩個問題。 它會調整自身大小並對其內容進行計數。 整潔吧?

send(client, buffer, bufsize, 0);

即使用戶輸入較少,也將發送 1024 字節的數據。 或者更多。 哎呀。 從上面使用outbuf,

send(client, outbuf.c_str(), outbuf.length(), 0);

每次寫入正確數量的字符,但如果您想保留字符串的終止空值,則必須發送outbuf.length() + 1字符。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM