2015-07-10 72 views
1

我创建了一个服务器/客户端连接。服务器和客户端都编译正确,但是当我运行客户端,它给了我一个Segmentation Fault (core dumped)C++套接字 - 客户端给出分段错误(linux)

我不知道我在做什么我的内存分配有问题。该程序不是悬挂或任何东西。我认为我的程序正在写入内存的只读部分,或者正在访问不可用的内存。

如果任何人都可以知道错误在哪里,我会非常感激。

client.cpp

#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,因为这一切都很好,并等待传入​​连接。

谢谢!

+2

'char * ip; strcpy(ip,“127.0.0.1”);'永远不会分配任何指针指向的存储空间,永远不会指向任何内容,然后将数据复制到该未定义的区域。 KABOOOM! – user4581301

+0

...和'char * buffer = new char(bufsize);'不是你想象的那样('()[]')。而你恰好有0'delete []'。 ......“我不知道我在做什么,我的记忆分配有问题。”一切。任何地方都没有正确的分配。 – deviantfan

+0

为什么不直接写'char * ip =“127.0.0.1”;' – Barmar

回答

5

有许多与此代码的问题,而是直接和致命的错误是:

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]; 

会做你想要什么。而不是bufsize,请使用sizeof(buffer)。另外下面的往往是最好:

最多在文件的顶部,右侧下包括:

#define BUFSIZE 1024 

然后

char buffer[BUFSIZE]; 

现在你可以使用BUFSIZEsizeof(buffer)。两者都在编译期间解决,因此不存在性能成本。

这两个选项的优点是内存是自我管理的。 char* buffer = new char[bufsize];需要代码中的某个地方使用delete[] buffer来恢复内存。你必须确保你能达到delete[]。除非必须,否则不要使用指针和动态分配。

接下来,

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

分配一个指针,ip指向任何废话正好是在栈上。然后将“127.0.0.1”写在ip指向的任何事情上。与先前超出缓冲区结尾的效果相同。

再次,我们确切地知道IP会在点,所以解决方法是简单的:

char * ip = "127.0.0.1"; 

我喜欢

char ip[] = "127.0.0.1"; 

,但我没有理由这样做。

接下来,

recv(client, buffer, bufsize, 0); 

有两个问题:

它丢弃读取的字节数和错误代码返回。程序不知道是否由于套接字错误或者是否收到了整个消息而读取任何内容。

这也表明了对TCP工作原理的误解。 TCP在很好的,定义的数据包中不起作用。写入套接字的数据可能会与其他数据一起打包到同一个出站消息中。它可能分成多个数据包并在不同的时间到达。背后的逻辑超出了StackOverflow的范围。做一些关于TCP和流数据的阅读。

但是等等!还有更多!

cin >> buffer; 

会溢出buffer即使固定于预期的大小,如果用户键入1025个或更多字符。此外,您不知道输入了多少个字符而没有自己计算。痛苦而缓慢。幸运的是有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字符。

+0

哇,这就是我所说的详细而详尽的答案。 +1,完全当之无愧! –