gpt4 book ai didi

c - 在 C 中,为什么从套接字读取会导致 printw 出现段错误?

转载 作者:太空宇宙 更新时间:2023-11-04 03:49:29 25 4
gpt4 key购买 nike

我正在编写一个连接到服务器的程序,获取发送的数据并将其显示到屏幕上。我正在使用 ncurses 为程序创建 UI。我初始化屏幕,连接到服务器,读取套接字,打印输出,关闭套接字,结束屏幕,这给了我一个段错误。

如果我跳过套接字读取,则不会出现错误并显示屏幕;但是,在它显示之前有一个暂停。我想知道这是否与我的套接字是非阻塞的事实有关?

我有 3 个文件,main.c socket.cscreen.c。我将截断所需信息的文件。

ma​​in.c

#include "socket.h"
#include "screen.h"

int main(int argc, char *argv[]){
screenInit();

socketConnect(argv[1], argv[2]);
sleep(1);

char buffer[1024];
socketRead(buffer, sizeof buffer);//commenting this out lets the screen display
screenDraw(buffer);

socketClose();
screenEnd();

return 0;
}

套接字.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>

int sockfd;

int socketRead(char *output, int length){
memset(output, 0, length);

char buffer[1024];
memset(buffer, 0, sizeof buffer);

for(;;){
char *ch;

if(recv(sockfd, ch, 1, 0) == -1)
return -1;

if(strlen(buffer)+1 == sizeof buffer)
return -2;

strcat(buffer, ch);
if(*ch == '\n'){
if(strlen(buffer)+1 <= length){
strcpy(output, buffer);
return 0;
}else{
return -3;
}
}
}
}

int socketConnect(char *host, char *port){
//sockfd gets set here
fcntl(sockfd, F_SETFL, O_NONBLOCK);
return 0;
}

void socketClose(){
close(sockfd);
}

屏幕.c

#include <ncurses.h>

void screenInit(){
initscr();
cbreak();
noecho();
}

void screenDraw(char *string){
printw("%s", string);
refresh();
getch();
}

void screenEnd(){
endwin();
}

这是来自 gdb

的堆栈
#0 0x00007ffff7647caa in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#1 0x00007ffff7649191 in ?? () from /lib/x86_64-linux-gnu/libc.so.6
#2 0x00007ffff764b580 in malloc() from /lib/x86_64-linux-gnu/libc.so.6
#3 0x00007ffff7bce2de in _nc_printf_string () from /lib/x86_64-linux-gnu/libncurses.so.5
#4 0x00007ffff7bc93ef in vwprintw () from /lib/x86_64-linux-gnu/libncurses.so.5
#5 0x00007ffff7bca0e9 in printw () from /lib/x86_64-linux-gnu/libncurses.so.5
#6 0x000000000040111f in screenDraw ()
#7 0x0000000000400d56 in main ()

如果出于某种原因与问题有关,我想我也会在这里添加我的 Makefile。

生成文件

objects = main.o socket.o screen.o

program: $(objects)
cc -Wall -o program $(objects) -lncurses

.PHONY: clean
clean:
@-rm -f program

最佳答案

您在此处的 socketRead() 中出错:

char *ch;

if(recv(sockfd, ch, 1, 0) == -1)
return -1;

ch 只是一个指针,您从未分配内存来在其中存储内容 - 您所拥有的只是一个未初始化的指针。您不能使用它并将其传递给 recv,因为 recv 将尝试写入未定义的位置。这就是您的程序崩溃的原因。

我想你想在这里使用 buffer:

if (recv(sockfd, buffer, sizeof buffer, 0) == -1) { ... }

或者,您可以在使用前让 ch 指向一个有效的位置:

ch = buffer;
if (recv(sockfd, ch, sizeof buffer, 0) == -1) { ... }

但是请注意,在这种情况下您不能使用 sizeof ch,因为那样会产生 char * 的大小。

如果您想明确地为空终止字节留出空间,则使用 sizeof(buffer) - 1:

if (recv(sockfd, buffer, sizeof buffer, 0) == -1) { ... }

这些行也是错误的,原因相同:您从未初始化 ch

strcat(buffer, ch);
if (*ch == '\n') {

请注意,recv(sockfd, buffer, sizeof(buffer)-1, 0) 将读取最多 sizeof(buffer)-1 字节的 block 。您的代码传达了您想要一个字符一个字符地读取它的想法;在这种情况下,您可能希望将 ch 设为 char 而不是 char *。在这种情况下,您只需在调用 recv 时使用运算符的地址,因为 recv 需要一个指针:

if (recv(sockfd, &ch, 1, 0) == -1)

但是当然,您不能将 strcat 与 char 一起使用(strcat 期望以 null 结尾的字符序列),而不是 if (* ch == '\n'),你必须使用 if (ch == '\n')

关于c - 在 C 中,为什么从套接字读取会导致 printw 出现段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21891959/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com